Skip Headers
Oracle® Database Rules Manager and Expression Filter Developer's Guide
11g Release 2 (11.2)

Part Number E14919-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Master Index
Master Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

4 Event and Rule Class Configurations

For a rule application, the types of data you include in an event structure and the event sources are application dependent. Rules Manager makes use of the Oracle rich type system to support rules applications involving complex data types such as XML, Spatial, and Text. Similarly, it leverages from its integration with the database to capture transactional and non-transaction modifications to the data as the source of events.

This chapter discusses various event and rule class configurations that provide the ultimate flexibility in designing rules applications in the database.

4.1 Rules Specified on Relational Tables

The rule applications considered so far use rule conditions that you define on some application data. That is, the concept of an event instance exists in the application and it may or may not be stored in the database. Often however, the data in the event instances correspond to some rows stored in relational tables. For such applications, you can use the row identifiers (ROWIDs) of these rows to pass the data by reference to the Rules Manager procedures, for example, using the event_inst parameter to represent an event instance of the PROCESS_RULES call (event_inst => :FlightDataRowid). For this purpose, you should model the corresponding event structure using Expression Filter's table alias constructs. See the ADD_ELEMENTARY_ATTRIBUTE procedure for more information. See Section 10.2 and Appendix A for more examples.

For the travel services application considered in Section 2.4, if you store the AddFlight and AddRentalCar primitive events in two relational tables FlightData and RentalCarData respectively, you can create the corresponding composite event structure to refer to rows in these tables as follows:

BEGIN  DBMS_RLMGR.CREATE_EVENT_STRUCTURE (event_structure => 'TSCompEvent');
  DBMS_RLMGR.ADD_ELEMENTARY_ATTRIBUTE (
                           event_structure => 'TSCompEvent',
                           attr_name => 'Flt', --- Prim event name
                           tab_alias => rlm$table_alias('FlightData'));
  DBMS_RLMGR.ADD_ELEMENTARY_ATTRIBUTE (
                           event_structure => 'TSCompEvent',
                           attr_name => 'Car', --- Prim event name
                           tab_alias => rlm$table_alias('RentalCarData'));
END;

Now you can use the composite event structure TSCompEvent to configure a rule class (Same as step 2 in Section 2.4.1). The representation of the rules in the rule class does not vary with this event structure. However, within the action callback procedure, the primitive event instances that match a rule are each passed in as ROWIDs from the corresponding tables and you use these ROWIDs to obtain the original event data. Also, with this new event structure, the primitive event instances, for which the rules are processed, are passed in by reference using the ROWIDs for the corresponding table rows.

BEGIN
  dbms_rlmgr.process_rules (
            rule_set_nm => 'TravelPromotion',
            event_type => 'FlightData',
            event_inst => :FlightDataRowid); -- rowid of a row ---
END;

Note that you evaluate the conditions corresponding to a primitive event when the dbms_rlmgr.process_rules procedure is invoked with the appropriate ROWID. However, Rules Manager does not keep track of any changes to the original row through an UPDATE operation.

Optionally, you can eliminate the PROCESS_RULES call by configuring the preceding rule class to consider all the DML (INSERT, UPDATE, and DELETE) operations on the corresponding tables as events. This is done using the DMLEVENTS or CNFEVENTS property at the time of rule class creation. (See Section 3.7 and Section 3.8).

When the duration and consumption policies are set for the primitive events derived from relational data, it is the references to the table rows that are consumed or deleted from the rule class. The original rows are not affected by these event management policies.A composite event structure can be formed using a combination of table alias constructs and embedded abstract data types (ADTs) (for various primitive events). The rule conditions defined for a composite event structure consisting of one or more table alias constructs may not use the (short form of) the SEQUENCE property to enforce sequencing among primitive events (see Section 5.2). This is because the implicit attribute rlm$crttime may not exist for the rows stored in the relational tables. You can enforce partial sequencing using the join property in the rule conditions.

4.2 Rule Conditions For XML Events

You can use the XMLType data type supplied by Oracle Database to create attributes in the event structures and rule classes that can process rules defined on XML documents. For this purpose, a primitive event structure can be created with one or more XMLType attributes (along with some non-XML attributes), such as the following:

CREATE or REPLACE TYPE AddFlight AS OBJECT (
                  CustId NUMBER,
                  Airline VARCHAR(20),
                  FromCity VARCHAR(30),
                  ToCity VARCHAR(30),
                  Depart DATE,
                  Return DATE,
                  Details sys.XMLType)

If a primitive event is just an XML document, then the preceding object type can be created with just one attribute, that is of XMLType. You specify the predicates on the XMLType attributes using the EXTRACT and EXISTSNODE operators supplied by Oracle, as shown in the following example.

<condition> <!-- optional for conditions on primitive events -->
   Airline='Abcair' and ToCity='Orlando' and
            EXTRACT(doc, '/preferences/seat[@class="economy"]') is not null
</condition>

You can form a composite event structure for XML events by including two or more primitive event types that contain an XMLType attribute. So, you create the composite event structure as an object type with embedded primitive event types (as described in Section 2.4). Once you create the event structures with XMLType attributes, all the other concepts described in Section 2.2 apply to the XML data that is part of the events.

For a better understanding of how XPath predicates are handled and how they are indexed, see Chapter 13.

4.3 Rule Conditions with Spatial Predicates

Note:

The Oracle Spatial or the Locator components must be installed in order to use spatial predicates in stored expressions.

The SDO_GEOMETRY data type supplied by Oracle Database can be used to create event structures and rule classes that can process rules defined on spatial geometries. For this purpose, you can create a primitive event structure with one or more attributes of the MDSYS.SDO_GEOMETRY type, as follows:

CREATE or REPLACE TYPE AddHotel AS OBJECT (
       CustId    NUMBER,
       Type      VARCHAR(20),
       CheckIn   DATE,
       CheckOut  DATE,
       Location  MDSYS.SDO_GEOMETRY)

In order to specify predicates on the spatial attributes and index them for efficiency, you should associate the geometry metadata describing the dimension, lower and upper bounds, and tolerance in each dimension with each spatial geometry attribute. You can insert this metadata information into the USER_SDO_GEOM_METADATA view using the event structure name in the place of the table name. For more information on the USER_SDO_GEOM_METADATA view and its semantics, see Oracle Spatial Developer's Guide.

INSERT INTO user_sdo_geom_metadata VALUES ('ADDHOTEL','LOCATION',
        mdsys.sdo_dim_array(
             mdsys.sdo_dim_element('X',  -180, 180, 0.5),
             mdsys.sdo_dim_element('Y',  -90, 90, 0.5)), 8307);

When you use the event structure with spatial attribute to create a rule class, the rule conditions stored in the rule class table can include predicates in these attributes using SDO_WITHIN_DISTANCE or SDO_RELATE operators, as shown in the following examples:

<condition>
  Type = 'Luxury' and CheckOut-CheckIn > 3 and  
    SDO_WITHIN_DISTANCE (Location,
      SDO_GEOMETRY(2001, 8307, 
        SDO_POINT_TYPE(-77.03644, 37.89868, NULL), NULL, NULL), 
      'distance=0.5 units=mile') = 'TRUE'
</condition>
<condition>
  Type = 'Luxury' and CheckOut-CheckIn > 3 and  
    SDO_RELATE (Location,
      SDO_GEOMETRY(2001, 8307, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 3), 
         SDO_ORDINATE_ARRAY(-77.03644, 37.89868, -75, 39), 
      'mask=anyinteract') = 'TRUE'
</condition>

You can form a composite event structure involving spatial attributes by including two or more primitive event structures that contain SDO_GEOMETRY attributes. In the case of rules specified for composite events, the spatial predicates involving SDO_WITHIN_DISTANCE or SDO_RELATE operators are not allowed in the join clause of the rule condition. If needed, you can use functions defined in the MDSYS.SDO_GEOM package to achieve this functionality. See Oracle Spatial Developer's Guide for additional information.

4.4 Rule Conditions for Text Events

You can configure the event structure associated with a rule class for one or more text attributes such that the corresponding rule conditions may include text predicates on these attributes. You specify the text predicates in the rule conditions using the Oracle Text CONTAINS operator. The CONTAINS operator refers to the text attribute defined in the event structure and applies a text query expression on the documents bound to this attribute.

You can define the text attributes in an event structure to be of CLOB or VARCHAR data type with associated text preferences. You can create such attributes using the DBMS_RLMGR.ADD_ELEMENTARY_ATTRIBUTE procedure. You specify the text preferences for an attribute using an instance of EXF$TEXT type, which accepts the text preferences in string format, for example: (LEXER hotelreserv_lexer WORDLIST hotelreserv_wordlist). Use the preferences specified through this argument for parsing the document bound to the attribute and for indexing the text query expressions within the rule conditions. Alternately, you can assign an EXF$TEXT instance with an empty preferences string to use default preferences.

For the travel services application considered in Section 2.4, if each hotel reservation includes some addition information, you can model the AddHotel event structure as follows.

BEGIN
  DBMS_RLMGR.CREATE_EVENT_STRUCT (EVENT_STRUCT => 'AddFlight'); 
  DBMS_RLMGR.ADD_ELEMENTARY_ATTRIBUTE (
                       EVENT_STRUCT => 'AddHotel',
                       ATTR_NAME => 'CustId',
                       ATTR_TYPE => 'NUMBER'); 
  DBMS_RLMGR.ADD_ELEMENTARY_ATTRIBUTE (
                       EVENT_STRUCT => 'AddHotel',
                       ATTR_NAME => 'Type',
                       ATTR_TYPE => 'VARCHAR2(20)'); 
  . . . 
  DBMS_RLMGR.ADD_ELEMENTARY_ATTRIBUTE (
                       EVENT_STRUCT => 'AddHotel',
                       ATTR_NAME => 'AddlInfo',
                       ATTR_TYPE => 'CLOB',
                       TEXT_PREF => EXF$TEXT('LEXER hotelreserv_lexer')); 
END;

The rule conditions specified for the previous event structure can now include text predicates on the AddlInfo attribute shown as follows.

Type = 'Luxury' and CONTAINS (AddlInfo, 'Disney World') = 1

The event structure created with one or more text attributes could be part of composite event structure so that you can specify the text predicates on the individual primitive events as follows.

<condition>
        <and equal="Car.CustId, Hotel.CustId">
           <object name="Car"> carType = 'Luxury' </object>
           <object name="Hotel"> Type = 'Luxury' and
                          CONTAINS (AddlInfo, 'Disney World') = 1 </object>
        </and>
     </condition>

In the case of rules specified for composite events, the predicates involving text attributes are not allowed in the join clauses of the rule condition. The use of CONTAINS operator is only valid within the primitive event conditions. The text predicates in the rule conditions are processed using the CTXRULE index that is implicitly created for each text attribute. Unlike other forms of indexes, the CTXRULE index is not transactional in nature. That is, any modifications made to the rule conditions are not automatically reflected in the corresponding CTXRULE indexes. This could result in incorrect matching of events with rule conditions until you synchronize the text indexes with the updated rule conditions. You can synchronize all the text indexes associated with a rule class with the following command.

BEGIN
  DBMS_RLMGR.SYNC_TEXT_INDEXES (rule_class => 'CompTravelPromo');
END;

The user must have the EXECUTE privilege on the CTX_DDL package in order to run the previous command.

4.5 Disabling and Enabling Rules

Often there is a need to add rules to the rule class and keep them disabled. Such rules still belong to the rule class and they can be enabled at a later point in time. For this purpose, you can create a rule class table with DBMS_RLMGR.CREATE_RULE_CLASS procedure that implicitly has an rlm$enabled column in which to store the status of each rule. In the case of a rule class resulting from an upgrade of an Oracle 10g database, this column does not exist and thus the rules in such rule classes cannot be disabled. The rlm$enabled column in the rule class table defaults to a value of Y to indicate that a rule by default is always enabled. Optionally, a value N can be assigned to this column during the insert of a new rule or update of an existing rule. A rule with N assigned to the rlm$enabled column is disabled and it cannot match any incoming events. Any modification to the rlm$enabled column (to enable or disable the rule) or a modification to the rule condition itself discards any intermediate state information associated with the rule. In effect, when an existing rule is enabled after being disabled, it is equivalent to a new rule with no prior state information.

4.6 Shareable Primitive Rule Conditions

The rules defined for composite events have conditions on individual primitive events and a join condition that relates these primitive events. In many rule-based applications, multiple rule conditions involving composite events use the same conditional expressions on the primitive events. For example, in the Travel Services application described in Section 2.4, a vacation in Orlando is defined as a round trip to Orlando with a minimum stay of 4 days (ToCity = 'Orlando' and Return-Depart >= 4). The same vacation in the Orlando scenario can be combined with a primitive event condition capturing a Luxury car rental and another condition capturing a car rental with a child seat option to form two different rule conditions. For such applications, Rules Manager has provisions to share parts of the rule condition across rules by using references into primitive rule condition repositories. Within a repository, each primitive rule condition has a unique identifier that can be referenced from one or more rules sharing the primitive condition. The ability to share primitive conditions simplifies the construction of the rule conditions for composite events and also allows managing them as one logical unit for any modifications made to the shared primitive rule condition.

The shareable rule conditions are associated with a primitive events structure and they do not belong to a particular rule class. So, a common list of rule conditions defined for a primitive event structure can be shared across multiple rules in a rule class as well as rules defined in multiple rule classes (configured with the same primitive event structure).

In addition to the basic steps for creating the event structure, the rule class, and the action callback procedure, a rules application with sharable primitive rule conditions has the following steps:

  1. Create a primitive rule conditions repository for a given object type (to be configured as a primitive event structure) or an existing primitive event structure.

    BEGIN
      dbms_rlmgr.create_conditions_table(
            cond_table    => 'FlightConditions',
            pevent_struct => 'AddFlight');
    END;
    

    The previous step creates a relational table to store the primitive rule conditions. This table is created with the user-specified name (FlightConditions) and it has a set of columns to store the unique identifier (primary key) for each rule condition (rlm$condid), the rule conditions (rlm$condition), and their descriptions in plain text (rlm$conddesc).At the time of operation, if the primitive event structure specified for the primitive event argument is just an object type in the database and thus not associated with a rule class, the object type is converted into an event structure and it is later assigned as expression metadata to the rlm$condition column.

    Note:

    There can only be at most one primitive rule conditions table associated with an event structure.
  2. Insert a primitive rule condition into the table created in Step 1. The values stored in the condition column (rlm$condition) are automatically validated using the event structure associated with it.

    INSERT INTO FlightConditions (rlm$condid, rlm$conddesc, rlm$condition)
     VALUES ('OrlandoVacation', 'Vacation in Orlando',
             'ToCity = ''Orlando'' and Return-Depart >= 4');
    
  3. Once you create one or more rule classes using the primitive event structure (AddFlight), the rules added to the rule classes can refer to the conditions in the corresponding primitive rule conditions table (FlightConditions). This is done by assigning the primary key of a shared primitive rule condition to the ref attribute of the corresponding object element within the rule condition.

    INSERT INTO CompTravelPromo
      (rlm$ruleid, promoType, offeredBy, rlm$rulecond) VALUES
      ('PARKS_PROMO', 'TICKETS','THEME_PARKS_ASSOC',
       '<condition>
          <and join="Flt.CustId = Car.CustId">
            <object name="Flt" ref="OrlandoVacation"/>
            <object name="Car" ref="LuxuryCarRental"/>
          </and>
        </condition>');
    

    In the previous rule definition, the primitive rule condition references OrlandoVacation and LuxuryCarRental are resolved through the event structure names (AddFlight, AddRentalCar respectively) to the corresponding primitive rule condition tables and the primary keys within those tables. Multiple rules in the CompTravelPromo table can refer to the same primitive rule condition.

    The primitive rule condition references within a rule condition for composite event are resolved at the time of rule definition. The runtime characteristics of such rules are similar to those of rules with in-place primitive rule conditions and the steps involved in evaluating the rules remain unchanged.

    Note:

    When a primitive condition that is shared by one or more rules is updated, the changes are propagated to all the rules referring to it. Effectively, the rules themselves are considered updated and any intermediate state associated with these rules is discarded.

    A primitive rule condition cannot be deleted when one or more rules in one or more rule classes refer to it. You cannot use a SQL DROP TABLE command to drop the primitive rule conditions table. You must use the DBMS_RLMGR.DROP_CONDITIONS_TABLE procedure instead. A primitive conditions table may not be truncated (with SQL TRUNCATE TABLE command) if a rule class is configured with the corresponding primitive event structure.

    The list of rule conditions that have references to conditions defined in a conditions table can be obtained by joining the rule class table with the condition table using a join predicate with the DBMS_RLMGR.CONDITION_REF function. Given a rule condition and a primitive event name, this function returns the identifier (key) for the condition reference. This function returns NULL if the rule condition does not use a reference for that primitive event. The following query identifies all the rule conditions that refer to any shared conditions stored in the FlightConditions table.

    select ctp.rlm$ruleid from CompTravelPromo ctp, FlightConditions fc
    where dbms_rlmgr.condition_ref(ctp.rlm$rulecond, 'FLT') = fc.rlm$condid; 
    

    The previous query uses a functional index defined to retrieve rows from the rule class table based on the condition references they use. Note that if the rule class is configured for duplicate primitive events of the same type, the previous query should include multiple join predicates (combined with disjunctions). Also note that the primitive event name passed to the CONDITION_REF function must be case-sensitive for the previous query to benefit from the functional index. When a primitive event name requires quotes to preserve the case or special characters in the name, the quoted name must be passed to the CONDITION_REF function.

Note:

When a rule class with one or more condition references is exported, the corresponding conditions tables are not automatically exported. The conditions table can be explicitly exported using the tables clause of the EXPORT command. The conditions tables are implicitly included in a schema export. During an IMPORT operation, all the references in the rule conditions are resolved using the conditions table that existed prior to import or that are exported with the rule class. The import of a rule class fails with an ORA-41704 error message when one of its rules refers to a missing conditions table or a condition. In such cases, the rules with invalid references are marked invalid by storing the value F under the corresponding RLM$ENABLED column.

4.7 Events Through Continuous Query Notification (Formerly Database Change Notification)

In 10g Release 2, when the event structure used for a rule class is defined with one or more table alias attributes, the rule class can be configured to treat all INSERT (UPDATE and DELETE enabled in 11g) operations on the underlying tables as the events for which the rules are evaluated (see Section 3.7 and Section 4.1). You specify this using the DMLEVENTS property at the time of rule class creation. In this case, the row level triggers on the relational tables capture the events and invoke the PROCESS_RULES procedure from within the trigger body. As the rules are processed as part of DML operations, this configuration poses some restrictions on the types of rule actions possible (for example, rule actions cannot commit) and the AUTOCOMMIT policy for the rule class. Also, a long running transaction holding some locks on the matching rules in a rule class can often lead to deadlocks.

Identifying the events after committing the DML operations is often desirable to avoid the side effects of DMLEVENTS configuration. Rules Manager provides an option to process the rules for the net data changes within a transaction after the end of the transaction. In this case, Rules Manager makes use of the continuous query notification (formerly database change notification) feature (see Oracle Database Advanced Application Developer's Guide) to receive notifications of net data changes (within a transaction) after the end of each transaction. These notifications are used to capture the modified rows or the event data and match them with the rules in the rule class.

A rule class using an event structure with one or more table alias attributes can be configured for continuous query notification (CNF) events with the CNFEVENTS property at the time of rule class creation. The rule class can be configured to treat just INSERT notifications or all INSERT, UPDATE, and DELETE notifications as events with CNFEVENTS="I" or CNFEVENTS="IUD" specifications respectively. The configuration CNFEVENTS="I" is ideal for append-only databases. The user creating a rule class with the CNFEVENTS property should be granted the CHANGE NOTIFICATION privilege and the execute privilege on the DBMS_CHANGE_NOTIFICATION package. A rule class cannot be configured for both DML events and CNF events. Using a combination of table alias and embedded primitive event types in the composite event structure, a rule class can be configured to obtain a subset of the events automatically through continuous query notification while others are explicitly added by the application.

Unlike in the case of DMLEVENTS, where the rules are processed synchronously with a DML operation, a CNFEVENTS configuration processes the rules asynchronously after the commit of a transaction. Since the order in which the continuous query notifications for a set of transactions are processed is not guaranteed, rules that are sensitive to the order of events may yield inconsistent results. Also, the version of the row picked up at the time of rule evaluation could be different from the version of the row at the end of transaction (with potential race conditions). By picking the latest version of the row for rule evaluation, it is ensured that the rule class with CNFEVENTS="IUD" configuration has the correct persistent state information after all the events (notifications) are processed.

4.8 Collection Events

A class of rule-based applications requires support for conditional expressions on collections of events as opposed to individual events. The rule conditions in such applications compute aggregate values over a finite but potentially large number of primitive events of the same type and specify predicates on the resulting aggregates. For this purpose, primitive events of a specific type are grouped based on certain event attributes and aggregate operators such as SUM, AVG, MIN, MAX, and COUNT on the other event attributes are used to apply predicates. For example, a rule condition may test the sum of amounts transferred from a particular account. In this scenario, if each bank transaction is an individual event, these events are grouped based on the account identifier and the predicate is specified on the sum of the amounts (SUM(amount) > 10000).

Rules Manager supports aggregate operators in rule conditions with the use of collection events. A collection event consists of one or more primitive events of a specific type grouped by one or more event attributes and optionally satisfying user-specified conditions described with the having clause and/or a text node within the collection element. For example, a collection event could represent a set of BankTransaction events that share a common account identifier attribute and for a withdrawal type. The items needed to define a collection event include at least one primitive event structure, a composite rule class enabled for collection events, a composite event, and a named collection specified by a <collection> element in a rule condition as follows:

<condition> 
  <collection name="bank" groupby = "subjectId" 
                          having  = "SUM(amount) > 10000">
      tranType = 'Withdrawal'
  </collection>
</condition>

The name attribute of the <collection> element restricts the type of primitive events considered for the collection and the value specified for the groupby attribute combined with predicates on the other event attributes define the properties that are common across all the primitive events in the collection. The having attribute specifies the aggregate predicates that should be evaluated for the events in the collection. A rule condition involving a <collection> element can be viewed as operating as a standard SQL query with WHERE, GROUP BY and HAVING clauses. For example, the preceding rule condition can be mapped to the following SQL query on the conceptual Transactions table.

SELECT DISTINCT subjectId FROM Transaction 
WHERE tranType = 'Withdrawal'
GROUP BY subjectId
HAVING SUM(amount) > 10000

In the preceding rule condition, each bank transaction primitive event is tested for the Withdrawal transaction type and the matching primitive events are grouped based on their subjectId attribute resulting in one collection event for each distinct subjectId.

4.8.1 Setting a Fixed Window Size or Length to Restrict the Number of Primitive Events

The primitive events participating in a particular collection may be further restricted using moving window semantics. Rules Manager supports two types of moving windows with collection events:

  • Fixed window length: The window length for a collection is specified as n units of time (fraction of a day). A collection with a fixed window length only consists of the primitive events that are generated within the last n units of time. Any primitive event generated prior to this time are not considered for evaluating the aggregate conditions. With a windowlen="1" specification in the following example, the SUM is computed only for the bank transactions that are generated within 24 hours of the last event in the collection. This rule identifies the situation where over $10,000 is withdrawn from an account within the past 24 hours.

    <condition>
           <collection name="bank" groupby = "subjectId" 
                                   having  = "SUM(amount) > 10000"
                                   windowlen ="1">
              tranType = 'Withdrawal'
           </collection>
    </condition>
    
  • Fixed window size: The window size for a collection is specified as n number of primitive events. A collection with a fixed window size specification only consists of the most recent n primitive events that belong in that collection. With a windowsize="10" specification in the place of the windowlen specification in the preceding example would compute the SUM for the last 10 withdrawal transactions for each account.

4.8.2 Using Collection Primitive Events to Form Composite Events

With some restrictions, a rule condition can combine a collection event with other collection events or primitive events to form composite events involving collections (see Section 5.6). You can use the basic rule condition syntax for composite events to relate one collection with other events within a composite event.

Unlike in the case of rule conditions involving set semantics (see Section 5.4), the number of primitive events participating in the rule conditions through collections is not restricted by the event structure definition. A subset of the primitive event types within a composite event are configured for collections and each rule condition in the corresponding rule class can consider varying number of primitive events using varying window specifications. Consider a Law enforcement application that relates BankTransaction, Transportation, and FieldReport events to raise some security alerts (see Section 10.1). In this application, if there is a need to specify aggregate predicates on BankTransaction events, the rule class created with the LawEnforcement composite event structure should be configured as follows.

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">
            <collection type = "BankTransaction"
                        groupby = "subjectId, tranType"/> 
          </composite>');
END;
/

For each primitive event type participating in collections, the rule class properties should include a <collection> element with the name of the type and a groupby specification. The groupby specification lists all possible groupby attributes expected with this primitive event. The rule class created with the preceding command can include rule conditions that group bank transactions just on the subjectId or transType attributes or a combination of these two attributes, (subjectId, transType). Note that grouping of events could also be based on some expression involving the attributes in the event structure. For example, if some rules need to group the events based on the region from which the events originated, a user defined function, which maps a country to a broader region can be included in the groupby specification. (Example: groupby = "subjectId, tranType, regionOf(fundFrom)" ).

The use of a <collection> element in the place of an <object> element in rule class properties enables the specific event type for collections. The <collection> element can also include the attributes that are allowed with the <object> elements such as consumption and duration. A rule class configured for collection events internally uses some additional database objects to maintain the incremental state information pertaining to collections. Such rule classes can store and manage rule conditions involving individual events as well as those involving collection events.

When a rule class is configured for collections involving specific primitive event type, the corresponding rules can create collection events out of individual primitive event instances using the <collection> element within the rule condition syntax for composite events. The rule condition syntax for collection events has provisions for grouping a set of primitive events to form collection events and for testing aggregate predicates on these events. The attributes over which the primitive events are grouped is a subset of the attributes listed in the rule class properties for the given event type. Each rule in the rule class may use a different groupby specification for the collection event. The aggregate predicates for the collection events are specified using the SQL operators COUNT for counting the number of events, AVG for computing the average value for an attribute, SUM for computing the sum of certain attribute, MIN for computing the minimum values for an attribute, and MAX for computing the maximum values for an attribute. The aggregate predicates expressed in SQL-HAVING clause syntax are assigned to the having attribute of the <collection> element.

<condition>
       <collection name="bank" groupby = "subjectId" 
                               having  = "SUM(amount) > 10000 or COUNT(*) > 10"
                               windowlen ="1">
          tranType = 'Withdrawal'
       </collection>
</condition>

Unlike the primitive events that are shared across multiple rules that match the event, a collection event is specific to the rule matching it. Based on the number of unique combinations of the attributes the primitive events are grouped on, one rule condition may have multiple collection events associated with it. These collection events are maintained as some primitive events are added to the collection or (dropped for the collection owing to window specification). Each collection event and the corresponding aggregate values are computed incrementally and the resulting state is stored persistently in the database. Note that the aggregate values are computed only upon the arrival of a new event and a primitive event dropping out of a window due to elapsed time does not force the computation.

When a rule condition involving collections evaluates to true, the corresponding action can be executed using the action callback mechanism or the results views as discussed in Section 2.4 and Section 2.6. For the action execution, an instance of the collection event is passed into the callback procedure. The collection event is of the same type as the primitive events of which it consists. However, in the collection event, only the attributes on which the events are grouped (native attributes from the collections's GROUP BY clause) are initialized, while the rest are each set to NULL. For example, a collection event matching the previous rule condition will be an instance of BankTransaction type that only has the subjectId (known to be common across all primitive events in the collection) initialized. In order to provide access to the aggregate values computed for the collection event, the action callback procedure (and the results view) is created with an additional argument for passing in the collection event identifier (ROWID type). This event identifier is passed into the DBMS_RLMGR.GET_AGGREGATE_VALUE call to fetch the computed values for an aggregate function such as SUM(amount).

CREATE OR REPLACE PROCEDURE LawEnforcementCBK (
    bank        BankTransaction,
    bank_evtid  ROWID,   -- event identifier for the "bank" collection events --
    transport   Transportation,
    fldrpt      FieldReport,
    rlm$rule    LawEnforcementRC%ROWTYPE) IS 
BEGIN
  .. 
  dbms_rlmgr.get_aggregate_value(rule_class  => 'LawEnforcementRC', 
                                 event_ident =>  bank_evtid, 
                                 aggr_func   =>  'SUM(amount)'); 
END;

Note that the DBMS_RLMGR.GET_AGGREGATE_VALUE call returns a non-null value only if the signature of the aggregate function passed in matches one of the aggregate operators computed for that collection.

4.8.3 Collection Events Have NULL Values Stored in its rlm$CrtTime (Timestamp) Attribute

Since the collection event is created over a period of time, there is no precise timestamp associated with such an event. A null value is stored in its rlm$CrtTime (timestamp) attribute and thus operations involving this attribute (such as SEQUENCE) are invalid. For the same reason, a duration policy that is specified as elapsed time has no impact on collection events. Note that when you configure the rule class with SESSION or TRANSACTION event duration policies, the collection events are also expired at the end of SESSION or TRANSACTION respectively. Since a collection event is private to a rule, consuming such an event (using an EXCLUSIVE or RULE consumption policy) will reset the collection (empty the collection) and does not impact the number of rules that are executed. Recall that when multiple rules evaluate to true with a primitive event (no use of collections), consuming the event by one or more of these matching rules will automatically stop the action execution for the other rules.

When the rule conditions with collection constructs coexist with the rule conditions with individual primitive events (no collections), the consumption of the primitive events owing to the EXCLUSIVE or RULE consumption policy does not drop the primitive event from the existing collection events. Similarly, when the primitive events expire due to an elapsed time duration policy, the collection events depending on this event are not impacted.

A rule class can be configured for multiple primitive event types that are collections. However, in this release, the primitive events modeled as table aliases to some relational table cannot be configured as collections. Also, the composite event structure used for the rule class may not have multiple primitive events of the same type.

4.9 Performance Tuning

Tuning a rule class for optimal performance falls into three broad areas:

Tuning Expression Filter Indexes

A rule class created for simple or composite events implicitly creates one or more Expression Filter indexes to process the rule conditions for incoming events. These default indexes, created at the time of rule class creation, assume that predicates with all scalar attributes in the event structures are equally likely in the rule conditions and this assumption may not hold true for most applications. The performance of a rules application can be improved by tuning the indexes to the specific workload. This is possible either with the domain knowledge or by analyzing a representative workload from the rules application.

When using the domain knowledge to tune the Expression Filter indexes created for a rule class, treat the primitive event structures (or a simple event structure) as the Expression Filter attribute sets (see Section 11.2).

The default index parameters associated with an attribute set can be obtained by querying the USER_EXPFIL_DEF_INDEX_PARAMS view and they can be changed using the DBMS_EXPFIL.DEFAULT_INDEX_PARAMETERS call (see Section 12.6). These default index parameters are used any time a corresponding Expression Filter index is created. The default indexes created for a rule class can be dropped using the DBMS_RLMGR.DROP_EXPFIL_INDEXES call and they can be recreated to use the user assigned index parameters using the DBMS_RLMGR.CREATE_EXPFIL_INDEXES call.

When using a workload to tune Expression Filter indexes created for a rule class, the most common predicate constructs in the rule conditions can be identified by collecting statistics on a representative set of rules already defined in the rule class. The Expression Filter indexes are created from these statistics by setting the coll_stats argument of the DBMS_RLMGR.CREATE_EXPFIL_INDEXES call to YES.

When the event structure used for a rule class has one or more XMLType attributes, the default Expression Filter indexes and the indexes created from statistics are not optimized for the XPath predicates on these attributes. Hence, the XPath index parameters should be explicitly assigned to the event structure using the DBMS_RLMGR.DEFAULT_XPINDEX_PARAMETERS call as discussed in Section 13.2.4.

Create Rule Class Interface Package

A way to improve the runtime performance of a rules application is to create a rule class interface package that is specific to the rule class. This avoids the overhead involved in using the generic DBMS_RLMGR package. The DBMS_RLMGR procedures used for the run time operations such as processing the rules for some events, consuming the events and resetting the session make use of the rule class name passed in as one of the arguments and map them to the corresponding operations on the rule class. This step can be avoided by creating a rule class interface package that is used to directly operate on the rule class. The rule class interface package is most effective when the rules in the rule class are selective or they often do not match any incoming events. This package is created using the DBMS_RLMGR.CREATE_INTERFACE call and this has a set of procedures to perform all runtime operations on the rule class. See the DBMS_RLMGR.CREATE_INTERFACE call in Oracle Database PL/SQL Packages and Types Reference for additional information.

4.10 Database State in Rule Conditions

The predicates in a rule condition may use user-defined functions, references to database table data, and database state information. In the case of a condition specified for a simple or a primitive event, the corresponding predicates are evaluated using the state information at the time the event is added to the rule class (using either the PROCESS_RULES or the ADD_EVENT call. This is the case even for conditions specified for individual primitive events within a composite event. So, when multiple primitive events are used to capture a composite event, the predicates associated with individual primitive events are evaluated at different times, corresponding to the occurrences of their respective event. Only the predicates specified in the join attribute of the composite condition are evaluated at the time of composite event creation. So, this aspect should be considered when using database state or schema object references in the rule conditions.

4.11 Resetting Events for Development Environments

When developing rule applications using Rules Manager, rules defined in the rule class can be tested using some hypothetical events. Because these events could match some rules in the rule class partially, they could contribute to the incremental states stored in the database. So before you deploy your application in a production environment, you must purge this partial state information so as not to cause any unexpected rule actions. Use the DBMS_RLMGR.PURGE_EVENTS procedure call to purge any state information and the events from the database prior to deploying the application in a production environment.