RecordsetCursor class
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.
The "List of RecordsetCursor methods" lists all the methods in this class.
Cursor state
A cursor 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 (Recordset Clear or RemoveRecord method) removed the record from the underlying Recordset. This state is new in Sirius Mods version 7.0.
- Empty
- The cursor points to an empty record set. This state is new in Sirius Mods version 7.6.
The CursorState enumeration returns the state of a cursor:
%state is enumeration CursorState
The valid values for CursorState are BeforeStart, HasRecord, AfterEnd, NoRecord, and Empty, as described above. For more information about enumerations, see Enumerations.
The RecordsetCursor object also has a read-only property
called State
.
This property 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:Unknown title
%(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 stateEmpty
. 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 behaviour 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