RecordsetCursor class

From m204wiki
Jump to navigation Jump to search

You can loop on the records in a Recordset or SortedRecordset object using the traditional User Language For Each Record loop construct, as described in the preceding sections for those objects. However, it can be convenient to advance through a record set and access its records outside the context of a single record loop.

The Janus SOAP RecordsetCursor object gives you this additional capability for both Recordset and SortedRecordset objects. Essentially, a RecordsetCursor is a position marker in a record set. A cursor can be used to access the record at its position, or the cursor can be moved to a new position.

Cursor state

A RecordSetCursor can be in various states as it navigates a record set:

BeforeStart
The cursor is positioned before the first record in the set.
HasRecord
The cursor points to a record that is available for processing.
AfterEnd
The cursor is positioned after the last record in the set.
NoRecord
The cursor had a valid position identifying a record in a record set, but a subsequent operation (a Recordset Clear or RemoveRecord method) removed the record from the underlying Recordset.
Empty
The cursor points to an empty record set. This state is new in Sirius Mods version 7.6.

These cursor states are the values returned by the CursorState enumeration:

%state is enumeration CursorState

Note: As with all enumerations, the ToString method implicitly converts an enumeration value to a character string whose value is the name of the enumeration value. For more information about methods available to all enumerations, see Common enumeration methods.

The RecordsetCursor read-only property State returns a CursorState enumeration that indicates the current state of the cursor.

Any method that repositions the cursor returns a CursorState enumeration that indicates the new state of the cursor after the completion of the operation performed by the method.

Declaration and instantiation

A RecordsetCursor is declared like any other file or group context based object. For example:

%myCurs1 is object RecordsetCursor in file ftptest %myCurs2 is object RecordsetCursor in group foo

Prior to version 7.6 of the Sirius Mods, the RecordsetCursor class contained no native constructor methods, and the way to instantiate a RecordsetCursor object is to use the Cursor method provided by both the Recordset and SortedRecordset classes. In version 7.6, the RecordsetCursor New method was added, primarily to enable the creation of extension classes of the RecordsetCursor class, which the Cursor constructor cannot do.

Instantiation by the Cursor and New methods is described below.

  • The Cursor method instantiates a RecordsetCursor for a particular instance of a Recordset or SortedRecordset object. The method takes no arguments. If the set has at least one record, Cursor instantiates an instance of the RecordsetCursor object. If Cursor is called on a set that "isEmpty" (0 records), it returns a Null object. Here is a small syntax example:

    %rs is object recordSet in file stooges %srs is object SortedRecordset in file stooges %myCursor1 is object RecordsetCursor in file stooges %myCursor2 is object RecordsetCursor in file stooges ... fd to %rs end find ... sort records in %rs to %srs by name ... %myCursor1 = %rs:Cursor %myCursor2 = %srs:Cursor

  • Since a RecordsetCursor references a Recordset or SortedRecordset object and may have a LoopLockStrength, the RecordsetCursor New constructor is of this form:

    %(RecordsetCursor):New(recset [, LoopLockStrength=lls])

    Where:

    recset
    A required Recordset or SortedRecordset object.
    lls
    A LockStrength enumeration setting the minimum lock strength for a record in a For Record At loop on a RecordsetCursor object. This argument is only valid if recset is a SortedRecordset object.

    Note: If recset is empty, New returns a RecordsetCursor object with the state Empty. This is different from the Cursor methods instantiation, which return a null if recset is empty.

With either of the instantiation methods, when a RecordsetCursor is instantiated, it is automatically positioned on the first record in the set (state=HasRecord).

You can have as many cursors as you want for a record set.

Referencing a RecordsetCursor object

If the state of a RecordsetCursor is HasRecord, it can be referenced on a new For/End For variation:

For Record At Cursor %RecordsetCursorObject ... whatever End For

If the cursor is not in HasRecord state, the request is cancelled.

Processing a record with this construct is very much like processing it with a For Each Record loop that runs on a set that only contains that record. This means:

  • No extra record locking is done. The record is locked (or not) at whatever level the underlying record set is.
  • If the cursor is for a SortedRecordset that was created using a Sort Records To statement, the records returned will be copies of the actual records. If the SortedRecordset was created with Sort Record Keys, the actual Table B record from the file is returned. This is consistent with the contrasting behavior of Sort Records and Sort Record Keys elsewhere in Model 204.

The For Record %recobj construct can be used on the result of the RecordsetCursor CurrentRecord method (or on a Record object to which the method result was assigned). For example:

For Record %myCursor1:CurrentRecord ... whatever End For

Or, for example:

%r is object record in foo %r = %myCursor1:CurrentRecord(exclusive) For Record %r ... whatever End For

This second technique is less efficient, because you incur the overhead of Record object instantiation and record locking. It is more flexible because you can control the locking strength.

In addition, with this technique you always refer to the real record in Table B, and never to a Sort copy.

LoopLockStrength for RecordsetCursors

In addition to the LockStrength property, in Sirius Mods 7.0 and later, all RecordsetCursor objects also have a LoopLockStrength property. Like the LockStrength property, the LoopLockStrength property's values are of the LockStrength enumeration. The LoopLockStrength property indicates the minimum lock strength for the record being processed in an iteration of a For Record At loop on a RecordsetCursor object.

If the LoopLockStrength is the same as or weaker than the LockStrength of a RecordsetCursor object (which is, in fact, the lock strength of the underlying Recordset object), no action is required at the start of each loop — the record in the iteration is known to be locked at the strength of the Recordset which is greater than the LoopLockStrength. If, however, the LoopLockStrength is stronger than the LockStrength, each execution of a For Record At loop on a RecordsetCursor object tries to obtain a LoopLockStrength level lock on the record in the iteration. If successful, the iteration is processed and the lock is released at the end of the loop execution.

The default value of LoopLockStrength is None, which means that no additional locking is performed for the record in the RecordsetCursor during loop processing.

LoopLockStrength locking behavior is identical to the locking behavior of the For Record Number (FRN) statement. The meanings of certain statements in an On Record Locking conflict unit are identical to their meaning for a For Record Number statement conflict:

Bypass
Causes processing of the record to be skipped, which means that the For Record loop is not processed.
Retry
Causes the For Record At statement to be re-executed and to try again to lock the record at the LoopLockStrength level.

There are many similarities in LoopLockStrength processing for RecordsetCursor and Recordset objects. For more information about the use of LoopLockStrength with Recordset objects see LoopLockStrength for Recordsets.

Discarding a cursor

In addition to the standard discard (%myCursor1:Discard), you can also use the Close method to discard a RecordsetCursor object:

%myCursor1:close

List of RecordsetCursor methods

The List of RecordsetCursor methods shows all the class methods.