Application Development


Chapter 36. Runtime Transaction Manager Processing

This chapter describes transaction manager processing at runtime. It includes:


Running Transaction Manager

Once the application screen is created and its widgets, table views and links are properly defined, the screen is ready to use.

Refer to Chapter 31, "Building a Transaction Manager Screen," for instructions on building a transaction manager screen.

Opening the Screen

Processing for the transaction manager begins when you open an application screen. On screen entry, the transaction manager automatically executes the following steps:

If a named function cannot be found or if the root table view cannot be determined, an error message is issued and the transaction manager stops its processing.

Closing the Screen

When you close a screen, the transaction manager performs the necessary exit processing. This includes:

If a named function cannot be found, an error message is issued.

Viewing the Generated SQL

The following options are available for viewing the generated SQL:

Disabling the Transaction Manager

If you want to disable the transaction manager, change the screen's Root property to "-none-".


Displaying Data

The transaction manager uses two commands to display data from a database, VIEW and SELECT. These commands can be invoked whenever a database connection is active.

VIEW displays information; SELECT allows the user to modify the selected data.

Executing the Select Statement

In general, when a VIEW or SELECT command is executed, data is fetched from the database and displayed in appropriate widgets using dbms commands (as part of the TM_SEL_BUILD_PERFORM event):

This series of dbms statements is performed for each server view, which includes the table view (defined as a server view) and all table views joined to it via server links.

If the Panther targets for the select set are arrays, the first retrieved row populates the first occurrence, the second row populates the second occurrence, and so on.

Figure 36-1 illustrates a screen that lets users enter a video title by name or identification number, and view the names of the actors and their roles for the specified video. In addition, new videos can be added with the corresponding actors and roles.

Figure 36-1 Data are displayed by executing a series of DBMS statements.

The screen in Figure 36-1 contains two server views; therefore, the statements are executed twice. The first series fetches a video title and its associated price category from the titles and pricecats tables. The second series fetches the actors appearing in the video and the name of their roles.

Figure 36-2 illustrates the DB Interactions window for this screen. The titles table view has a sequential link with the roles table view; therefore, values in the titles table view (which is the parent) are used to fetch data for the child table view. The Relations property of the sequential link tells the transaction manager which widget to use to supply the value. In this example, the value in title_id is used to build a WHERE clause which fetches only the actors in that video.

Figure 36-2 The DB Interactions window displays the table views and their associated links.

Scrolling Through the Select Set

The CONTINUE command (only available on two-tier processing) in the transaction manager fetches the next set of data for the screen. For the root table view, the next row, or set of rows, is fetched. For any child table views connected by sequential links, additional SQL SELECT statements are issued, using the values from the parent table view in the WHERE clause. For each subsequent CONTINUE command, another set of data is fetched. If there are no additional rows, nothing is done.

There are two ways to allow users to scroll forward and backward through a select set. You can create scrolling widgets or a grid for displaying the data. In environments where memory is limited, you can fetch only a small number of rows to the application and buffer the rest in a disk file. This is known as using a continuation file or a store file.

To use a continuation file with transaction manager, you need to edit the Fetch Directions property for either the screen or the table view. If Fetch Directions is set to Up/Down-all modes or Up/Down-view mode, the transaction manager fetches the data to a continuation file. Then, issuing a CONTINUE_UP command displays the previous set of data, and issuing a CONTINUE_TOP command displays the first set of data.

Panther does not set backward scrolling via continuation files as the default since Panther does not update the continuation file when the onscreen data is changed. Scrolling backward shows the original, fetched data. If you set Fetch Directions to be Up/Down in all modes, be aware that once a SAVE command is issued, you need to re-execute SELECT in order to see any updated data.

Controlling the Number of Rows

The number of occurrences fetched for transaction manger is set in the Maximum Occurrences (max_occurrences) property.

The Count Select property of each server view allows you to request that the transaction manager count the number of rows in a result set and compare it to a specified threshold value before actually fetching data.

In the server view's properties, set the Count Select property and its subproperty, Count Warning, to Yes. In the Count Threshold property, specify the maximum number of rows to fetch in a result set. If the size of a result set (stored in the server view's runtime count_result property) exceeds this value, the user is prompted before the data is actually fetched.

For any command which can modify the database, such as SELECT, the transaction manager must synchronize the widgets in a server view. For more information, refer to "Updating Data in Arrays."

Customizing Select Processing

In order to customize the processing done for any table view, you can:


Updating the Database

If you execute a command that modifies data, such as NEW, SELECT, COPY or COPY_FOR_UPDATE, the transaction manager initiates before-image processing for all updatable table views. Panther's before image remembers the original values of the fetched data. Then, when you execute SAVE, the transaction model generates the necessary statements so that the database matches the current data on the screen.

The NEW command prepares the screen for data entry; it does not insert information into the database. Similarly, the SELECT command retrieves data from the database and prepares the screen to be edited by changing the screen to update mode. The changes made on the screen are not saved to the database until a SAVE command is executed.

Traversal for Database Updates

Specialized traversal patterns are used for the TM_INSERT, TM_UPDATE, and TM_DELETE requests. For these requests, the traversal pattern is determined by the link properties for the transaction tree and the operation being performed.

You can change the traversal order for the TM_INSERT, TM_UPDATE, and TM_DELETE requests by modifying the link widget's Insert Order (insert_order), Update Order (update_order), and Delete Order (delete_order) properties, indicating whether the parent (PV_PARENT_FIRST) or child (PV_CHILD_FIRST) table view should be processed first.

Updating Data

The transaction manager SELECT command queries the database for information so that it can be updated. When you execute the SELECT command, the transaction manager fetches the first screenful of data for each of the linked table views. (If you then execute the CONTINUE command, the transaction manager fetches the next screenful of data.)

Panther keeps track of the changes the user makes while the screen is in update mode. When the application executes SAVE, the transaction manager generates the statements to update the database. If the application attempts any other transaction manager operation, the transaction manager prompts the user if it should discard the changes. If the user chooses to discard, the transaction manager proceeds to the next command without changing the database. If the user chooses not to discard, transaction manager returns control to the screen. You can modify this behavior if you wish.

When before image processing is activated, each time a field is modified in some way (data is edited, data is cleared, new data is entered), the data previously in the widget is copied into memory and the transaction manager is notified that data on the screen has changed. Then, when the SAVE command is selected, the transaction manager looks at the changes and determines which statements are necessary to update the database so that it matches what is currently on the screen.

Updating Data in Arrays

For any command which can modify the database, such as SELECT, NEW, COPY and COPY_FOR_UPDATE, the transaction manager must synchronize the widgets in a server view. This ensures that any updates occur on the same occurrence of each widget in the server view. Each time the SELECT, NEW, COPY and COPY_FOR_UPDATE commands are chosen, the transaction manager attempts to synchronize the widgets in a server view if:

If you get a synchronization error, check to see if the widgets can be set to the same number of occurrences. If this is not possible, review the Use In Select, Use In Insert, and Use In Update properties for each widget to see if they can be changed. Another property change you can make is setting the Synchronization property to No.

However, changing the Synchronization property to No does not change the way Panther fetches data to arrays. The number of rows fetched from the database equals the least number of occurrences set for any widget in the server view whose Use In Select property is set to Yes.

Using Multi-text Widgets

For multi-text widgets with the Word Wrap property set to Yes (the default setting), you need to set the Maximum Occurrences (max_occurrences) property.

Changing the Primary Key

If you change value of a primary key, the transaction manger first deletes the row associated with the old value and then inserts a row with the new value.

You can change this behavior by setting the application property primary_key_update to Yes which performs a SQL UPDATE for the primary key change. Deleting the row can lead to data loss when there are database columns that are not in the table view.

In both cases, if you change the value of a primary key to a null value, the transaction manager deletes the row.

Deleting Data

To delete data in the transaction manager, execute the CLEAR command, followed by SAVE. This removes all the data displayed on the screen from the database. The TM_DELETE request usually processes child table views first. The resulting SQL DELETE statement contains a WHERE clause built from the before image values of the primary key widgets.

The user can also use the logical key DELL to delete a line. Since the transaction manager synchronizes the arrays in a server view, using this key deletes the same occurrence in every array in the server view. You can program a delete line event by calling the function sm_doccur or sm_1clear_array.

Clearing Data in Arrays

For the CLEAR command, the transaction manager clears the fields in each table view (by calling sm_1clear_array). To have the transaction manager clear the fields in each server view (the equivalent of calling sm_clear_array), you need to either:

However, setting tm_clear_fast to Yes can be over-inclusive, clearing too much data, or under-inclusive, clearing too little data. In particular, widgets in the synchronization group that do not belong to the table view will get cleared.

If widgets have been excluded from synchronization (via the synchronization property) or if widgets are members of a non-updatable table view, they will not be cleared.

If tm_clear_fast is set to Yes, it is not recommended that you call CLEAR before the synchronization of tables views occurs.

Do not change this property while the transaction manger is traversing table views for a CLEAR command. The current setting applies to the entire application; you cannot apply the setting per table view.

Inserting Data

To insert data in the transaction manager, execute the NEW command, let the user complete the data entry, and then execute SAVE. This inserts a row in each table view that was modified on the screen.

If the data is in arrays or grids, the user can use the logical key INSL, which inserts a line. Since the transaction manager synchronizes the arrays in a server view, using this key inserts a line in each array in the server view. You can program an insert line event by calling the function sm_ioccur.

For inserts, the transaction models call the SQL generator to build a values list for the widgets in the table view whose Use In Insert property is set to Yes.

Saving Data

Since the SAVE command generates different types of statements, depending on whether it needs to insert, update or delete data, the transaction manager checks the value of the variable TM_OCC_TYPE to determine what kind of change was made to the row or occurrence. (Refer to "Determining How Screen Data Has Changed" for a description of TM_OCC_TYPE values; the values are defined in tmusubs.h.)

To check the status of changes generated by the SAVE command, you can call sm_tm_inquire(TM_SAVE_COUNT) which returns the number of rows that were saved to the database.

Note: The value returned is not equivalent to the number of SQL statements issued, since multiple SQL statements can be issued for each row.

If at any time in this process, you wish to abort the edits to the screen, you can execute the CLOSE command which discards the user's changes and puts the screen in initial mode.

Customizing Database Updates

In order to customize the processing done for any table view, you can:


Transaction Modes

The transaction manager uses a set of transaction modes to help monitor and control your application's appearance and behavior. Transaction modes are initiated by associated transaction manager commands.

At a given point in time, the transaction mode determines:

For example, in a typical client screen the Save button is disabled when you first enter the screen. In this case, the initial transaction mode causes the Save button to be disabled (grayed) and precludes use of the SAVE command.

Table 36-1 lists the transaction modes set by the transaction manager and the commands that initiate those modes.

Table 36-1 Transaction modes and the commands that initiate them

Mode Description Command selection

initial

Indicates that no processing is in progress.

START, CLOSE and FORCE_CLOSE

new

Allows new data to be entered.

NEW and COPY

update

Allows existing data to be modified.

SELECT and COPY_FOR_UPDATE

view

Allows existing data to be displayed.

VIEW and COPY_FOR_VIEW

The following commands do not change the transaction mode, but are available in certain modes:

When you execute a command, the transaction manager checks the current transaction mode and either changes the mode or reports an error if the current mode is invalid for the command. Each screen can have its own mode at any given time.

In addition, when the mode changes, the appearance and protection of widgets can also change depending on the style and class settings for the widget.

Transaction Styles and Classes

As some of the transaction commands are executed, widget behavior is automatically affected. For instance, data entry type widgets can prevent input, menu choices might be deactivated, and push buttons can go from gray (inactive) to becoming accessible. These changes occur because predefined style and class settings exist for each transaction mode.

The style and class settings give a consistent user interface to an application. Data entry widgets can have the same focus and protection settings; the same color changes. This takes place without having to write any source code or set any properties in the screen editor.

The definitions for the styles and classes are defined in the styles.sty file in the distributed client.lib and, for JetNet /Oracle Tuxedo applications, in the distributed server.lib. You can use the predefined styles and classes, or edit style and classes settings or define your own styles and classes using the styles editor (for details on using the styles editor, refer to page 23-1 in the Using the Editors).

Applying Styles

In general, when a SELECT command is executed, rows from the database are retrieved for possible edit, and the transaction mode is set to update. On the screen illustrated in Figure 36-1, the title_id and actor_id widgets are automatically protected from input, preventing any edits to primary key fields. The pricecat_dscr, first_name, and last_name widgets are also protected since they members of non-updatable table views. The remaining data entry widgets can be updated.

For a given transaction mode, certain types of widget behavior are determined by:

Therefore, a widget's class property specification determines the style, that is, the behavior/appearance of that widget given a particular mode.

Default transaction styles
A transaction style defines a limited set of widget properties. Table 36-2 lists the property settings for the default transaction styles.

Table 36-2 Property settings associated with transaction styles

Style Property Settings

change

Allows focus, input, clearing, and validation

edit

Allows focus, input, clearing, and validation

show

Prevents focus, input, and clearing; allows validation

visit

Allows focus and validation; prevents input and clearing

In addition, there are other predefined styles to use with menu selections and push buttons. For more information on these styles, refer to page 23-6 in the Using the Editors.

Default transaction classes
Each of a default transaction classes already has a style assigned to each of the transaction modes. If you specify a new class, you must assign a style to each of the modes.

Table 36-3 lists a description for the default transaction classes and the style assignments in each mode. To see how these transaction classes are applied to the data widgets in the sample screen, refer to Figure 36-3.

Table 36-3 Transaction classes and their style assignments

Transaction class Description initial new view update occ update

non-updatable

Widget can only be entered in initial mode. Data cannot be edited in any mode if the widget is a part of a non-updatable table view.

edit

show

visit

show

show

primary key

Data cannot be edited in update or view modes if the widget is part of the table's primary key in an updatable table view.

edit

edit

visit

visit

edit

updatable

Data can be edited except in view mode if the widget is a member of an updatable table view and is not part of the table's primary key.

edit

edit

visit

change

edit

Figure 36-3 A sample screen with the default transaction classes.

In the sample screen, the default class assignments are as follows:

You can change the class of any widget by editing the Class property.


Accessing Transaction Information

When you customize transaction manager behavior, you might need to access various property settings or obtain information about the current transaction. Information is available via:

Using Functions to Set Transaction Manager Behavior

Several library functions are used by the transaction manager, but two of the functions are provided specifically to obtain information about the current transaction—sm_tm_pinquire and sm_tm_inquire. For example, the name of the current transaction and the root table view of the current transaction are two of the transaction attributes. Some of these attributes can be set by calling the functions sm_tm_pset and sm_tm_iset. For a complete list of the attributes, refer to the functions sm_tm_pinquire and sm_tm_inquire.

Using Transaction Manager Variables

Table 36-4 lists the transaction manager variables available for transaction event functions written in JPL.

Table 36-4 Transaction manager variables for writing transaction event functions

Variable Description Availability

@bi(field) [occurrence]

Access the before image value of the specified field and occurrence. field can be the widget name or field number. The variable @tm_occ can be used to specify the current occurrence.

In an event function during TM_DELETE_EXEC, TM_INSERT_EXEC, or TM_UPDATE_EXEC events.

@tm_occ

Occurrence number being processed. Equivalent to sm_tm_inquire (TM_OCC). Negative value indicates a deleted occurrence.

In any event function

@tm_occ_type

Code reflecting the change, if any, from its before image. Equivalent to sm_tm_inquire(TM_OCC_TYPE). Refer to page 36-26 for the code values.

In any event function

@tm_pocc

Parent occurrence number. Equivalent to sm_tm_inquire (TM_PARENT_OCC).

In any event function

@tm_save_cursor

Name of the cursor used for non-SELECT statements. Equivalent to sm_tm_pinquire (TM_SAVE_CURSOR).

In any event function

@tm_sel_cursor

Name of the cursor used for SELECT statements. Equivalent to sm_tm_pinquire (TM_SV_SELECT_CURSOR).

In any event function

Results are unpredictable if these variables are called outside of a transaction event function.

Example of using transaction manager variables

The following event function performs a "logical" delete on a database row. Instead of physically removing the row from the database, the two slices from the TM_DELETE event, TM_DELETE_DECLARE and TM_DELETE_EXEC, mark the row as deleted so that it can be excluded from selection.

proc logicalDeleteEvent (event)
{
if (event == TM_DELETE_DECLARE)
{
if (@tm_occ < 0)
{
DBMS DECLARE :@tm_save_cursor CURSOR FOR \
UPDATE customers \
SET deleted = 1 \
WHERE cust_id = ::p1
return TM_CHECK
}
}
else if (event == TM_DELETE_EXEC)
{
if (@tm_occ < 0)
{
DBMS WITH CURSOR :@tm_save_cursor \
EXECUTE USING @bi(cust_id)[:@tm_occ]
return TM_CHECK_ONE_ROW
}
}
return TM_PROCEED
}

In this example, the customers table view includes a column named deleted. The column is used to flag the record so that it is excluded from selection. Also, the use of @tm_save_cursor supplies the cursor name, @bi obtains the before image value for cust_id, and @tm_occ supplies the occurrence number.

Using Traversal Properties

In addition to the properties available through the screen editor's Properties window for each object, there are properties associated with the transaction manager which contain information about the current traversal tree. These properties, known as traversal properties, are accessible programmatically using JPL. All transaction manager related properties are readable at runtime, and some of them are settable as long as they are not currently participating in transaction.

The traversal properties provide information about the application (or current transaction), server views, table views, links, and widgets. Some of the properties can apply to more than one object type and return different information depending on what is specified. For example, the property sv, when specified for the application with @app()->sv, returns the name of the server view participating in the current transaction. When specified for a widget, for example title_id->sv, it returns the name of the server view associated with the widget title_id.

To use traversal properties effectively, you need to know when a table view is also a server view. A table view is defined as a server view if:

Many of these properties allow you to programmatically iterate through all occurrences of widgets or table views that are participating in the current transaction or all occurrences of widgets belonging to a particular table view. In addition, many properties identify an object (widget, table view, or link) by returning its ID. Panther converts the ID to a string if one is provided; for example, a widget's field number is returned if its Name property has no value.

If a table view or link is not in the current traversal tree, no information is available. If this is specified in a JPL procedure, you receive the message:

Bad field name, #, or subscript.

Table 36-5 lists application-level traversal properties that are available for identifying, at runtime, the participants associated with the root table view of the current transaction.

Table 36-5 Application traversal properties

Property Description

field_below[int]

Identifies widgets participating in current transaction.

num_fields_below

Number of widgets participating in current transaction.

num_svs_below

Number of server views participating in current transaction.

num_tvs_below

Number of table views participating in current transaction.

sv

Root table view of current transaction.

sv_below[int]

Names of server views participating in current transaction.

tv_below[int]

Names of table views participating in current transaction.

Reading the Current Transaction

The DB Interactions window, accessible via the screen editor, can illustrate how the you can monitor and control the processing of table views and server views via runtime access to properties through JPL.

Figure 36-4 DB Interactions window illustrates the tree of table views, server views, and their links.

Figure 36-4 shows the current screen having three server views:

The property num_svs_below provides the number of server views at and below the specified server view. Therefore, if rentals is specified, the num_svs_below value is 3 and the sv_below property can provide the names of the server views: rentals, users, and titles. If customers is specified, the num_svs_below property value returned is 1 even though customers is part of a server view which has server views below it, customers itself is not a server view and has no children with sequential links. The 1 is returned for the customers table view itself.

In general, to identify the objects in transaction, that is, the objects participating in the traversal tree of the transaction that contain a specified table or server view, you might determine the number of objects in the traversal tree prior to seeking the identity of a particular object.

Getting and Setting Property Values via JPL

The following JPL procedure illustrates how, on field entry, to determine to which server view the current field is a member. Given that, the procedure executes the transaction manager VIEW command for that specific server view.

proc get_sv_query
if K_ENTRY
{
vars value1
value1 = name->sv
call sm_tm_command("VIEW :value1")
}
return

If you use server view-specific properties to refer to a table view that is not a server view, no error is reported. Instead, it returns the information for that table view; for example if you use num_svs_below on a table view that is not a server view, instead of returning the number of server views that participate in the current server view, the value returned is 1 which is derived from the table view itself.

Table 36-6 Table view traversal properties

Property Definition

bi_status[int]

Reports statuses (fetched data, changed data, or empty) of rows or occurrence in specified table view.

child[int]

Names of child table views (from 1 to num_children) in specified table view.

field[int]

Identifies widgets (from 1 to num_fields) in specified table view.

field_below[int]

Identifies widgets (from 1 to num_fields_below) in specified server view and in its child table views.

key_constant[int]

Identifies primary key constants (from 1 to num_key_columns) in specified table view (updatable table views only, after SELECT, NEW, COPY or COPY_FOR_UPDATE command).

key_field[int]

Identifies primary key fields (from 1 to num_key_columns) in specified table view (updatable table views only, after SELECT, NEW, COPY or COPY_FOR_UPDATE command).

num_children

Number of child table views in specified table view.

num_columns

Number of columns in the specified table view, derived from the number of occurrences of the Columns property.

num_fields

Number of widgets in specified table view.

num_fields_below

Number of widgets in specified table view and in its child table views.

num_key_columns

Number of widgets that comprise the primary key (indicated in Primary Key property) of the specified table view (updatable table views only, after SELECT, NEW, COPY or COPY_FOR_UPDATE command.

num_sorts

Number of widgets in the specified table view that have a sort_widgets property specifications.

num_sv_fields

Number of widgets in specified server view (as identified by the sv property) or in direct or indirect child table views connected via server links to the specified server view.

num_svs_below

Number of server views connected to specified server view; the number includes the specified one and all direct and indirect child table views connected to parent table views via sequential links.

num_tvs

Number of child table views connected directly or indirectly, via server links, to the specified server view (as identified by the sv property).

num_tvs_below

Number of table views, including the specified server view, that are direct or indirect child table views of the specified server view.

parent

Name of parent table view (if any) of specified table view. There is at most one parent to any table view; the root table view of a transaction has no parent.

parent_link

Name of link in which specified table view is the child. The root table view of a transaction has no parent.

source_occ

Occurrences in server view that were valid when child table view was fetched.

sv

Name of server view containing specified table view.

sv_below [int]

Name of specified server view and all direct or indirect child server views (from 1 to num_svs_below) to which it is connected.

sv_field[int]

Identifies widgets (from 1 to num_sv_fields) in specified server view.

tv[int]

Name of specified server view and all table views connected directly or indirectly (from 1 to num_tvs) via server links to the specified server view.

tv_below[int]

Names of table views connected directly or indirectly (from 1 to num_tvs_below) to the specified table view.

Identifying a Widget's Table View

A widget must be a member of a table view in order to participate in a database transaction in order to get values for its traversal properties. The properties listed in Table 36-7 return the name of the table view to which the widget is a member.

The term server view is defined as the table view containing the specified widget and is considered to be a server view if it is joined to its parent table view by a sequential link. If the table view not a server view, the value returned is the closest table view, in the chain of successive parent table views of the transaction above the specified widget, that is not joined to its parent table view by a server link. (The root table view of the transaction, since it has no parent, is never joined to a parent by a server link. Every widget having membership in a table view in a transaction is a member of some server view.)

Table 36-7 Widget traversal properties

Property Definition

sv

Name of server view containing specified widget.

tv

Name of table view containing specified widget.

Identifying Links

To identify the link between two table views, use the parent_link property, which identifies the link that connects a specified table view with its parent table view. Once you identify of the link, you can obtain its property definitions.

Table 36-8 Link traversal properties

Property Definition

rel_child

Identifies a column belonging to the child table view with which the link connects to a column belonging to the parent table view.

rel_op

Identifies type of relationship between the parent and child components of the link: PV_JOIN (refer to page 33-22 for details on joining two database tables) or PV_LOOKUP (refer to page 33-46 for details on defining a lookup for validation links)

rel_parent

Identifies a column belonging to the parent table view with which the link connects to a column belonging to the child table view.

num_relations

Number of entries defined in the relations property. Each entry defines the relationship between a parent and child table view.

JPL Properties for Transaction Manager Operations

There are additional application properties for other aspects of transaction manager operations.

Table 36-9 Transaction manager application properties

Property Definition

primary_key_update

Generate a SQL UPDATE statement for primary key changes (instead of a SQL DELETE and INSERT).

In JetNet/Oracle Tuxedo applications, additional application properties are available:

Table 36-10 Service request application properties

Property Definition

tm_transaction

Determine whether a service is transaction manager-enabled, and if so, which transaction manager operation is to be performed.

Determining How Screen Data Has Changed

Use the function sm_tm_inquire to determine the current value of TM_OCC_TYPE. The transaction models use the sm_bi_compare function to query for the type of change made to a row or occurrence. The values of TM_OCC_TYPE are:

BI_DELETED

Occurrence was deleted.

BI_INSERTED

New data was entered.

BI_KEY_CHANGED

Primary key was edited. The before image and the current value of a key field are different.

BI_KEY_NULLED

Primary key was changed to NULL.

BI_UPDATED

Data was updated. The before image and the current value of a non-key field are different.

BI_UNCHANGED

No changes were made.

BI_UNDETERMINED

Error occurred since change was undetermined.


Processing Errors in the Transaction Manager

A transaction manager command is composed of a series of transaction events. If an error occurs while processing an event, the TM_STATUS variable is set to a value other than zero. When the transaction manager completes all the event processing for a command, it then displays an error message.

This section includes information about:

For a listing of common transaction manager errors, refer to page 10-1. For information about how event functions deal with errors, refer to page 32-4.

Identifying the Value of the TM_STATUS Variable

You can test for the current value of TM_STATUS by using the function sm_tm_inquire(TM_STATUS).

The default processing by the transaction manager sets TM_STATUS to -1 if there is an error, but you can define other non-zero values for errors if needed.

Generally, the transaction manager sets TM_STATUS to a non-zero value only if its current value is zero. In this way, the value set by the first error is not overwritten by errors in later events.

Setting the Value of TM_STATUS

TM_STATUS can be set to return a certain value in all conditions or only to return that value if its previous value is zero.

A transaction model or event function can set the return value unconditionally by calling:

sm_tm_iset(TM_STATUS, return_value)

However, the database-specific models set the TM_PROPOSE_STATUS parameter:

sm_tm_iset(TM_PROPOSE_STATUS, return_value)

This sets the TM_STATUS variable only if the previous value was zero. This prevents a non-zero return value resulting from a previous error from being overridden. The transaction models also use this after calling the function dm_dbms to execute SQL statements. This preserves non-zero values that might have been set by a error handler (if some other non-zero value had not already been set in TM_STATUS).

Event Processing after Errors

Most transaction manager commands are subdivided into three transaction requests:

TM_PRE_commandName
TM_commandName
TM_POST_commandName

For example, the VIEW command is divided into three requests: TM_PRE_VIEW, TM_VIEW, and TM_POST_VIEW.

Generally, an error does not prevent the processing of the TM_PRE_ and TM_POST_ requests, but does prevent processing of the "main" request. Even if an error occurs in TM_PRE_ or TM_POST_ request processing, it does not interfere with table view traversal. However, traversal for the main request ceases when an error is encountered, and never even begins if an error is encountered in TM_PRE_ processing. Traversal for TM_POST_ processing begins immediately after main processing ceases.

Consider the processing of the three requests associated with the VIEW command. Normally, each table view processes TM_PRE_VIEW. Next, each table view processes TM_VIEW. Then, each table view processes TM_POST_VIEW. If an error is encountered during TM_PRE_VIEW, then processing continues to the TM_POST_VIEW request, but no TM_VIEW processing is done. In particular, this allows TM_POST_VIEW to clean up actions taken by TM_PRE_VIEW. However, if an error is encountered during TM_VIEW processing, the processing immediately switches to TM_POST_VIEW.

Processing the Event Stack

When an error occurs (setting TM_STATUS to a non-zero value), transaction events on the event stack continue to be processed. Since all slices for a request can be pushed onto the stack at the same time, processing for each slice would occur even if there is an error.

If there are no events on the stack, then processing continues as if the original event had failed. You can clear the event stack by calling sm_tm_clear_model_events.

Controlling Error Messages

If the TM_STATUS variable is not zero when sm_tm_command completes its processing of a command, the transaction manager displays an error message. The content of the message indicates the first error that the transaction manager encountered.

This is the standard behavior for errors in the transaction manager. You can change this behavior by setting the following variables:

Error Message Display

To set whether the transaction manager error message be displayed, use:

sm_tm_iset(TM_EMSG_USED, flag)

If flag is zero, then sm_tm_command displays an error message. If flag is non-zero, then sm_tm_command does not display an error message, even if an error is encountered.

The most common use of this facility is to disable the transaction manager error message in cases where the error message has already been reported to the user and the transaction manager error message is merely a duplicate.

An example of this could be part of a database error handler as illustrated in the following JPL procedures. The entry procedure is called on screen entry and activates the error handler. The dberror procedure specifies the content of the error handler and tests for a connection error. If a database connection does not exist, the error handler displays the database driver error, but disables the duplicate transaction manager error.

proc entry
DBMS ONERROR JPL dberror
return 0
proc dberror
if @dmretcode == DM_NO_CONNECT
{
call sm_tm_iset(TM_EMSG_USED, 1)
msg emsg "Panther DB: " @dmretcode " " @dmretmsg "%N"\
"Engine Error: " @dmengretcode " " @dmengretmsg}
else
msg emsg "Panther DB Error: " @dmretcode " " \
@dmretmsg "%N"\
"Engine Error: " @dmengretcode " " @dmengretmsg

Error Message Content

You can specify the text of an error message using the following:

sm_tm_pset(TM_MSG_TEXT, text)
sm_tm_pset(TM_PROPOSE_MSG_TEXT, text)

Setting TM_MSG_TEXT specifies the content of the message in all conditions. Setting TM_PROPOSE_MSG_TEXT specifies the content of the message only if a message has not already been specified.

When an error occurs in a transaction event, the transaction manager always sets TM_PROPOSE_MSG_TEXT which in turn sets TM_MSG_TEXT only if it is empty. It is the value of TM_MSG_TEXT that is displayed when sm_tm_command finishes.

The transaction models also use this call after calling dm_dbms to execute SQL statements. They thus preserve non-empty values that might have been set by an error handler (if some other non-empty value had not already been set in TM_MSG_TEXT).

To change the message displayed for a transaction manager error, you must set these error message variables. The error message variables take precedence over the error number variables.

Error Message Numbers

If no message text has been set by a call to sm_tm_pset or by an error in the transaction manager itself, error message display can be specified by calling:

sm_tm_iset(TM_MSG, msg_nbr)
sm_tm_iset(TM_PROPOSE_MSG, msg_nbr)

The msg_nbr parameter would correspond to a message number defined in a message file.

The text of associated with error messages can be defined in a message file.

Refer to page 45-2 for details on how to create a message file for your application.

Suppress Error Messages

To suppress transaction manager messages, set:

sm_tm_iset
(TM_EMSG_USED, flag) 

in a customized transaction model, in the database error handler, or in an event function. If flag is set to a non-zero value, the transaction manager does not display an error message.