汎用モジュールを使用した論理データベースからの項目取得


## １．固定資産の論理データベースからの一部項目の取得
以前BWのプロジェクトで固定資産のデータをビジネスコンテンツのデータソースで取得し、足りないデータをEXIT内で取得する必要がありまして論理データベースから汎用モジュールを使用して取得しました。

 一応、固定資産を担当している方に「取得したい項目をどうとればいいのか？」確認したところ「固定資産の論理データベースから取れるよ」と回答が。
 
 論理データベースはほとんど経験が無いのでトランザクションコード：SE36(またはSLDB)で実際に見てみると取得したい項目はどうやら論理データベースの中で計算されものらしい……(他の項目は透過テーブルなのに…)
![ADA1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110632/eff3645e-7bf8-36da-feff-23269272d928.png)

![ADA2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110632/88164710-33a8-6b4d-5845-2e1c92321e58.png)

## ２．汎用モジュール：LDB_PROCESS
論理データベースを調べてみると「論理データベースとは、データを取得してデータをアプリケーションプログラムに利用させる特別なABAP プログラムです。」と書いてある。

https://help.sap.com/doc/saphelp_nw70/7.0.12/ja-JP/9f/db9b5e35c111d1829f0000e829fbfe/content.htm?no_cache=true

ABAPならデバッグで追っかけて必要箇所を特定してそれだけEXIT内に記述しよう！！と思いソースコードを見てみましたが複雑…(時間がなかったため追っかけるのは諦めました…)

そこで上記ページに書いてある汎用モジュール：LDB_PROCESSを使用して必要な項目を取得する事に。

汎用モジュールを見てみるとインポートパラメータに論理データベースIDとテーブルパラメータのコールバックを最低限設定してあげれば動きそう。
![汎用モジュール1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110632/30350be0-b204-eb30-eef9-b6afa076a2cd.png)

![汎用モジュール2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110632/f12e8a7b-6574-528f-0382-1d7f7a5571dc.png)


コールバック？あと値を受けるようなパラメータがないなと思い調べてみると汎用モジュール単体では値が取れないらしい。

https://help.sap.com/doc/saphelp_nw70/7.0.12/ja-JP/64/237f8cd43711d1950b0000e8353423/content.htm?no_cache=true

コールバックルーチンが値を取得できるような役目みたいなので汎用モジュールの記述以外にサブルーチンを書かないといけいない模様。諸々考慮してABAPを書いてみると

~~~
CALLBACK_WA-LDBNODE     = 'ANEPV'.          "取得したい項目があるノードID
CALLBACK_WA-GET         = 'X'.              "GETイベントで、対応するコールバックルーチンを呼び出すためのフラグ
CALLBACK_WA-CB_PROG     = SY-REPID.         "コールバックルーチンがあるプログラムID
CALLBACK_WA-CB_FORM     = 'CALLBACK_ANEPV'. "コールバックルーチンID
APPEND CALLBACK_WA TO CALLBACK.

*以下論理データベースの選択条件の内部テーブル設定
SELECTIONS_WA-KIND = 'P'.
SELECTIONS_WA-SELNAME = 'BUKRS'.
SELECTIONS_WA-SIGN = 'I'.
SELECTIONS_WA-OPTION = 'EQ'.
SELECTIONS_WA-LOW = '1000'.
SELECTIONS_WA-HIGH
APPEND SELECTIONS_WA TO SELECTIONS.


*汎用module：論理データベースの処理
CALL FUNCTION 'LDB_PROCESS'
  EXPORTING
    LDBNAME                     = 'ADA'      "論理データベースID
  TABLES
    CALLBACK                    = CALLBACK   "上記で設定したコールバックルーチン
    SELECTIONS                  = SELECTIONS "上記で設定した論理データベースの選択条件
  EXCEPTIONS
    LDB_NOT_REENTRANT           = 1
    LDB_INCORRECT               = 2
    LDB_ALREADY_RUNNING         = 3
    LDB_ERROR                   = 4
    LDB_SELECTIONS_ERROR        = 5
    LDB_SELECTIONS_NOT_ACCEPTED = 6
    VARIANT_NOT_EXISTENT        = 7
    VARIANT_OBSOLETE            = 8
    VARIANT_ERROR               = 9
    FREE_SELECTIONS_ERROR       = 10
    CALLBACK_NO_EVENT           = 11
    CALLBACK_NODE_DUPLICATE     = 12
    OTHERS                      = 13.
~~~
値を受け取るコールバックルーチンは以下の通り。
~~~
FORM CALLBACK_ANEPV USING NAME  TYPE LDBN-LDBNODE
                        　WA    TYPE ANEPV
                          EVT   TYPE C
                          CHECK TYPE C.
*************************************************  
* この中で取得したい項目の値を変数等に格納する。
************************************************** 
ENDFORM.
~~~
これでグローバル変数かなにかに取得した値を設定してあげればEXIT内で拡張した項目に値を設定できるな思い試したところうまくいきました。

## ３．オチ
無事取得したい項目も取れたなと思ったんですが最後に落ちが待っていました。
どうやら論理データベースには1セッションで実行出来る回数が1回だけのものがあると……

えぇ、無事当たりましたよｗ　
論理データベース：ADAは1セッション中に1回しか実行できない物でしたww

データソースのEXITは基本1レコードずつ実行していくものなので一番最初のレコードの条件で論理データベースを実行したら次レコード以降実行されてませんでしたｗ
論理データベース：ADAを複数回実行できるようにしようかとも考えましたが「1セッションで1回しか実行できないならセッション切っちまえ！」
ってことで論理データベースを実行する汎用モジュールとコールバックルーチンを別プログラムにしてEXITからSUBMITを使って別セッションで呼び出すようにしました。
(値の受け渡しはメモリを使用)

これなら1回実行されて呼び出し元プログラムに帰ってきたら実行された汎用モジュール部分のセッションは切れるので複数回実行可能となりましたｗ