この章では、警察管理アプリケーションおよび受注管理アプリケーションを使用して、ルール・マネージャを複数の構成で使用する方法、および複雑なルール条件の表現方法を説明します。
注意: この2つのアプリケーションの完全なスクリプトは、$ORACLE_HOME/rdbms/demo にインストールされているruldemo.sql です。 |
このアプリケーションでは、ルールを定義して、特定の基準に基づくセキュリティ・アラートの生成、警戒リストへの対象者の登録などを行います。このため、銀行取引、輸送、現場報告など実社会の出来事を使用して基準を説明しています。
コンポジット・イベントを使用する警察管理ルール・アプリケーションを作成する手順は、次のとおりです。
タイムスタンプ値を含むメッセージを保持するための表messagequeue
を作成します。
create table messagequeue (attime timestamp, mesg varchar2(4000));
イベント構造を表す基本タイプを作成します。
create or replace type BankTransaction as object (subjectId NUMBER, --- Refer to entity such as personnel --- Could be SSN and so forth tranType VARCHAR2(30), --- DEPOSIT / TRANSFER / WITHDRAW amount NUMBER, --- fundFrom VARCHAR2(30)); --- Location from which it is transfered / create or replace type Transportation as object (subjectId NUMBER, vesselType VARCHAR2(30), --- TRUCK / CAR / PLANE / TRAIN locFrom VARCHAR2(30), --- Starting location locTo VARCHAR2(30), --- Ending location startDate DATE, --- start date endDate DATE); --- end date / create or replace type FieldReport as object (subjectId NUMBER, rptType VARCHAR2(30), --- Tel call / Meeting / Bg Check whoWith NUMBER, --- Identifier of the person with whom --- the subject is in touch rptOrg VARCHAR2(30), --- Organization reporting it rptReg VARCHAR2(30), --- Region rptBody sys.XMLType); --- The actual report /
手順2で定義した複数の基本タイプで構成されるコンポジット・イベント・タイプを作成します。
create or replace type LawEnforcement as object (bank BankTransaction, transport Transportation, fldrpt FieldReport); /
コンポジット・イベント構造に対して定義したルールのデータベース表を作成します。
BEGIN DBMS_RLMGR.CREATE_RULE_CLASS( rule_class => 'LawEnforcementRC', event_struct => 'LawEnforcement', action_cbk => 'LawEnforcementCBK', actprf_spec => 'actionType VARCHAR2(40), actionParam VARCHAR2(100)', rslt_viewnm => 'MatchedCriteria', rlcls_prop => '<composite equal="bank.subjectId, transport.subjectId, fldrpt.subjectId" ordering="rlm$rule.rlm$ruleid, bank.subjectId, transport.subjectId"/>'); END; /
ルール・クラスLawEnforcementRC
は、ルールのリポジトリとして機能するリレーショナル表です。この表には一連の事前定義済の列があり、ルール識別子、ルール条件および説明が格納されます。これらの列以外に、このルール・クラス表には、actpref_spec
引数を使用して指定されたactionType
列とactionParam
列も定義されています。この2つの列では、各ルールに対して実行されるアクションのタイプを取得します。次に例を示します。
desc LawEnforcementRC; Name Null? Type --------- -------- ---------------------------------------- RLM$RULEID VARCHAR2(100) ACTIONTYPE VARCHAR2(40) ACTIONPARAM VARCHAR2(100) RLM$RULECOND VARCHAR2(4000) RLM$RULEDESC VARCHAR2(1000) RLM$ENABLED CHAR(1) DEFAULT 'Y'
この手順では、指定の名前を使用して、アクション・コールバック・プロシージャのスケルトンも作成します。次に例を示します。
select text from user_source where name = 'LAWENFORCEMENTCBK' order by line; TEXT ------------------------------------------------------------------------------- procedure "LAWENFORCEMENTCBK" ( "BANK" "BANKTRANSACTION", "TRANSPORT" "TRANSPORTATION", "FLDRPT" "FIELDREPORT", rlm$rule "LAWENFORCEMENTRC"%ROWTYPE) is begin null; --- The action for the matching rules can be carried here. --- The appropriate action can be determined from the --- event and action preferences associated with each rule. end; 10 rows selected.
コールバック・プロシージャを実装し、ルールおよびルールに関連付けられたアクション・プリファレンスと一致するイベント・インスタンスに基づいて、各一致ルールに対する適切なアクションを実行します。この使用例では、メッセージ・キュー表に挿入された詳細メッセージをルールに対するアクションとみなします。次に例を示します。
CREATE OR REPLACE PROCEDURE LAWENFORCEMENTCBK ( bank banktransaction, transport transportation, fldrpt fieldreport, rlm$rule LawEnforcementRC%ROWTYPE) IS mesg VARCHAR2(4000); msgl VARCHAR2(100); begin msgl := 'Rule '||rlm$rule.rlm$ruleid||' matched following primitive events'; dbms_output.put_line(msgl); mesg := msgl||chr(10); if (bank is not null) then msgl := '->Bank Transaction by subject ('||bank.subjectId||') of type ['||bank.tranType||']'; dbms_output.put_line(msgl); mesg := mesg||msgl||chr(10); end if; if (transport is not null) then msgl := '->Transportation by subject('||transport.subjectId||') use vessel ['||transport.vesselType||']'; dbms_output.put_line(msgl); mesg := mesg||msgl||chr(10); end if; if (fldrpt is not null) then msgl := '->Field report refer to('||fldrpt.subjectId||' and '||fldrpt.whowith||')'; dbms_output.put_line(msgl); mesg := mesg||msgl||chr(10); end if; msgl := '=>Recommended Action : Action Type ['||rlm$rule.actionType|| '] Action Parameter ['||rlm$rule.actionParam||']'; dbms_output.put_line(msgl||chr(10)); mesg := mesg||msgl||chr(10); insert into messagequeue values (systimestamp, mesg); end; /
ルール・クラスに定義されているルールでは、データベース・スキーマ内のユーザー定義関数を使用できます。次のリストのコマンドでは、後でルール条件で使用するダミー関数を作成します。
渡される区域の値について、警戒区域の表を問い合せ、現在の区域が警戒区域の場合は1を戻します。
CREATE OR REPLACE FUNCTION IsRestrictedArea(region VARCHAR2) RETURN NUMBER IS BEGIN -- User can expand this function and implement a logic -- that relies on other relational tables. RETURN 1; END; /
選択した対象者が警戒リストにあるかどうかをチェックし、リストにある場合は1を戻します。
CREATE OR REPLACE FUNCTION OnWatchList(subject NUMBER) RETURN NUMBER IS BEGIN -- User can expand this function and implement a logic -- that relies on other relational tables. RETURN 1; END; /
2名の対象者が顔見知りであるかどうかをチェックします。登録簿に従って、渡される2名の対象者が顔見知りである場合は1を戻します。
CREATE OR REPLACE FUNCTION AreAssociates(subjectA NUMBER, subjectB NUMBER) RETURN NUMBER IS BEGIN -- User can expand this function and implement a logic -- that relies on other relational tables. RETURN 1; END; /
次の3つのユーザー定義関数をコンポジット・イベントLawEnforcementに追加します。
EXEC DBMS_RLMGR.ADD_FUNCTIONS('LawEnforcement', 'OnWatchList'); EXEC DBMS_RLMGR.ADD_FUNCTIONS('LawEnforcement', 'IsRestrictedArea'); EXEC DBMS_RLMGR.ADD_FUNCTIONS('LawEnforcement', 'AreAssociates');
次の各アクションを提案するルールを定義します。
ルール: ある人物が10,000ドルを超える送金を受領し、警戒区域の1つに向かうためにトラックを片道分借りた場合は、ニューヨーク市警の警戒リストにその人物を追加します。結合述語はルール・クラス・レベルで指定されることに注意してください。
INSERT INTO LawEnforcementRC (rlm$ruleid, actionType, actionParam, rlm$rulecond) VALUES ('1', 'ADD2WATCHLIST','NYPD', '<condition> <and> <object name="bank"> tranType = ''TRANSFER'' AND amount > 10000 AND fundFrom != ''USA'' </object> <object name="transport"> vesselType = ''TRUCK'' AND locFrom != locTo AND IsRestrictedArea(locTo)=1 </object> </and> </condition>');
ルール: ある人物が、次の3つの条件の2つを満たしている場合は、ニューヨーク市警の警戒リストにその人物を追加します。条件は、海外から10,000ドルを超える送金を受領した場合、警戒区域の1つに向かうためにトラックを片道分借りた場合、およびすでに警戒リストに登録されている人物と電話連絡を取った場合です。次のルールでは、<ANY>
要素の使用方法を示します。このルール条件では、n個のイベントの内、m個のイベントが検出された場合にTRUEと判断されます。
INSERT INTO LawEnforcementRC (rlm$ruleid, actionType, actionParam, rlm$rulecond) VALUES ('2', 'ADD2WATCHLIST','NYPD', '<condition> <any count="2"> <object name="bank"> tranType = ''TRANSFER'' AND amount > 10000 AND fundFrom != ''USA'' </object> <object name="transport"> vesselType = ''TRUCK'' AND locFrom != locTo AND IsRestrictedArea(locTo)=1 </object> <object name="fldrpt"> rptType = ''TELCALL'' AND OnWatchList(whoWith) = 1 </object> </any> </condition>');
ルール: ある人物が海外から多額の送金を受領し、警戒区域の1つに向かうためにトラックを片道分借り、その人物の身元情報に関する現場報告がない場合は、その人物の身元確認を開始します。次のルールでは、否定の使用方法を示します。このルール条件では、指定したイベントの一部が検出され、その他のイベントは検出されなかった場合にTRUEと判断されます。
INSERT INTO LawEnforcementRC (rlm$ruleid, actionType, actionParam, rlm$rulecond) VALUES ('3','STARTBACKGROUNDCHECK','RENTAL_DESTINATION', '<condition> <and> <object name="bank"> tranType = ''TRANSFER'' AND amount > 10000 AND fundFrom != ''USA'' </object> <object name="transport"> vesselType=''TRUCK'' AND locFrom != locTo AND IsRestrictedArea(locTo)=1 </object> <not> <object name="fldrpt"/> </not> </and> </condition>');
ルール: 対象者が海外から10,000ドルを超える送金を受領し、警戒区域に向かうためにトラックを片道分借り、その対象者に逮捕履歴がないことを示す現場報告が特定の時間内(1日の1000分の1単位、日数も使用できますが、ここでは期限の使用方法を示すために秒を使用)に発行されていない場合は、そのトラックの行先を危険区域に追加します。このルールでは、期限を伴う否定を使用しています。
INSERT INTO LawEnforcementRC (rlm$ruleid, actionType, actionParam, rlm$rulecond) VALUES ('4','ADD2HIGH_RISK_AREA','RENTAL_DESTINATION', '<condition> <and> <object name="bank" tranType = ''TRANSFER'' AND amount > 10000 AND fundFrom != ''USA'' </object> <object name="transport"> vesselType = ''TRUCK'' AND locFrom != locTo AND IsRestrictedArea(locTo)=1 </object> <not by="systimestamp+0.001"> <object name="fldrpt"> rptType = ''BACKGROUNDCHECK'' and extract(rptBody, ''/history/arrests[@number=0'') is not null </object> </not> </and> </condition>');
ルールを参照します。これはオプションです。次に、このタスクの例を示します。
select rlm$ruleid, rlm$rulecond from LawEnforcementRC order by 1; RLM$R RLM$RULECOND ----- -------------------------------------------------------------------- 1 <condition> <and> <object name="bank"> tranType = 'TRANSFER' AND amount > 10000 AND fundFrom != 'USA' </object> <object name="transport"> vesselType = 'TRUCK' AND locFrom != locTo AND IsRestrictedArea(locTo)=1 </object> </and> </condition> . . .
プリミティブ・イベントに対するルールを処理します。
ルール・アクションが実行される2つのプリミティブ・イベント(部分的に1つ以上のルールに一致するプリミティブ・イベントと、1つのルールに一致するプリミティブ・イベント)を追加します(メッセージはmessagequeue
表に挿入され、画面にも表示されます)。
set serveroutput on size 10000; BEGIN dbms_rlmgr.process_rules ( rule_class => 'LawEnforcementRC', event_inst => sys.anydata.convertobject( fieldreport(123302122, 'TELCALL',123302123, 'NSA', 'NE', null))); END; /
BEGIN dbms_rlmgr.process_rules ( rule_class => 'LawEnforcementRC', event_inst => sys.anydata.convertobject( banktransaction(123302122, 'TRANSFER', 100000, 'USSR'))); END; / Rule 2 matched following primitive events ->Bank Transaction by subject (123302122) of type [TRANSFER] ->Field report refer to(123302122 and 123302123) =>Recommended Action : Action Type [ADD2WATCHLIST] Action Parameter [NYPD]
次のTransportationイベントは、Bank Transactionイベントと組み合せていくつかのルールを評価し、TRUEの場合は、適切な引数を使用してアクション・コールバック・プロシージャをコールします。
BEGIN dbms_rlmgr.process_rules ( rule_class => 'LawEnforcementRC', event_inst => sys.anydata.convertobject( transportation(123302122, 'TRUCK', 'WIS', 'MD', sysdate, sysdate + 7))); END; / Rule 1 matched following primitive events ->Bank Transaction by subject (123302122) of type [TRANSFER] ->Transportation by subject(123302122) use vessel [TRUCK] =>Recommended Action : Action Type [ADD2WATCHLIST] Action Parameter [NYPD] Rule 2 matched following primitive events ->Transportation by subject(123302122) use vessel [TRUCK]->Field report refer to(123302122 and 123302123) =>Recommended Action : Action Type [ADD2WATCHLIST] Action Parameter [NYPD] Rule 2 matched following primitive events ->Bank Transaction by subject (123302122) of type [TRANSFER] ->Transportation by subject(123302122) use vessel [TRUCK] =>Recommended Action : Action Type [ADD2WATCHLIST] Action Parameter [NYPD] Rule 3 matched following primitive events ->Bank Transaction by subject (123302122) of type [TRANSFER] ->Transportation by subject(123302122) use vessel [TRUCK] =>Recommended Action : Action Type [STARTBACKGROUNDCHECK] Action Parameter [RENTAL_DESTINATION]
メッセージ・キューをチェックします。
SQL> select mesg from messagequeue order by attime; MESG -------------------------------------------- Rule 2 matched following primitive events ->Bank Transaction by subject (123302122) of type [TRANSFER] ->Field report refer to(123302122 and 123302123) =>Recommended Action : Action Type [ADD2WATCHLIST] Action Parameter [NYPD] Rule 1 matched following primitive events ->Bank Transaction by subject (123302122) of type [TRANSFER] ->Transportation by subject(123302122) use vessel [TRUCK] =>Recommended Action : Action Type [ADD2WATCHLIST] Action Parameter [NYPD] Rule 2 matched following primitive events ->Transportation by subject(123302122) use vessel [TRUCK] ->Field report refer to(123302122 and 123302123) =>Recommended Action : Action Type [ADD2WATCHLIST] Action Parameter [NYPD] Rule 2 matched following primitive events ->Bank Transaction by subject (123302122) of type [TRANSFER] ->Transportation by subject(123302122) use vessel [TRUCK] =>Recommended Action : Action Type [ADD2WATCHLIST] Action Parameter [NYPD] Rule 3 matched following primitive events ->Bank Transaction by subject (123302122) of type [TRANSFER] ->Transportation by subject(123302122) use vessel [TRUCK] =>Recommended Action : Action Type [STARTBACKGROUNDCHECK] Action Parameter [RENTAL_DESTINATION]
表messagequeueを切り捨てます。
SQL> truncate table messagequeue;
ここで、ルール4の期限が経過するのを待機するとします。スケジューラ処理では、このルールを取得してそのアクションを実行します。その結果、新規メッセージがメッセージ・キューに挿入されます。
SQL> exec dbms_lock.sleep(180);
期限が経過した後は、ルール4に対して次のアクションが実行されます。
SQL> select mesg from messagequeue; MESG -------------------------------------------- Rule 4 matched following primitive events ->Bank Transaction by subject (123302122) of type [TRANSFER] ->Transportation by subject(123302122) use vessel [TRUCK] =>Recommended Action : Action Type [ADD2HIGH_RISK_AREA] Action Parameter [RENTAL_DESTINATION]
この受注管理ルール・アプリケーションでは、リレーショナル表に格納されているイベント・データについてルール・マネージャを使用する方法を示します。
コンポジット・イベントを使用する受注管理ルール・アプリケーションを作成する手順は、次のとおりです。
次に示すように、購買依頼に関する情報、出荷情報および支払情報を格納するための3つのリレーショナル表を作成します。
create table PurchaseOrders (orderId NUMBER, custId NUMBER, itemId NUMBER, itemType VARCHAR2(30), quantity NUMBER, shipBy DATE); create table ShipmentInfo (orderId NUMBER, destState VARCHAR2(2), address VARCHAR2(50), shipTime DATE, shipType VARCHAR2(10)); create table PaymentInfo (orderId NUMBER, payType VARCHAR2(10), -- Credit Card / Check -- amountPaid NUMBER, pymtTime DATE, billState VARCHAR2(2));
イベント構造を作成します。表の別名の構成メンバーを使用して既存の表を参照するイベント構造は、オブジェクト型から作成できません。かわりに、次に示すように式フィルタの属性セットとしてイベント構造をモデル化します。
begin DBMS_RLMGR.CREATE_EVENT_STRUCT (event_struct => 'OrderMgmt'); DBMS_RLMGR.ADD_ELEMENTARY_ATTRIBUTE( event_struct => 'OrderMgmt', attr_name => 'po', tab_alias => RLM$TABLE_ALIAS('PurchaseOrders')); DBMS_RLMGR.ADD_ELEMENTARY_ATTRIBUTE( event_struct => 'OrderMgmt', attr_name => 'si', tab_alias => RLM$TABLE_ALIAS('ShipmentInfo')); DBMS_RLMGR.ADD_ELEMENTARY_ATTRIBUTE( event_struct => 'OrderMgmt', attr_name => 'py', tab_alias => RLM$TABLE_ALIAS('PaymentInfo')); end; /
OrderMgmt
コンポジット・イベントに対してルール・クラス(ルールのデータベース表)を作成します。さらに、次に示すように、イベント・データ表に挿入された行ごとにルールを処理するようにDMLEVENTS
を指定します。
BEGIN DBMS_RLMGR.CREATE_RULE_CLASS ( rule_class => 'OrderMgmtRC', event_struct => 'OrderMgmt', action_cbk => 'OrderMgmtCBK', actprf_spec => 'actionType VARCHAR2(40), actionParam VARCHAR2(100)', rslt_viewnm => 'MatchingOrders', rlcls_prop => '<composite equal="po.orderId, si.orderId, py.orderId" dmlevents="I"/>'); END; /
この手順では、次に示すように、指定した名前を使用して、アクション・コールバック・プロシージャのスケルトンも作成します。
desc OrderMgmtCBK; PROCEDURE OrderMgmtCBK Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- PO ROWID IN SI ROWID IN PY ROWID IN RLM$RULE RECORD IN RLM$RULEID VARCHAR2(100) IN ACTIONTYPE VARCHAR2(40) IN ACTIONPARAM VARCHAR2(100) IN RLM$RULECOND VARCHAR2(4000) IN RLM$RULEDESC VARCHAR2(1000) IN RLM$ENABLED CHAR(1) DEFAULT 'Y' IN
コールバック・プロシージャを実装し、ルールおよびルールに関連付けられたアクション・プリファレンスと一致するイベント・インスタンスに基づいて、各一致ルールに対する適切なアクションを実行します。この場合、次の例に示すように、画面に表示されるメッセージはアクションの1つとみなされます。
CREATE OR REPLACE PROCEDURE OrderMgmtCBK ( po ROWID, -- rowid from the PurchaseOrders table si ROWID, -- rowid from the ShipmentInfo table py ROWID, -- rowid from the PaymentInfo table rlm$rule OrderMgmtRC%ROWTYPE) IS ordId NUMBER; msg VARCHAR2(2000); begin -- the rowid arguments represent the primitive events that are -- rows inserted into the corresponding tables. Use the rowids -- to fetch necessary values. if (po is not null) then select orderId into ordId from PurchaseOrders where rowid = po; elsif (si is not null) then select orderId into ordId from ShipmentInfo where rowid = si; elsif (py is not null) then select orderId into ordId from PaymentInfo where rowid = py; end if; msg := 'Order number: '||ordId||' Matched rule: ' ||rlm$rule.rlm$ruleid||chr(10)|| '-> Recommended Action : '||chr(10)|| ' Action Type ['||rlm$rule.actionType|| ']'||chr(10)|| ' Action Parameter ['|| rlm$rule.actionParam||']'; dbms_output.put_line (msg||chr(10)); end; /
ルール条件で使用できるユーザー定義関数を追加します。
create or replace function getCustType(custId number) return VARCHAR2 is begin -- the actual function implementation can rely on other -- relational tables to derive the customer type information return 'GOLD'; end; / exec DBMS_RLMGR.ADD_FUNCTIONS('OrderMgmt','getCustType');
いくつかのルールを追加します。
ルール: 100個を超えるルーターの注文で、支払いを小切手で受領する場合は、顧客と連絡を取って注文のステータスを更新します。イベント・タイプ間の結合述語は、ルール・クラス・レベルで指定されることに注意してください。次に例を示します。
INSERT INTO OrderMgmtRC (rlm$ruleid, actionType, actionParam, rlm$rulecond) VALUES (1, 'CALL_CUSTOMER','UPDATE_ORDER_STATUS', '<condition> <and> <object name="po"> itemType = ''ROUTER'' and quantity > 100 </object> <object name="py"> payType = ''CHECK'' </object> </and> </condition>');
ルール: Goldクラスの顧客から注文があり、支払いを受ける前に注文品を出荷した場合は、顧客の与信を調整します。次に例を示します。
INSERT INTO OrderMgmtRC (rlm$ruleid, actionType, actionParam, rlm$rulecond) VALUES (2, 'UPDATE_CUST_PROFILE', 'DECR_AVAILABLE_CREDIT', '<condition> <and> <object name="po"> getCustType(custid) = ''GOLD'' </object> <object name="si"/> <not> <object name="py"/> </not> </and> </condition>');
ルール: Goldクラスの顧客から注文があり、出荷期限の1日前以内に注文品を出荷した場合は、サービス品質の統計を増分します。次に例を示します。
INSERT INTO OrderMgmtRC (rlm$ruleid, actionType, actionParam, rlm$rulecond) VALUES (3, 'UPDATE_STATISTICS', 'INCREMENT QOS', '<condition> <and join="po.shipby > si.shiptime-1"> <object name="po"> getCustType(custid) = ''GOLD'' </object> <object name="si"/> </and> </condition>');
次のリストに示すように、いくつかのプリミティブ・イベント(対応するデータ表に挿入された行)に対してルールを処理します。
次のイベントは、ルール・クラス内のいくつかのルールと部分的に一致し、対応するアクションはありません。
insert into PurchaseOrders (orderId, custId, itemId, itemType, quantity, shipBy) values (1, 123, 234, 'ROUTER', 120, '01-OCT-2004');
次のイベントは、前に追加したイベントと組み合せて2つのルールに一致し、対応するアクションを起動します。
insert into ShipmentInfo (orderId, deststate, address, shipTime, shipType) values (1, 'CA','1 Main street, San Jose','29-SEP-2004','1 Day Air'); Order number: 1 Matched rule: 2 -> Recommended Action : Action Type [UPDATE_CUST_PROFILE] Action Parameter [DECR_AVAILABLE_CREDIT] Order number: 1 Matched rule: 3 -> Recommended Action : Action Type [UPDATE_STATISTICS] Action Parameter [INCREMENT QOS]
次のイベントは、さらに1つのルールに一致します。
insert into PaymentInfo (orderId, paytype, amountpaid, pymttime, billstate) values (1, 'CHECK', 100000, '30-SEP-2004', 'CA'); Order number: 1 Matched rule: 1 -> Recommended Action : Action Type [CALL_CUSTOMER] Action Parameter [UPDATE_ORDER_STATUS]
ここで、DMLEVENTS
プロパティを使用しない類似のアプリケーションを考えてみます。この場合、ユーザーは明示的にルール・マネージャAPIを起動して、リレーショナル表に格納されたデータに対してルールを処理します。このルール・クラスは、OrderMgmtRC
ルール・クラスとイベント構造を共有します。
次に示すように、OrderMgmtRC2
コンポジット・イベントに対してルール・クラス(ルールのデータベース表)を作成します。
BEGIN DBMS_RLMGR.CREATE_RULE_CLASS ( rule_class => 'OrderMgmtRC2', event_struct => 'OrderMgmt', action_cbk => 'OrderMgmtCBK2', actprf_spec => 'actionType VARCHAR2(40), actionParam VARCHAR2(100)', rslt_viewnm => 'MatchingOrders2', rlcls_prop => '<composite equal="po.orderId, si.orderId, py.orderId"/>'); END; /
次に示すように、コールバック・プロシージャを実装し、ルールおよびルールに関連付けられたアクション・プリファレンスと一致するイベント・インスタンスに基づいて、各一致ルールに対する適切なアクションを実行します。
--- Implement the action callback procedure -- CREATE OR REPLACE PROCEDURE OrderMgmtCBK2 ( po ROWID, -- rowid from the PurchaseOrders table si ROWID, -- rowid from the ShipmentInfo table py ROWID, -- rowid from the PaymentInfo table rlm$rule OrderMgmtRC2%ROWTYPE) IS ordId NUMBER; msg VARCHAR2(2000); begin -- the rowid argument represent the primitive events that are -- rows inseted into the corresponding tables. Use the rowids -- to fetch necessary values. if (po is not null) then select orderId into ordId from PurchaseOrders where rowid = po; elsif (si is not null) then select orderId into ordId from ShipmentInfo where rowid = si; elsif (py is not null) then select orderId into ordId from PaymentInfo where rowid = py; end if; msg := 'Order number: '||ordId||' Matched rule: ' ||rlm$rule.rlm$ruleid||chr(10)|| '-> Recommended Action : '||chr(10)|| ' Action Type ['||rlm$rule.actionType|| ']'||chr(10)||' Action Parameter ['|| rlm$rule.actionParam||']'; dbms_output.put_line (msg||chr(10)); end; /
次に示すように、同じルール・セットを新規のルール・クラスに挿入します。
insert into OrderMgmtRC2 (select * from OrderMgmtRC); commit;
次のコード例に示すように、データ表の行に対してルールを処理します。このルール・クラスにはDMLイベントが構成されていないため、アプリケーションはデータ表の行に対してルールを明示的に処理する必要があります。データ表に挿入された行のROWIDは、イベントへの参照として使用され、ルールを処理するためにPROCESS_RULES
プロシージャに渡されます。
var datarid varchar2(40);
insert into PurchaseOrders (orderId, custId, itemId, itemType, quantity, shipBy) values (2, 123, 234, 'ROUTER', 120, '01-OCT-2004') returning rowid into :datarid; BEGIN dbms_rlmgr.process_rules (rule_class => 'OrderMgmtRC2', event_type => 'PurchaseOrders', event_inst => :datarid); END; /
insert into ShipmentInfo (orderId, deststate, address, shipTime, shipType) values (2, 'CA','1 Main street, San Jose','29-SEP-2004','1 Day Air') returning rowid into :datarid; BEGIN dbms_rlmgr.process_rules (rule_class => 'OrderMgmtRC2', event_type => 'ShipmentInfo', event_inst => :datarid); END; / Order number: 2 Matched rule: 2 -> Recommended Action : Action Type [UPDATE_CUST_PROFILE] Action Parameter [DECR_AVAILABLE_CREDIT] Order number: 2 Matched rule: 3 -> Recommended Action : Action Type [UPDATE_STATISTICS] Action Parameter [INCREMENT QOS]
insert into PaymentInfo (orderId, paytype, amountpaid, pymttime, billstate) values (2, 'CHECK', 100000, '30-SEP-2004', 'CA') returning rowid into :datarid; BEGIN dbms_rlmgr.process_rules (rule_class => 'OrderMgmtRC2', event_type => 'PaymentInfo', event_inst => :datarid); END; / Order number: 2 Matched rule: 1 -> Recommended Action : Action Type [CALL_CUSTOMER] Action Parameter [UPDATE_ORDER_STATUS]
次に、ルールのセッション指向の評価を試行します。次のリストに示すように、一致ルールの結果は、結果ビューで問合せに使用できます。
次に、結果ビュー表の記述を示します。
set linesize 80; desc MatchingOrders2; Name Null? Type ----------------------------------------- -------- ---------------------------- RLM$EVENTID ROWID PO ROWID SI ROWID PY ROWID RLM$RULEID VARCHAR2(100) ACTIONTYPE VARCHAR2(40) ACTIONPARAM VARCHAR2(100) RLM$RULECOND VARCHAR2(4000) RLM$RULEDESC VARCHAR2(1000) RLM$ENABLED CHAR(1) DEFAULT 'Y' select count(*) from MatchingOrders2; COUNT(*) ---------- 0
データ表の行に対するルールを処理します。前述の例で使用したPROCESS_RULES
プロシージャのかわりに、ADD_EVENT
プロシージャを使用することに注意してください。これによって、イベントをルールと一致させた結果がルール・クラス結果ビューに格納されます。次に例を示します。
insert into PurchaseOrders (orderId, custId, itemId, itemType, quantity, shipBy) values (3, 123, 234, 'ROUTER', 120, '01-OCT-2004') returning rowid into :datarid; --- Use ADD_EVENT API in the place of PROCESS_RULES --- BEGIN dbms_rlmgr.add_event (rule_class => 'OrderMgmtRC2', event_type => 'PurchaseOrders', event_inst => :datarid); END; /
insert into ShipmentInfo (orderId, deststate, address, shipTime, shipType) values (3, 'CA','1 Main street, San Jose','29-SEP-2004','1 Day Air') returning rowid into :datarid; BEGIN dbms_rlmgr.add_event (rule_class => 'OrderMgmtRC2', event_type => 'ShipmentInfo', event_inst => :datarid); END; /
insert into PaymentInfo (orderId, paytype, amountpaid, pymttime, billstate) values (3, 'CHECK', 100000, '30-SEP-2004', 'CA') returning rowid into :datarid; BEGIN dbms_rlmgr.add_event (rule_class => 'OrderMgmtRC2', event_type => 'PaymentInfo', event_inst => :datarid); END; /
イベント構造は表の別名を使用して構成されているため、イベントは対応する表のROWIDを使用して表されます。
column rlm$ruleid format a7; column actiontype format a25; column actionparam format a25; select po, si, py, rlm$ruleid, actionType, actionParam from MatchingOrders2; PO SI PY RLM$RUL ------------------ ------------------ ------------------ ------- ACTIONTYPE ACTIONPARAM ------------------------- ------------------------- AAAOBxAAEAAAAHPAAC AAAOByAAEAAAAHXAAC 2 UPDATE_CUST_PROFILE DECR_AVAILABLE_CREDIT AAAOBxAAEAAAAHPAAC AAAOByAAEAAAAHXAAC 3 UPDATE_STATISTICS INCREMENT QOS AAAOBxAAEAAAAHPAAC AAAOBzAAEAAAAHfAAC 1 CALL_CUSTOMER UPDATE_ORDER_STATUS
ROWIDを使用すると、次に示すように、実際のイベントの値をデータ表から導出できます。
select (select orderId from purchaseOrders where rowid = po) as OrderId, rlm$ruleid, actionType, actionParam from MatchingOrders2; ORDERID RLM$RUL ACTIONTYPE ACTIONPARAM ---------- ------- ------------------------- ------------------------- 3 2 UPDATE_CUST_PROFILE DECR_AVAILABLE_CREDIT 3 3 UPDATE_STATISTICS INCREMENT QOS 3 1 CALL_CUSTOMER UPDATE_ORDER_STATUS
次の受注管理アプリケーションでは、複雑なイベントの例を識別し、機能するコレクション・イベントを使用する方法を示します。このアプリケーションでは、イベント構造としてデータベースのオブジェクト型を使用しており、このアプリケーションを作成する基本手順は第10.1項で説明されている手順と同じです。
プリミティブ・イベント構造を表すオブジェクト型およびコンポジット・イベント構造を作成します。
create or replace type PurchaseOrder as object ( orderid number, customerid number, itemid number, itemcount number, amount number, exptddate date); / create or replace type ShipItem as object ( itemid number, itemtype varchar2(30), orderid number, truckid number); / create or replace type TruckAtDock as object ( truckid number, loadid date, status varchar2(30), capacity number); / create or replace type OrderMgmt as object ( porder PurchaseOrder, sitem ShipItem, truck TruckAtDock ); /
ルール・クラスを作成します。ルール・クラス・プロパティは、イベントがPurchaseOrder
に基づくように、またShipItem
型がコレクションで使用可能になるように設定されます。
BEGIN DBMS_RLMGR.CREATE_RULE_CLASS( rule_class => 'OrderMgmtRC', event_struct => 'OrderMgmt', action_cbk => 'OrderMgmtCBK', actprf_spec => 'actionType VARCHAR2(40), actionParam VARCHAR2(100), poAggrRet VARCHAR2(20) default null', rslt_viewnm => 'MatchedScenarios', rlcls_prop => '<composite equal="(porder.orderid, sitem.orderid) | (sitem.truckid, truck.truckid)" ordering="rlm$rule.rlm$ruleid, porder.orderid, porder.itemid, truck.loadid"> <collection type="PurchaseOrder" groupby="orderid, customerid, itemid"/> <collection type="ShipItem" groupby="itemid, truckid"/> </composite>'); END; /
アクション・コールバック・プロシージャの実装。各プリミティブ・イベント・タイプはコレクションで使用可能で、アクション・コールバック・プロシージャには、コレクション・イベントの識別子にバインドされているROWID引数が1つ追加されます。このイベント識別子を使用して、指定のルールで計算された値の総計を取得できます。
create or replace procedure "ORDERMGMTCBK" ( PORDER PURCHASEORDER, PO_EVTID ROWID, SITEM SHIPITEM, SI_EVTID ROWID, TRUCK TRUCKATDOCK, rlm$rule ORDERMGMTRC%ROWTYPE) is mesg VARCHAR2(100); aggrval VARCHAR2(100); begin mesg := ' Rule "'||rlm$rule.rlm$ruleid|| '" matched '|| case when porder.orderid is not null then 'Purchase Order' ||porder.orderid when porder.customerid is not null then 'Customer' ||porder.customerid when sitem.truckid is not null then '||Truck '||sitem.truckid end; if (porder is not null and rlm$rule.poAggrRet is not null) then aggrval := dbms_rlmgr.get_aggregate_value ('OrderMgmtRC', po_evtid, rlm$rule.poAggrRet); aggrval := ' with '||rlm$rule.poAggrRet||' equal to '||aggrval; end if; dbms_output.put_line (mesg||aggrval); end; /
ルール・クラスで使用するユーザー定義関数を作成します。
create or replace function CustomerType (custId int) return VARCHAR2 is begin return 'GOLD'; end; / exec dbms_rlmgr.add_functions('OrderMgmt','CustomerType');
ルール・クラスにルールを追加します。
ルール: ある顧客が各注文につき10,000ドルを超える大量の注文を発行した場合、その人物にエリートのステータスを提供します。
insert into OrderMgmtRC (rlm$ruleid, actionType, actionParam, rlm$ruledesc, rlm$rulecond) values ('Large number of orders promo', 'PROMOTION','ELITE_STATUS', 'Offer an elite status to a customer if he submited a large number of orders, each with a minimum of 10000 dollars', '<condition> <collection name="porder" groupby="customerid" having="count(*) > 10"> amount > 10000 </collection> </condition>');
ルール: 最新の10注文の平均が20,000ドルを超える場合、大量注文のための販促を提供します。
insert into OrderMgmtRC (rlm$ruleid, actionType, actionParam, rlm$ruledesc, rlm$rulecond) values ('Expanding customer', 'PROMOTION', 'LARGE_ORDER', 'Offer a promotion for ordering in bulk if the average size of the last 10 orders is over 20000 dollars', '<condition> <collection name="porder" groupby="customerid" windowsize="10" having="avg(amount) > 20000"/> </condition>');
ルール: ある顧客が各注文につき1,000ドルを超える多数の注文を発行した場合、30日以内にその人物にエリートのステータスを提供します。
insert into OrderMgmtRC (rlm$ruleid, actionType, actionParam, rlm$ruledesc, rlm$rulecond) values ('Promo on Total size of orders in 10 days ', 'PROMOTION','ELITE_STATUS', 'Offer an elite status to a customer if he submitted a large number of orders, each with a minimum of 1000 dollars, in a 30 day period', '<condition> <collection name="porder" groupby="customerid" windowlen="30" having="sum(amount) > 50000"/> amount > 1000 </collection> </condition>');
ルール: 注文品と出荷が完了した出荷品の数量を比較します。
insert into OrderMgmtRC (rlm$ruleid, actionType, actionParam, rlm$ruledesc, rlm$rulecond) values ('Completed order', 'UPDATE_ORDER_STATUS','COMPLETE', 'Compare the number of items ordered and the items shipped to mark the order complete', '<condition> <and equal="porder.orderid, sitem.orderid" having="count(sitem.*) = porder.itemcount"> <object name="porder"/> <collection name="sitem" groupby="orderid" compute="count(*)"> itemtype != ''Reusable Container'' </collection> </and> </condition>');
ルール: トラックの積載量が90%以上で、出荷の準備が整ったことを示します。
insert into OrderMgmtRC (rlm$ruleid, actionType, actionParam, rlm$ruledesc, rlm$rulecond) values ('Ready to ship', 'READY_TO_SHIP', 'LOADED_TRUCK', 'Signal readiness to ship when the truck is at least 90% full', '<condition> <and equal="sitem.truckid, truck.truckid" having="count(sitem.*) >= truck.capacity*0.9" > <object name="truck"> status = ''Loading'' </object> <collection name="sitem" groupby="truckid" compute="count(*)"> itemtype = ''Reusable Container'' </collection> </and> </condition>');
PurchaseOrder
イベント、ShipItem
イベントおよびTruckAtDock
イベントのインスタンスに対するルールを処理します。