Record class: Difference between revisions

From m204wiki
Jump to navigation Jump to search
m (minor formatting)
 
(22 intermediate revisions by 3 users not shown)
Line 5: Line 5:
record over the life of an object, or at least over several
record over the life of an object, or at least over several
method invocations.
method invocations.
The Record class makes this possible.
The <var>Record</var> class makes this possible.
   
   
The Record class is a file class that references a specific
The <var>Record</var> class is a file class that references a specific
record in a file or group.
record in a file or group.
==Instantiating Record objects==
==Instantiating Record objects==
As discussed in this section,
As discussed in this section,
there are two ways to instantiate a Record object:
there are two ways to instantiate a <var>Record</var> object:
<ul>
<ul>
<li>With the New function
<li>With the New function
<li>With the CurrentRecord function
<li>With the <var>CurrentRecord</var> function
</ul>
</ul>
   
   
You can also set the record locking for a newly instantiated Record object.
You can also set the record locking for a newly instantiated Record object.
The [[List of Record methods|"List of Record methods"]] lists all the methods in this class.


===Using New to instantiate a Record object===
===Using New to instantiate a Record object===
Line 35: Line 34:
The returned record object references the indicated record number in
The returned record object references the indicated record number in
the indicated file.
the indicated file.
===Using CurrentRecord to instantiate a Record object===
===Using CurrentRecord to instantiate a Record object===
The CurrentRecord constructor, a shared method in the Record class,
The <var>CurrentRecord</var> constructor, a shared method in the <var>Record</var> class,
must be in the appropriate record context:
must be in the appropriate record context:
<ul>
<ul>
<li>Inside a record loop
<li>Inside a record loop
(For Each Record, For Record Number, For Record, etc.) that has
(<var>For Each Record</var>, <var>For Record Number</var>, <var>For Record</var>, etc.) that has
the same file/group context as the Record object.
the same file/group context as the <var>Record</var> object.
   
   
For example:
For example:
<p class="code"> %recSet  is object recordSet in file music
<p class="code">%recSet  is object recordSet in file music
%rec      is object record    in file music
%rec      is object record    in file music
    ...
  ...
find records to %recSet
find records to %recSet
    composer = 'Mozart'
  composer = 'Mozart'
end find
end find
   
   
for each record in %recSet
for each record in %recSet
    %rec = currentRecord
  %rec = currentRecord
    ...
  ...
end for
end for
</p>
</p>
   
   
It is not valid to issue the CurrentRecord method for a
It is not valid to issue the <var>CurrentRecord</var> method for a record in one file or group context when the record loop has a different file or group context.</li>
record in one file or group context when the record loop has
 
a different file or group context.
<li>Inside a user method that is declared with the <code>CurrentRecord</code>
<li>Inside a user method that is declared with the <code>CurrentRecord</code>
''attribute'' and with the same file or group as the Record object.
''attribute'' and with the same file or group as the <var>Record</var> object.
<p>
Available as of <var class="product">Sirius Mods</var> version 7.7,
Available as of <var class="product">Sirius Mods</var> version 7.7,
a <code>CurrentRecord In File</code> <code>''name''</code>
a <code>CurrentRecord In File</code> <code>''name''</code>
or <code>CurrentRecord In Group</code> <code>''name''</code> clause
or <code>CurrentRecord In Group</code> <code>''name''</code> clause
on a method declaration indicates that:
on a method declaration indicates that:</p>
<ul>
<ul>
<li>The method may only be invoked in a record context (established by a
<li>The method may only be invoked in a record context (established by a
For Each Record loop, for example) for the declared file or group.
For Each Record loop, for example) for the declared file or group.
<p>
For example, the <code>printField</code> method, defined with the
For example, the <code>printField</code> method, defined with the
CurrentRecord attribute, is successfully invoked within an FR loop:
<var>CurrentRecord</var> attribute, is successfully invoked within an <var>FR</var> loop:</p>
<p class="code"> local subroutine (Record in file myproc):printField  -
<p class="code">local subroutine (Record in file myproc):printField  -
      currentRecord in file myproc
      currentRecord in file myproc
    for record currentRecord
  for record currentRecord
      print NAME
      print NAME
    end for
  end for
end subroutine
end subroutine
   
   
for each record in %recset
for each record in %recset
  %rec = CurrentRecord
  %rec = CurrentRecord
  %rec:printField
  %rec:printField
end for
end for
</p>
</p></li>
<li>Statements within the method definition, even a CurrentRecord
 
<li>Statements within the method definition, even a <var>CurrentRecord</var>
method call, may reference the record without having to be wrapped
method call, may reference the record without having to be wrapped
inside a record For loop.
inside a record For loop.
<p>
For example, the XmlDoc class LoadFromRecord method, which normally requires
For example, the <var>XmlDoc</var> class <var>LoadFromRecord</var> method, which normally requires
a containing record loop, is valid as specified in the following method:
a containing record loop, is valid as specified in the following method:</p>
<p class="code"> local function getDoc is object xmlDoc  -
<p class="code">local function getDoc is object xmlDoc  -
      currentRecord in file parents
      currentRecord in file parents
    %doc is object xmlDoc
  %doc is object xmlDoc
    %doc = new
  %doc = new
    %doc:loadFromRecord
  %doc:loadFromRecord
    return %doc
  return %doc
end function
end function
</p>
</p>
'''Note:'''
<blockquote class="note">
<p>'''Note:'''
Under <var class="product">Sirius Mods</var> 7.7, field references are an exception to this rule.
Under <var class="product">Sirius Mods</var> 7.7, field references are an exception to this rule.
You may not reference a record field from within a method declared with
You may not reference a record field from within a method declared with
CurrentRecord without being inside a record
<var>CurrentRecord</var> without being inside a record
For loop, unless you are running under <var class="product">Sirius Mods</var> version 7.8 or higher.
For loop, unless you are running under <var class="product">Sirius Mods</var> version 7.8 or higher.</p>
<p>
For example, the <code>For Record currentRecord</code> and <code>End For</code>
For example, the <code>For Record currentRecord</code> and <code>End For</code>
statements within the printField method in the
statements within the <code>printField</code> method in the
preceding bullet item are not necessary in <var class="product">Sirius Mods</var> version 7.8 or higher.
preceding bullet item are not necessary in <var class="product">Sirius Mods</var> version 7.8 or higher.
In those versions, the <code>print NAME</code> statement succeeds by itself.
In those versions, the <code>print NAME</code> statement succeeds by itself.</p>
</blockquote></li>
</ul></li>
</ul>
</ul>
</ul>
 
'''Note:'''
Under version 6.8 of <var class="product">Sirius Mods</var> and earlier, you must specify the
class name or an object variable before the CurrentRecord method name.
For example:
<p class="code"> %rec = %rec:currentRecord
</p>
===Setting record locking for a new Record instance===
===Setting record locking for a new Record instance===
Whether a record object is instantiated with the New constructor or
Whether a <var>Record</var> object is instantiated with the <var>New</var> constructor or
the CurrentRecord constructor, the record object will hold a
the <var>CurrentRecord</var> constructor, the record object will hold a
share lock on the record with which it is associated.
share lock on the record with which it is associated.
This is consistent with the locking behaviour of the <var class="product">Model 204</var> For Record Number
This is consistent with the locking behaviour of the <var class="product">Model 204</var> <var>For Record Number</var> construct.
construct.
   
   
You can change the default record locking by using the optional
You can change the default record locking by using the optional
<code>lockstrength</code> parameter when you instantiate the object.
<code>lockstrength</code> parameter when you instantiate the object.
The value you specify must be a LockStrength enumeration,
The value you specify must be a <var>[[LockStrength enumeration]]</var>,
which may take a variety of forms:
which may take a variety of forms:
<p class="code"> %filerec = new(17, share)
<p class="code">%filerec = new(17, share)
    ...
  ...
%filerec = new(17, %(LockStrength):exclusive)
%filerec = new(17, %(LockStrength):exclusive)
    ...
  ...
%grouprec = new(1, 'TESTPROC', exclusive)
%grouprec = new(1, 'TESTPROC', exclusive)
    ...
  ...
%rec = CurrentRecord(None)
%rec = CurrentRecord(None)
    ...
  ...
%e is enumeration lockstrength
%e is enumeration lockstrength
%e = exclusive
%e = exclusive
%grouprec = new(1, 'TESTPROC', %e)
%grouprec = new(1, 'TESTPROC', %e)
</p>
</p>
The following example shows how you can
The following example shows how you can
instantiate a Record object of the same lock strength as
instantiate a <var>Record</var> object of the same lock strength as
a Recordset object.
a <var>Recordset</var> object.
Within a record loop against a Recordset object,
Within a record loop against a <var>Recordset</var> object,
you refer to the LockStrength property of the Recordset as an argument to
you refer to the <var>LockStrength</var> property of the <var>Recordset</var> as an argument to
the CurrentRecord constructor for the Record object:
the <var>CurrentRecord</var> constructor for the <var>Record</var> object:
<p class="code"> begin
<p class="code">begin
   
   
    %stooges is object recordSet in file glwproc
%stooges is object recordSet in file glwproc
    %stooge is object record in file glwproc
%stooge is object record in file glwproc
   
   
    fdr to %stooges
fdr to %stooges
    end find
end find
   
   
    for each record in %stooges
for each record in %stooges
      %stooge = CurrentRecord(%stooges:LockStrength)
  %stooge = CurrentRecord(%stooges:LockStrength)
    end for
end for
   
   
    print %stooge:LockStrength:toString
print %stooge:LockStrength:toString
   
   
end
end
</p>
</p>
   
   
Since the Fdr statement instantiates a record set with Exclusive locking,
Since the <code>Fdr</code> statement instantiates a record set with <var>Exclusive</var> locking,
The Print statement result here is <code>Exclusive</code>.
the <code>Print</code> statement result here is <code>Exclusive</code>.
For more information about Recordset instantiation,
For more information about <var>Recordset</var> instantiation,
see [[Recordset class#Creating Recordset objects|"Creating Recordset objects"]].
see [[Recordset class#Creating Recordset objects|Creating Recordset objects]].
 
==Using Record objects in a For Record loop==
==Using Record objects in a For Record loop==
A Record object can be used to drive a single record For loop
A <var>Record</var> object can be used to drive a single record For loop
much like a For Record Number loop:
much like a <var>For Record Number</var> loop:
<p class="code"> %rec    is object record in file music
<p class="code"> %rec    is object record in file music
     ...
     ...
Line 176: Line 173:
  end for
  end for
</p>
</p>
A For Record loop using a locked Record object has these
A <var>For Record</var> loop using a locked <var>Record</var> object has these
advantages over a For Record Number loop:
advantages over a <var>For Record Number</var> loop:
<ul>
<ul>
<li>The Record object already holds a share lock so no share lock
<li>The <var>Record</var> object already holds a share lock so no share lock
has to be obtained, and the record does not need to be validated
has to be obtained, and the record does not need to be validated
against the existence bitmap.
against the existence bitmap.
Both these actions have to be done for each For Record Number loop,
Both these actions have to be done for each <var>For Record Number</var> loop,
and they have non-trivial overhead.
and they have non-trivial overhead. </li>
 
<li>The record lock on the Record object is not lost between loops
<li>The record lock on the Record object is not lost between loops
on the same record, or after a commit within a loop, so there are no worries
on the same record, or after a commit within a loop, so there are no worries
about the record changing between For Record loops.
about the record changing between <var>For Record</var> loops.
With multiple For Record Number loops, a record can change between
With multiple <var>For Record Number</var> loops, a record can change between
loops unless a lock is held on the record in some other way.
loops unless a lock is held on the record in some other way. </li>
</ul>
</ul>
===LoopLockStrength for Records===
===LoopLockStrength for Records===
In addition to the LockStrength property, in <var class="product">Sirius Mods</var> 7.0 and later,
In addition to the <var>LockStrength</var> property, in <var class="product">Sirius Mods</var> 7.0 and later,
all Record objects also have a LoopLockStrength property.
all <var>Record</var> objects also have a <var>LoopLockStrength</var> property.
Like the LockStrength property, the LoopLockStrength property's values
Like the <var>LockStrength</var> property, the <var>LoopLockStrength</var> property's values
are of the LockStrength enumeration.
are of the <var>LockStrength</var> enumeration.
The LoopLockStrength property indicates the minimum lock strength for
The <var>LoopLockStrength</var> property indicates the minimum lock strength for
the record being processed in an iteration of a For Record loop
the record being processed in an iteration of a For Record loop
on a Record object.
on a <var>Record</var> object.
   
   
If the LoopLockStrength is the same as or weaker than the LockStrength
If the <var>LoopLockStrength</var> is the same as or weaker than the <var>LockStrength</var>
of a Record object, no action is required at the start of each loop
of a <var>Record</var> object, no action is required at the start of each loop
&mdash; the record in the iteration is known to be locked at the
&mdash; the record in the iteration is known to be locked at the
strength of the Record which is greater than the LoopLockStrength.
strength of the <var>Record</var> which is greater than the <var>LoopLockStrength</var>.
If, however, the LoopLockStrength is stronger than the LockStrength,
If, however, the <var>LoopLockStrength</var> is stronger than the <var>LockStrength</var>,
each execution of a For Record loop on a Record object tries to obtain
each execution of a <var>For Record</var> loop on a <var>Record</var> object tries to obtain
a LoopLockStrength level lock on the record in the iteration.
a <var>LoopLockStrength</var> level lock on the record in the iteration.
If successful, the iteration is processed and the lock is released
If successful, the iteration is processed and the lock is released
at the end of the loop execution.
at the end of the loop execution.
   
   
The default value of LoopLockStrength is <code>None</code>, which means that
The default value of <var>LoopLockStrength</var> is <code>None</code>, which means that
no additional locking is performed for the record at the start
no additional locking is performed for the record at the start
of a For Record loop.
of a <var>For Record</var> loop.
   
   
LoopLockStrength locking behavior is identical to the locking
<var>LoopLockStrength</var> locking behavior is identical to the locking
behavior of the For Record Number (FRN) statement.
behavior of the <var>For Record Number</var> (<var>FRN</var>) statement.
The meanings of certain statements in an On Record Locking conflict
The meanings of certain statements in an <var>On Record Locking</var> conflict
unit are identical to their meaning for a For Record Number statement
unit are identical to their meaning for a <var>For Record Number</var> statement
conflict:
conflict:
<dl>
<dl>
<dt>Bypass
<dt>Bypass
<dd>Causes processing of the record to be skipped, which means that
<dd>Causes processing of the record to be skipped, which means that
the For Record loop is not processed.
the <var>For Record</var> loop is not processed.
<dt>Retry
<dt>Retry
<dd>Causes the For Record statement to be re-executed and
<dd>Causes the <var>For Record</var> statement to be re-executed and
to try again to lock the record at the LoopLockStrength level.
to try again to lock the record at the <var>LoopLockStrength</var> level.
</dl>
</dl>
   
   
There are many similarities in LoopLockStrength processing for Record
There are many similarities in <var>LoopLockStrength</var> processing for <var>Record</var>
and Recordset objects.
and <var>Recordset</var> objects.
For more information about the use of LoopLockStrength with Recordset
For more information about the use of <var>LoopLockStrength</var> with <var>Recordset</var>
objects see [[Recordset class#LoopLockStrength for Recordsets|"LoopLockStrength for Recordsets"]].
objects, see [[Recordset class#LoopLockStrength for Recordsets|LoopLockStrength for Recordsets]].
 
==List of Record methods==
The [[List of Record methods]] shows all the class methods.


[[Category:System classes]]
[[Category:System classes]]

Latest revision as of 19:41, 18 August 2015

It is quite common for an instance of a class to be associated with a specific record in a specific file. It is therefore quite useful to be able to hold a lock on the record over the life of an object, or at least over several method invocations. The Record class makes this possible.

The Record class is a file class that references a specific record in a file or group.

Instantiating Record objects

As discussed in this section, there are two ways to instantiate a Record object:

  • With the New function
  • With the CurrentRecord function

You can also set the record locking for a newly instantiated Record object.

Using New to instantiate a Record object

The New function takes as input a record number for file context Record objects, or it takes a filename and record number for group context Record objects. For example:

%fileRec is object record in file foo %groupRec is object record in group bar ... %fileRec = new(%recno) ... %groupRec = new(%recno, %filename)

The returned record object references the indicated record number in the indicated file.

Using CurrentRecord to instantiate a Record object

The CurrentRecord constructor, a shared method in the Record class, must be in the appropriate record context:

  • Inside a record loop (For Each Record, For Record Number, For Record, etc.) that has the same file/group context as the Record object. For example:

    %recSet is object recordSet in file music %rec is object record in file music ... find records to %recSet composer = 'Mozart' end find for each record in %recSet %rec = currentRecord ... end for

    It is not valid to issue the CurrentRecord method for a record in one file or group context when the record loop has a different file or group context.
  • Inside a user method that is declared with the CurrentRecord attribute and with the same file or group as the Record object.

    Available as of Sirius Mods version 7.7, a CurrentRecord In File name or CurrentRecord In Group name clause on a method declaration indicates that:

    • The method may only be invoked in a record context (established by a For Each Record loop, for example) for the declared file or group.

      For example, the printField method, defined with the CurrentRecord attribute, is successfully invoked within an FR loop:

      local subroutine (Record in file myproc):printField - currentRecord in file myproc for record currentRecord print NAME end for end subroutine for each record in %recset %rec = CurrentRecord %rec:printField end for

    • Statements within the method definition, even a CurrentRecord method call, may reference the record without having to be wrapped inside a record For loop.

      For example, the XmlDoc class LoadFromRecord method, which normally requires a containing record loop, is valid as specified in the following method:

      local function getDoc is object xmlDoc - currentRecord in file parents %doc is object xmlDoc %doc = new %doc:loadFromRecord return %doc end function

      Note: Under Sirius Mods 7.7, field references are an exception to this rule. You may not reference a record field from within a method declared with CurrentRecord without being inside a record For loop, unless you are running under Sirius Mods version 7.8 or higher.

      For example, the For Record currentRecord and End For statements within the printField method in the preceding bullet item are not necessary in Sirius Mods version 7.8 or higher. In those versions, the print NAME statement succeeds by itself.

Setting record locking for a new Record instance

Whether a Record object is instantiated with the New constructor or the CurrentRecord constructor, the record object will hold a share lock on the record with which it is associated. This is consistent with the locking behaviour of the Model 204 For Record Number construct.

You can change the default record locking by using the optional lockstrength parameter when you instantiate the object. The value you specify must be a LockStrength enumeration, which may take a variety of forms:

%filerec = new(17, share) ... %filerec = new(17, %(LockStrength):exclusive) ... %grouprec = new(1, 'TESTPROC', exclusive) ... %rec = CurrentRecord(None) ... %e is enumeration lockstrength %e = exclusive %grouprec = new(1, 'TESTPROC', %e)

The following example shows how you can instantiate a Record object of the same lock strength as a Recordset object. Within a record loop against a Recordset object, you refer to the LockStrength property of the Recordset as an argument to the CurrentRecord constructor for the Record object:

begin %stooges is object recordSet in file glwproc %stooge is object record in file glwproc fdr to %stooges end find for each record in %stooges %stooge = CurrentRecord(%stooges:LockStrength) end for print %stooge:LockStrength:toString end

Since the Fdr statement instantiates a record set with Exclusive locking, the Print statement result here is Exclusive. For more information about Recordset instantiation, see Creating Recordset objects.

Using Record objects in a For Record loop

A Record object can be used to drive a single record For loop much like a For Record Number loop:

%rec is object record in file music ... for record %rec ... end for

A For Record loop using a locked Record object has these advantages over a For Record Number loop:

  • The Record object already holds a share lock so no share lock has to be obtained, and the record does not need to be validated against the existence bitmap. Both these actions have to be done for each For Record Number loop, and they have non-trivial overhead.
  • The record lock on the Record object is not lost between loops on the same record, or after a commit within a loop, so there are no worries about the record changing between For Record loops. With multiple For Record Number loops, a record can change between loops unless a lock is held on the record in some other way.

LoopLockStrength for Records

In addition to the LockStrength property, in Sirius Mods 7.0 and later, all Record 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 loop on a Record object.

If the LoopLockStrength is the same as or weaker than the LockStrength of a Record 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 Record which is greater than the LoopLockStrength. If, however, the LoopLockStrength is stronger than the LockStrength, each execution of a For Record loop on a Record 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 at the start of a For Record loop.

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 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 Record and Recordset objects. For more information about the use of LoopLockStrength with Recordset objects, see LoopLockStrength for Recordsets.

List of Record methods

The List of Record methods shows all the class methods.