ヘッダーをスキップ
Oracle Databaseルール・マネージャおよび式フィルタ開発者ガイド
11gリリース1(11.1)
E05697-01
  目次
目次
索引
索引

戻る
戻る
次へ
次へ
 

10 ルール・マネージャの使用例

この章では、警察管理アプリケーションおよび受注管理アプリケーションを使用して、ルール・マネージャを複数の構成で使用する方法、および複雑なルール条件の表現方法を説明します。


注意:

この2つのアプリケーションの完全なスクリプトは、$ORACLE_HOME/rdbms/demoにインストールされているruldemo.sqlです。

10.1 警察管理ルール・アプリケーション

このアプリケーションでは、ルールを定義して、特定の基準に基づくセキュリティ・アラートの生成、警戒リストへの対象者の登録などを行います。このため、銀行取引、輸送、現場報告など実社会の出来事を使用して基準を説明しています。

コンポジット・イベントを使用する警察管理ルール・アプリケーションを作成する手順は、次のとおりです。

  1. タイムスタンプ値を含むメッセージを保持するための表messagequeueを作成します。

    create table messagequeue (attime timestamp, mesg varchar2(4000));
    
    
  2. イベント構造を表す基本タイプを作成します。

    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
    /
    
    
  3. 手順2で定義した複数の基本タイプで構成されるコンポジット・イベント・タイプを作成します。

    create or replace type LawEnforcement as object
        (bank      BankTransaction,
         transport Transportation,
         fldrpt    FieldReport);
    /
    
    
  4. コンポジット・イベント構造に対して定義したルールのデータベース表を作成します。

    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.
    
    
  5. コールバック・プロシージャを実装し、ルールおよびルールに関連付けられたアクション・プリファレンスと一致するイベント・インスタンスに基づいて、各一致ルールに対する適切なアクションを実行します。この使用例では、メッセージ・キュー表に挿入された詳細メッセージをルールに対するアクションとみなします。次に例を示します。

    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;
    /
    
    
  6. ルール・クラスに定義されているルールでは、データベース・スキーマ内のユーザー定義関数を使用できます。次のリストのコマンドでは、後でルール条件で使用するダミー関数を作成します。

    1. 渡される区域の値について、警戒区域の表を問い合せ、現在の区域が警戒区域の場合は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;
      /
      
      
    2. 選択した対象者が警戒リストにあるかどうかをチェックし、リストにある場合は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;
      /
      
      
    3. 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;
      /
      
      
    4. 次の3つのユーザー定義関数をコンポジット・イベントLawEnforcementに追加します。

      EXEC DBMS_RLMGR.ADD_FUNCTIONS('LawEnforcement', 'OnWatchList');
      EXEC DBMS_RLMGR.ADD_FUNCTIONS('LawEnforcement', 'IsRestrictedArea');
      EXEC DBMS_RLMGR.ADD_FUNCTIONS('LawEnforcement', 'AreAssociates');
      
      
  7. 次の各アクションを提案するルールを定義します。

    1. ルール: ある人物が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>');
      
      
    2. ルール: ある人物が、次の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>');
      
      
    3. ルール: ある人物が海外から多額の送金を受領し、警戒区域の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>');
      
      
    4. ルール: 対象者が海外から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>');
      
      
    5. ルールを参照します。これはオプションです。次に、このタスクの例を示します。

      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>
      .
      .
      .
      
      
  8. プリミティブ・イベントに対するルールを処理します。

    1. ルール・アクションが実行される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]
      
      
    2. 次の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]
      
      
    3. メッセージ・キューをチェックします。

      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]
      
      
    4. 表messagequeueを切り捨てます。

      SQL> truncate table messagequeue;
      
      
    5. ここで、ルール4の期限が経過するのを待機するとします。スケジューラ処理では、このルールを取得してそのアクションを実行します。その結果、新規メッセージがメッセージ・キューに挿入されます。

      SQL> exec dbms_lock.sleep(180);
      
      
    6. 期限が経過した後は、ルール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]
      
      

10.2 受注管理ルール・アプリケーション

この受注管理ルール・アプリケーションでは、リレーショナル表に格納されているイベント・データについてルール・マネージャを使用する方法を示します。

コンポジット・イベントを使用する受注管理ルール・アプリケーションを作成する手順は、次のとおりです。

  1. 次に示すように、購買依頼に関する情報、出荷情報および支払情報を格納するための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));
    
    
  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;
    /
    
    
  3. 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
    
    
  4. コールバック・プロシージャを実装し、ルールおよびルールに関連付けられたアクション・プリファレンスと一致するイベント・インスタンスに基づいて、各一致ルールに対する適切なアクションを実行します。この場合、次の例に示すように、画面に表示されるメッセージはアクションの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;
    /
    
    
  5. ルール条件で使用できるユーザー定義関数を追加します。

    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');
    
    
  6. いくつかのルールを追加します。

    1. ルール: 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>');
      
      
    2. ルール: 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>');
      
      
    3. ルール: 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>');
      
      
  7. 次のリストに示すように、いくつかのプリミティブ・イベント(対応するデータ表に挿入された行)に対してルールを処理します。

    1. 次のイベントは、ルール・クラス内のいくつかのルールと部分的に一致し、対応するアクションはありません。

      insert into PurchaseOrders (orderId, custId, itemId, itemType,
                                  quantity, shipBy) values
      (1, 123, 234, 'ROUTER', 120, '01-OCT-2004');
      
      
    2. 次のイベントは、前に追加したイベントと組み合せて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]
      
      
    3. 次のイベントは、さらに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ルール・クラスとイベント構造を共有します。

  1. 次に示すように、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;
    /
    
    
  2. 次に示すように、コールバック・プロシージャを実装し、ルールおよびルールに関連付けられたアクション・プリファレンスと一致するイベント・インスタンスに基づいて、各一致ルールに対する適切なアクションを実行します。

    --- 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;
    /
    
    
  3. 次に示すように、同じルール・セットを新規のルール・クラスに挿入します。

    insert into OrderMgmtRC2 (select * from OrderMgmtRC);
    commit;
    
    
  4. 次のコード例に示すように、データ表の行に対してルールを処理します。このルール・クラスには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]
    
    

次に、ルールのセッション指向の評価を試行します。次のリストに示すように、一致ルールの結果は、結果ビューで問合せに使用できます。

  1. 次に、結果ビュー表の記述を示します。

    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
    
    
  2. データ表の行に対するルールを処理します。前述の例で使用した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;
    /
    
    
  3. イベント構造は表の別名を使用して構成されているため、イベントは対応する表の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
    
    
  4. 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.3 受注管理アプリケーションのコレクションの使用

次の受注管理アプリケーションでは、複雑なイベントの例を識別し、機能するコレクション・イベントを使用する方法を示します。このアプリケーションでは、イベント構造としてデータベースのオブジェクト型を使用しており、このアプリケーションを作成する基本手順は第10.1項で説明されている手順と同じです。

  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
     );
    /
    
    
  2. ルール・クラスを作成します。ルール・クラス・プロパティは、イベントが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;
    /
    
    
  3. アクション・コールバック・プロシージャの実装。各プリミティブ・イベント・タイプはコレクションで使用可能で、アクション・コールバック・プロシージャには、コレクション・イベントの識別子にバインドされている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;
    /
    
    
  4. ルール・クラスで使用するユーザー定義関数を作成します。

    create or replace function CustomerType (custId int) return VARCHAR2 is
    begin
      return 'GOLD';
    end;
    /
    exec dbms_rlmgr.add_functions('OrderMgmt','CustomerType');
    
    
  5. ルール・クラスにルールを追加します。

    1. ルール: ある顧客が各注文につき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>');
      
      
    2. ルール: 最新の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>');
      
      
    3. ルール: ある顧客が各注文につき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>');
      
      
    4. ルール: 注文品と出荷が完了した出荷品の数量を比較します。

      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>');
      
      
    5. ルール: トラックの積載量が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>');
      
      
  6. PurchaseOrderイベント、ShipItemイベントおよびTruckAtDockイベントのインスタンスに対するルールを処理します。