表関数を実装するとAPI呼び出しの結果をSELECT文で扱うことができます。SQLのCROSS APPLYを使うと、APEXコレクションなどに保存した値を表関数に与えることができます。
少し前に、Oracle Spatialの接触追跡を使うAPEXアプリケーションを作成しました(こちらの記事)。この記事では(問題があったため)接触追跡はRESTサービスとして実装しています。その後、表関数でも接触追跡(SDO_OBJ_TRACING.GET_ALL_DURATIONSの呼び出し)が出来たので、その実装方法を紹介しています。(こちらの記事)。
この接触追跡の表関数を使って、CROSS APPLYの使い方を紹介します。
接触追跡を行う対象をAPEXコレクションCONTACT_USERSに保存します。APEXコレクションへの値の挿入、変更、削除には、対話グリッドを利用します。
作成したアプリケーションは以下のように動作します。
元記事で作成しているREST APIを使ったAPEXアプリケーションを改変します。表関数contact_tracingが作成済みであることを前提とします。
APEXコレクションの初期化
接触追跡の条件を保存するAPEXコレクションを初期化します。使用するAPEXコレクションの名前はCONTACT_USERSとします。これから対話グリッドのソースやマップのレイヤーのソース、その他のコードにもAPEXコレクション名を指定する箇所があるので、直書きを避けるためにアプリケーション定義の置換として、置換文字列を設定します。
アプリケーション定義の置換のセクションにて、置換文字列としてG_COLLECTION_NAME、置換値にCONTACT_USERSを設定します。
セッションの開始時に、このAPEXコレクションを初期化します。
共有コンポーネントのアプリケーション・プロセスを開きます。
アプリケーション・プロセスの一覧が表示されます。作成を実行します。
);
次へ進みます。
アプリケーションの日時書式の設定
ページの編集
select | |
seq_id id | |
, n001 user_id | |
, d001 start_time | |
, d002 end_time | |
, n002 distance | |
, n003 time_tolerance_in_sec | |
, n004 chaining_tolerance_in_sec | |
from | |
apex_collections | |
where | |
collection_name = :G_COLLECTION_NAME |
APEXコレクションのSEQ_IDは、列IDとして認識されます。これを主キーとして扱います。レンダリング・ツリーより列IDを選択し、識別のタイプを非表示、ソースの主キーをONに変更します。
挿入/更新/削除するPL/SQLコードに、以下のコードを記述します。
begin | |
case :APEX$ROW_STATUS | |
when 'C' then | |
:ID := apex_collection.add_member( | |
p_collection_name => :G_COLLECTION_NAME | |
, p_d001 => :START_TIME | |
, p_d002 => :END_TIME | |
, p_n001 => :USER_ID | |
, p_n002 => :DISTANCE | |
, p_n003 => :TIME_TOLERANCE_IN_SEC | |
, p_n004 => :CHAINING_TOLERANCE_IN_SEC | |
); | |
when 'U' then | |
apex_collection.update_member( | |
p_collection_name => :G_COLLECTION_NAME | |
, p_seq => :ID | |
, p_d001 => :START_TIME | |
, p_d002 => :END_TIME | |
, p_n001 => :USER_ID | |
, p_n002 => :DISTANCE | |
, p_n003 => :TIME_TOLERANCE_IN_SEC | |
, p_n004 => :CHAINING_TOLERANCE_IN_SEC | |
); | |
when 'D' then | |
apex_collection.delete_member( | |
p_collection_name => :G_COLLECTION_NAME | |
, p_seq => :ID | |
); | |
end case; | |
end; |
select | |
r.x | |
, r.y | |
, r.end_time | |
, r.contact_id | |
, r.in_user_id | |
, r.start_time | |
, r.out_user_id | |
, r.num_contact_times | |
, r.duration_in_minutes | |
, case | |
when contact_id = 1 then | |
'red' | |
when contact_id = 2 then | |
'green' | |
when contact_id = 3 then | |
'yellow' | |
when contact_id = 4 then | |
'blue' | |
else | |
'black' | |
end col | |
from | |
( | |
select | |
n001 user_id | |
, d001 start_time | |
, d002 end_time | |
, n002 distance | |
, n003 time_tolerance_in_sec | |
, n004 chaining_tolerance_in_sec | |
from apex_collections | |
where collection_name = :G_COLLECTION_NAME | |
) p | |
-- APEXコレクションの値を表関数に渡す。 | |
cross apply | |
( | |
table( | |
contact_tracing( | |
p.user_id | |
, p.start_time | |
, p.end_time | |
, p.distance | |
, p.time_tolerance_in_sec | |
, p.chaining_tolerance_in_sec | |
) | |
) | |
) r |