RuleWorks

Persistant Data Storage

This chapter describes the interface between SQL (structured query language) and RuleWorks. The SQL interface allows you easily to read data from a database into RuleWorks working memory, and write values from working memory into a database.

 

Note: In the current version of RuleWorks, the only supported database is VAX Rdb/VMS.

This chapter covers the following topics:

 

We assume that you are familiar with SQL concepts and statements. If not, please refer to the VAX Rdb/VMS documentation, especially the DEC Rdb Introduction to SQL and the DEC Rdb Guide to SQL Programming.

    1. SQL Expression Syntax SQL Expression Syntax
    2. The SQL interface consists of a set of RHS actions that generate the appropriate dynamic SQL statements (see the following table, SQL Statements Generated by RuleWorks Actions). The arguments to the RHS actions are passed to the SQL statements unchanged. For example, the following RuleWorks action:

       

      (sql-fetch-as-object select field1, field2 from table1 where field1 < field2)

      generates the following dynamic SQL statement:

       

      SELECT FIELD1, FIELD2 FROM TABLE1 WHERE FIELD1 < FIELD2

      Note that the select expression must start with SELECT spelled out in full, not abbreviated.

      Table -1. SQL Statements Generated by RuleWorks Actions

      RHS Action
      SQL Statement Description

      SQL-ATTACH database-spec [dbkey-scope] Specifies the database that is to be DECLARE SCHEMA database-spec accessed by the other RuleWorks SQL DBKEY SCOPE IS dbkey-scope actions.

      SQL-COMMIT Completes the current SQL transaction
      COMMIT the current SQL and makes permanent any changes made during the
      transaction.

      SQL-DELETE table-name [where-clause] Deletes specified records from the
      DELETE FROM table-name where-clause database.

      SQL-DETACH Commits any outstanding transaction
      FINISH and detaches from the database.

      SQL-FETCH-EACH<var>...select-expr (rhs-action)... Binds field values to RuleWorks variables
      select-expr and executes RuleWorks actions that can
      use those variables.

      SQL-FETCH-AS-OBJECT select-expr Makes WMOs from database records.
      select-expr

      SQL-INSERT table-name sql-expr Stores new records in the database.
      INSERT INTO table-name sql-expr

      SQL-INSERT-FROM-OBJECT <$id-var> Stores the contents of a WMO
      SQL-INSERT-INTO table-name (field-names) in a new database record.
      SQL-INSERT-INTO )VALUES (field-values)

      SQL-ROLLBACK Completes the current SQL transaction
      ROLLBACK and undoes any changes made during the
      transaction.

      SQL-START [txn-options] Starts an SQL transaction and sets
      SQL-SET TRANSACTION txn-options transaction options.

      SQL-UPDATE table-name set-clause [where-clause] Modifies existing database records.
      SQL-UPDATE table-name set-clause where-clause

      SQL-UPDATE-FROM-OBJECT <$id-var> [where-clause] Modifies existing database records,
      SQL-UPDATE table-name set-clause where-clause using the contents of a WMO.

       

      1. Using Vertical Bars ( | ) Using Vertical Bars ( | )

To make the process more efficient, you can use vertical bars (the RuleWorks quote character, | ) around the atoms that are passed to SQL. For example:

 

(sql-fetch-as-object |select field1, field2 from table1 where field1 < field2|)

In the action above, the RuleWorks parser makes a single atom out of the entire select expression. The same length restrictions apply to quoted atoms in select expressions as in other RuleWorks code (see Chapter 2). You cannot use vertical bars around a multiline SQL expression; you must use a pair of vertical bars for each line. For example:

 

(sql-fetch-as-object |select field1, field2|

|from table1|

|where field1 < field2|)

Vertical bars are required in the following circumstances:

 

(sql-insert table1 |(field1) values (| 'text' |)|)

generates this SQL statement:

 

INSERT INTO TABLE1 (field1) values ('text')

      1. Using Variables Using Variables
      2. Variables must be surrounded by white space to allow the RuleWorks parser to recognize them as variables. A variable name followed immediately by a comma looks to the parser like an atom instead of a variable to be evaluated. In the following example:

         

        <var1>, <var2>

        the RuleWorks parser treats <VAR1>, as a symbol and <VAR2> as a variable. The next example:

         

        <var1> , <var2>

        results in the expected behavior.

      3. Using Single Quotes (') Using Single Quotes (')
      4. Anything that SQL treats as a character string must be enclosed in single quotes ('). This applies to both atoms and variables. Quoted variables must have at least one white space character before the opening quote and after the closing quote.

        Quoted variables expand to the variable value surrounded by single quotes. Quoted variables that are bound to compound values expand to the list of compound elements surrounded by a single set of single quotes. The elements of the compound are not quoted. For example, assuming <COMPOUND2> is bound to the value (COMPOUND SOME MORE TEXT), the following RHS argument:

         

        '<compound2>'

         

        is passed to SQL as the literal:

         

        'SOME MORE TEXT'

      5. SQL Data Types SQL Data Types
      6. The following table, SQL Data Types Supported in RuleWorks, shows the mapping between SQL and RuleWorks data types.

        Table -2. SQL Data Types Supported in RuleWorks*

        SQL Data Type Converted to RuleWorks Data Type

        CHAR SYMBOL

        VARCHAR SYMBOL

        SMALLINT INTEGER

        INTEGER INTEGER

        QUADWORD SYMBOL

        FLOAT FLOAT

        DOUBLE FLOAT

        DATE SYMBOL

        * RuleWorks has no way to represent double-precision floating-point numbers or integers larger than 32 bits.

      7. Examples of SQL Expressions Examples of SQL Expressions

This section contains further examples of RHS actions and the SQL statements they generate. All the examples in this section assume the following variable bindings:

Table -3. SQL Variable Bindings

Variable Value Bound to

<simple1> SELECT

<simple2> 10

<simple3> | 'text' |

<simple4> TEXT

<compound1> (COMPOUND SELECT * FROM W2 WHERE SI = 10)

<compound2> (COMPOUND SOME MORE TEXT)

 

In the following example, six actions are equivalent, but the second is the most efficient:

Example -1. SQL Expression - Equivalent Actions

(SQL-FETCH-AS-OBJECT SELECT * FROM W2 WHERE SI = 10)

(SQL-FETCH-AS-OBJECT |SELECT * FROM W2 WHERE SI = 10|)

(SQL-FETCH-AS-OBJECT SELECT * FROM W2 WHERE SI = <simple2>)

(SQL-FETCH-AS-OBJECT <simple1> * FROM W2 WHERE SI = <simple2>)

(SQL-FETCH-AS-OBJECT <simple1> |* FROM W2 WHERE SI =| <simple2>)

(SQL-FETCH-AS-OBJECT <compound1>)

The SQL statement generated by the above six actions is shown below:

SELECT * FROM W2 WHERE SI = 10

Example -2. SQL Expression - Insert Into Table

(sql-insert table-name |(FIELD1) VALUES (| <simple3> |)|)

INSERT INTO TABLE-NAME (FIELD1) VALUES ( 'text' )

 

Example -3. SQL Expression - Insert Table Name

(sql-insert table-name (FIELD1) VALUES ( <simple2> ))

The RuleWorks parser stops at the unquoted parentheses and does not generate any SQL statement.

Example -4. SQL Expression - Insert Text Into Table Name

(sql-insert table-name |(FIELD1) VALUES (| <simple3> '<simple4>' |)|)

INSERT INTO TABLE-NAME (FIELD1) VALUES ( 'text' 'TEXT' )

 

Example -5. SQL Expression - Insert More Text Into Table Name

(sql-insert table-name

|(FIELD1, FIELD2, FIELD3, FIELD4)|

|VALUES (10, 'text','TEXT', 'SOME MORE TEXT')|)

INSERT INTO TABLE-NAME (FIELD1, FIELD2, FIELD3, FIELD4) -

VALUES (10, 'text','TEXT', 'SOME MORE TEXT')

 

Note that the RuleWorks-SQL interface does not actually generate multiline statements containing continuation characters (-). Multiline statements are shown here for clarity of the examples..

Example -6. SQL Expression - Multiline Statements

(sql-insert table-name

|(FIELD1, FIELD2, FIELD3, FIELD4) VALUES (|

<simple2> , <simple3> , '<simple4>' ,

'<compound2>' |)|)

INSERT INTO TABLE-NAME (FIELD1, FIELD2, FIELD3, FIELD4) -

VALUES ( 10 , 'text' , 'TEXT' , 'SOME MORE TEXT' )

This SQL action is the same as in the above example, except for the lack of white space between the variables and the commas. RuleWorks does not report any errors in the action below, but passes symbols to SQL rather than values:

Example -7. SQL Expression - Passing Symbols to SQL

(SQL-INSERT table-name

|(FIELD1, FIELD2, FIELD3, FIELD4) VALUES (|

<simple2>, <simple3>, '<simple4>', '<compound2>' |)|)

INSERT INTO TABLE-NAME (FIELD1, FIELD2, FIELD3, FIELD4) -

VALUES ( <SIMPLE2>, <SIMPLE3>, '<SIMPLE4>', -

'SOME MORE TEXT' )

If SQL detects an error in the generated SQL statement, the interface creates an instance of class SQL$MSG. See the section of this chapter, Error Handling, for details on message WMOs.

    1. Mapping Data to Working Memory Objects Mapping Data to Working Memory Objects
    2. The fetch, insert, and update actions come in two forms: simple and flexible. The simple forms require a one-to-one mapping between object class names and database table names, and between attribute names and database field names. The flexible forms have no mapping requirement.

      1. One-to-One Mappings One-to-One Mappings

The simple forms of the SQL fetch, insert, and update actions are listed below:

 

The syntax for these actions is much simpler than the syntax for the flexible SQL actions, because an automatic mapping from WMOs to SQL records is performed. There must be a database table name that exactly matches the object class name; there must also be some database field names that match attribute names. A one-to-one correspondence is shown in the following comparison of an OBJECT-CLASS declaration in RuleWorks and a CREATE TABLE statement in SQL:

Table -4. One-to-One Mappings

RuleWorks SQL

(OBJECT-CLASS part create table part
^partnumber
(partnumberchar (10),
^name namechar (63),
^price) price double);

The following simple fetch action is based on the declaration and statement shown above:

Example -8. Fetch Action

; to fetch a particular part number

; the part number is the symbolic value bound to <my-part>

(sql-fetch-as-object select * from part where partnumber = '<my- part>')

Exceptions to the one-to-one correspondence can be achieved easily by defining a view of the database, or by using more complex SQL select expressions. Note however that updates or inserts to multitable views are not supported. (See the section of this chapter titled, Using Views to Fetch Data, for more information on views.)

You can have more attributes in the object class than fields in the database table, or more fields than attributes. The simple fetch action, SQL-FETCH-AS-OBJECT, ignores fields that do not correspond to attributes. Attributes that do not correspond to fields are given their default value, if any, or the atom NIL. Similarly, the simple insert action SQL-INSERT-FROM-OBJECT ignores attributes that do not correspond to fields. Database fields that do not correspond to attributes are set to their default value, if any, or to "missing."

The SQL interface preserves "missing" database field values. When SQL-FETCH-AS-OBJECT makes an object from a database table that has "missing" field values, it sets the corresponding attribute values to NIL. Conversely, when SQL-INSERT-FROM-OBJECT makes a database record from an object that has NIL attribute values, it sets the corresponding field values to "missing" (NULL). That is, NIL maps to "missing" in both directions, even if the NIL attribute value was explicitly set.

 

Note: Data values for the ^$ID and ^$INSTANCE-OF attributes are not written to the database by SQL-INSERT-FROM-OBJECT, even if the database explicitly provides fields with these names.

 

The SQL interface does not recognize class inheritance. For example, a subclass cannot be passed to SQL-INSERT-FROM-OBJECT for a table that matches a parent class. The table name must be the same as the value of the ^$INSTANCE-OF attribute.

      1. Flexible Mappings Flexible Mappings

The flexible SQL fetch, insert, and update actions allow you to specify particular database tables or fields that do not necessarily correspond to object class or attribute names. The flexible actions are listed below:

 

    1. Linking with the SQL Libraries Linking with the SQL Libraries
    2. You must link your RuleWorks application with the SQL library in order to use the SQL actions. The easiest way is to define a logical name to point to the SQL library. For example:

      $ DEFINE LNK$LIBRARY SYS$LIBRARY:SQL$USER

      $ LINK MY_FILE, RUL$LIBRARY:RUL_TRL/LIB

      (See the DEC rdb Introduction to SQL for more information on the SQL library.)

    3. Attaching to a Database Attaching to a Database
    4. Before your first database transaction, you must specify which database you want to access. You do this with an SQL-ATTACH action, which executes a DECLARE SCHEMA statement.

      The syntax of the SQL-ATTACH action is show below:

      SQL-ATTACH database-spec [ DBKEY-scope ]

      The database-spec argument identifies which database you want to access. This argument can be either the filename of the Rdb database file, or the pathname of the CDD schema source. If you specify a filename, you can use the optional keyword FILENAME. If you specify a pathname, you must use the PATHNAME keyword. You can use a logical name in either case. For example:

       

      (sql-attach my_sql_db) ;logical name for DBDISK:[DATABASE]MY_DB.RDB

      (sql-attach pathname rul_db) ;logical name for CDD$TOP.DEPT3.PERSONNEL

      The optional DBKEY-scope argument can be either TRANSACTION or ATTACH.

      Note: You can access only one database at a time. Simultaneous access to multiple databases is not supported in the RuleWorks <vnum> SQL interface.

      You can sequentially access multiple databases in one RuleWorks program execution.

      If SQL-ATTACH is executed while a database is already attached, the original attachment is terminated and the new database is attached (unless a transaction is active, in which case a warning WMO is made and the second attachment is not performed).

    5. Starting an SQL Transaction Starting an SQL Transaction
    6. In RuleWorks, explicitly starting an SQL transaction is optional if you are only going to read from the database; it is required if you are going to write to the database. The syntax for the SQL-START action is shown below:

      SQL-START [ txn-options ]

      The txn-options argument is optional: its default value is READ ONLY. This argument can include any transaction option that is valid in a SET TRANSACTION statement. For example:

       

      (sql-start read write reserving table_1 for shared read)

      If a transaction is not currently active when a fetch action is executed, SQL implicitly starts a READ ONLY transaction. The interface ends this transaction immediately after the fetch is completed.

    7. Reading from a Database Reading from a Database
    8. The RuleWorks SQL interface provides two ways to read (fetch) data from a database. The simple form, SQL-FETCH-AS-OBJECT, automatically makes new objects from selected database records.

      The flexible form, SQL-FETCH-EACH, binds the values in selected database records to variables that can then be used in whatever RHS actions you specify.

      Both forms of the fetch action use the SQL syntax for select expressions. The select expression specifies which database records are selected, and which database fields are fetched. The select expression must be a valid one that you could put in a SELECT statement. For example:

       

      select fld1, fld2 from table_1 where fld3 > 10 and fld4 = 'abc'

      select * from table_2 where fld4 = '<var>'

      Note: You must put single-quote ( ') characters around nonnumeric constants and variables. You must put at least one white space character before the opening quote and after the closing quote. However, you must not put any white space between the single quotes and a variable.

      1. Using the Simple Fetch Action Using the Simple Fetch Action
      2. The SQL-FETCH-AS-OBJECT action automatically makes a new object out of each selected database record. If the select expression causes n records to be fetched from the database, then a single execution of that SQL-FETCH-AS-OBJECT action creates n new objects. The OBJECT-CLASS name of the new objects is the name of the database table.

        The syntax of the SQL-FETCH-AS-OBJECT action is shown below:

        SQL-FETCH-AS-OBJECT select-expr

        The names of WMO attributes to be set by SQL-FETCH-AS-OBJECT must match the field names of the database table (unless a view is used to access the table, in which case it is the view's local field names that must match the OBJECT-CLASS attribute names). For example:

         

        (sql-fetch-as-object select * from part)

        The example above corresponds to the OBJECT-CLASS declaration and CREATE TABLE statement in the section of this chapter, One-to-One Mappings.

      3. Using the Flexible Fetch Action Using the Flexible Fetch Action
      4. The SQL-FETCH-EACH action binds data from selected database fields to RuleWorks variables. You can then use these variables in RHS actions inside the SQL-FETCH-EACH action to create or change instances of any declared OBJECT-CLASS. If the select expression causes n records to be fetched from the database, then the variables are bound and the RHS actions are executed n times for a single execution of the SQL-FETCH-EACH action.

        The syntax of the SQL-FETCH-EACH action is shown below:

        SQL-FETCH-EACH <variable> ... (select-expr)
        (RHS-action)...

        You can specify one or more variables as the first argument, but they must not be bound prior to the SQL-FETCH-EACH action. They can be used only in the RHS actions specified as the third argument. They cannot be used after the SQL-FETCH-EACH action.

        If you use any variables in the select expression, they must be bound prior to the SQL-FETCH-EACH action. They can be bound on either the LHS or RHS of the rule.

        You can specify one or more RHS-actions for the third argument. These actions can use the variables from the first argument as well as variables bound prior to the SQL-FETCH-EACH action. If you use a BIND action inside the SQL-FETCH-EACH action, that variable is still bound after the action executes.

        SQL interface actions are not allowed inside the SQL-FETCH-EACH action.

        Example -9. Fetching Fields from an SQL Database Fetching Fields from an SQL Database

        (rule fetch-items-from-database:software-option

        (active-context ^name fetch-items-from-database)

        (software-option ^$ID <the-part> ^is-expanded NIL

        ^$INSTANCE-OF <part-type>)

        -->

        (sql-fetch-each <partnumber> <partname> <price> <media>

        (select partnumber , name , price , media_type

        from sw_part

        where classname = '<part-type>' )

        (modify <the-part>

        ^partnumber <partnumber>

        ^name <partname>

        ^price <price>

        ^media-type <media>

        ^is-expanded YES) ))

        SQL-FETCH-EACH does tolerate a mismatch between the number of RuleWorks variables specified in the action and the number of database fields to be fetched for each database record. If more variables are specified than fields fetched, the excess variables are set to NIL; if more fields are fetched than variables specified, the excess values are just ignored. In either case, an SQL warning WMO is generated (see the section of this chapter, Error Handling).

        Given the following OBJECT-CLASS declaration:

         

        (object-class objclass ^fld1 ^fld2 ^fld3)

        In terms of the WMOs created and the final binding of the variable <FETCHED-INSTANCES>, the following two sequences of BIND and fetch actions are equivalent:

        Example -10. Bind-Fetch Sequence

        (BIND <fetched-instances> (COMPOUND))

        (SQL-FETCH-EACH <v1> <v2> <v3>

        (|SELECT FLD1, FLD2, FLD3 FROM OBJCLASS WHERE FLD4 =10|)

        (BIND <instance>

        (MAKE objclass ^fld1 <v1> ^fld2 <v2> ^fld3 <v3>))

        (BIND <fetched-instances>

        (COMPOUND <fetched-instances> <instance>)))

         

        If this is what is what you want to do, the second sequence is more efficient:

        Example -11. Bind-Fetch Sequence - 2

        (BIND <fetched-instances>

        (SQL-FETCH-AS-OBJECT

        |SELECT FLD1, FLD2, FLD3 FROM OBJCLASS WHERE FLD4 = 10|))

        Note however, that the SQL-FETCH-EACH action gives you more flexibility by allowing arbitrary RHS actions (except other SQL actions) to be performed after each fetch. Also, you are not restricted to the one-WMO-to-one-record data model. Consider the following actions that fetch the same data but place it into one working memory object:

        Example -12. Placing Fetch Data into One Working Memory Object (WMO)

        (object-class objclass

        ^fld1 COMPOUND

        ^fld2 COMPOUND

        ^fld3 COMPOUND)

        ...

        (BIND <fld1> (COMPOUND))

        (BIND <fld2> (COMPOUND))

        (BIND <fld3> (COMPOUND))

        (SQL-FETCH-EACH <v1> <v2> <v3>

        (|SELECT FLD1, FLD2, FLD3 FROM OBJCLASS WHERE FLD4 =10|)

        (BIND <fld1> (COMPOUND <fld1> <v1>))

        (BIND <fld2> (COMPOUND <fld2> <v2>))

        (BIND <fld3> (COMPOUND <fld3> <v3>)))

        (BIND <instance>

        (MAKE objclass ^fld1 <fld1> ^fld2 <fld2> ^fld3 <fld3>))

         

      5. Using Views to Fetch Data Using Views to Fetch Data

      Using SQL views to fetch data from one or more tables into a specified class of object is perfectly acceptable and easily done. However, if you are using multiple tables, you can use views only to read database records, not to insert or update database records in multiple tables. (You cannot use views that contain aggregates to write data either; see the DEC Rdb Guide to SQL Programming section on CREATE VIEW for restrictions.)

      You can define a view to achieve the one-to-one mapping of object class to database table names, or of object attributes to database field names, required by the simple forms of the fetch, insert, and update actions. For example:

      Example -13. Using Views to Fetch Data

      CREATE TABLE Y (X INTEGER,

      Z CHAR(20), ...);

      CREATE VIEW A (B, C)

      AS SELECT X, Z FROM Y;

      In this example, attribute ^B of object class A maps to field B in view A (satisfying the 1-to-1 name mapping requirement), while the view's field B in turn corresponds to field X in the underlying table Y to which the view provides access.

    9. Using Database Key Values Using Database Key Values
    10. You can fetch database key values and use them inside RuleWorks, but you cannot use them to insert or update records. The SQL interface translates database key values into character strings, such as 1:2:3, for the database area, page, and line numbers of the fetched records.

      You can declare an attribute called ^DBKEY and test whether it is NIL to find out if the object was fetched from the database or not.

      You can compare two fetched database key values for equality.

      Note: Database key values are not persistent. They are valid for only the duration of a single attachment to the database (or less if you use the default transaction scope).

    11. Writing to a Database Writing to a Database

You can write WMO attribute values to a database in one of two ways: by updating existing database records or by inserting new ones. You can also choose either the simple or the flexible form of the update and insert actions. This section describes the following RHS actions:

 

Remember that you must explicitly start all write transactions with an SQL-START action.

      1. Updating Existing Records Updating Existing Records
      2. Updating existing records modifies data fields without creating any new database records. The SQL-UPDATE-FROM-OBJECT action uses the contents of an object to modify existing database records; the SQL-UPDATE action uses constants or bound variables.

        Both update actions allow you to use the SQL syntax for WHERE clauses to specify which database records are modified. The syntax for the SQL-UPDATE-FROM-OBJECT action is shown below:

        SQL-UPDATE-FROM-OBJECT <$id-variable> [ WHERE-clause ]

        SQL-UPDATE-FROM-OBJECT modifies records in the database table whose name matches the OBJECT-CLASS of the WMO specified by the $id-variable argument. This argument also specifies which object provides the new data values for the update. If the object has attributes that do not correspond to fields in the target database table, those attributes are ignored. On the other hand, if the database table has fields that do not correspond to attributes in the object, those fields are not modified.

        For example:

         

        (sql-update-from-object <W> where fld1 = <var>)

        Note that all of the fields in the database record(s) may be modified, not just fld1. SQL-UPDATE-FROM-OBJECT uses all the attribute values for the specified RuleWorks object to modify all the corresponding data fields in the selected database records. Depending on the WHERE clause, one or more records may be updated by a single SQL-UPDATE-FROM-OBJECT action.

        The SQL-UPDATE action uses the SQL syntax for SET clauses to specify which database fields are modified. The syntax for the SQL-UPDATE action is shown below:

        SQL-UPDATE table-name SET-clause [WHERE-clause]

        The table-name argument can be a symbol or bound variable; the SET-clause argument can contain constants or bound variables. As with SQL-UPDATE-FROM-OBJECT, the WHERE-clause argument is optional. For example:

         

        (sql-update tbl set fld1 = 0 where fld2 > 10)

        Note that one or many database records may be updated by a single RuleWorks SQL-UPDATE execution. If you want to update only one record per firing of this rule, you must write a WHERE clause that restricts the selection to a single record.

      3. Inserting New Records Inserting New Records

The SQL-INSERT-FROM-OBJECT action adds to the database a single new record whose field values are the attribute values of a specified object. The SQL-INSERT action adds one or more new records to the database. SQL-INSERT-FROM-OBJECT does not remove the object whose data it stores in the database.

The syntax of the SQL-INSERT-FROM-OBJECT action is shown below:

SQL-INSERT-FROM-OBJECT <$id-variable>

For example:

 

(sql-insert-from-object <W>)

The syntax of the SQL-INSERT action is shown below:

SQL-INSERT table-name SQL-expr

The SQL-expr argument lists the field names into which values are to be inserted and the new values themselves. For example:

 

(sql-insert tbl |(| fld1, fld2 |) values (| 10, 'abc' |)|)

    1. Error Handling Error Handling
    2. The SQL interface signals error conditions by creating WMOs whose class name is SQL$MSG. In order to accept these objects, your RuleWorks program must include the following OBJECT-CLASS declaration:

      Example -14. OBJECT-CLASS Declaration

      (OBJECT-CLASS SQL$MSG

      ^SEV ; severity code

      ^COND ; condition code, or message name

      ^TEXT ; description of the error

      ^RULE) ; the name of the rule that executed the SQL action

      The following example, SQL Error Objects, shows a few sample objects of class SQL$MSG.

      Example -15. SQL Error Objects SQL Error Objects

      RuleWorks>PPWM SQL$MSG

      #54 60 [ATTACH-DATABASE:DO-IT] (SQL$MSG ^SEV W ^COND SQLATTFAI ^TEXT SQL attac

      h to database failed ^RULE ATTACH-DATABASE:DO-IT)

      #56 62 [FETCH-ITEMS-FROM-DATABASE:HARDWARE-OPTION] (SQL$MSG ^SEV W ^COND SQLFET

      PRE ^TEXT Preparation of SQL fetch statement failed ^RULE FETCH-ITEMS-FROM-DATA

      BASE:HARDWARE-OPTION)

      #60 66 [FETCH-ITEMS-FROM-DATABASE:HARDWARE-OPTION] (SQL$MSG ^SEV W ^COND SQLFET

      PRE ^TEXT Preparation of SQL fetch statement failed ^RULE FETCH-ITEMS-FROM-DATA

      BASE:HARDWARE-OPTION)

      You can write rules to process SQL$MSG objects as they are produced; you decide how, or whether, to proceed after an SQL warning. The following example, Handling an SQL Error, shows a rule that halts the program when the attachment to the database fails.

      Example -16. Handling an SQL Error Handling an SQL Error

      (rule abort-on-db-attach-failure

      (sql$msg ^cond sqlattfai ^text <text> ^rule )

      -->

      (write (crlf) |Execution of| |caused the following error:|)

      (write (crlf) <text>)

      (halt))

       

    3. Ending an SQL Transaction Ending an SQL Transaction
    4. When you end an SQL transaction, you can either apply (commit) any changes to the database made during the transaction, or you can undo them (rollback). Use the SQL-COMMIT action to apply the changes, the SQL-ROLLBACK action to undo them. Both of these actions complete the current SQL transaction. Their syntax is shown below:

      SQL-COMMIT
      SQL-ROLLBACK

      The SQL interface automatically performs an SQL-COMMIT action to terminate any transaction you started implicitly by a fetch operation.

    5. Detaching from a Database Detaching from a Database

When your program is finished using the database, it should detach from the database. The syntax of the SQL-DETACH action is shown below:

SQL-DETACH

If there is a current transaction, the SQL-DETACH action performs an implicit SQL-COMMIT action to complete it before detaching.