Try OpenEdge Now
skip to main content
ABL Essentials
Record Buffers and Record Scope : Record scope : Scoping buffers
 

Scoping buffers

Record Buffer Rule 4: If you have a free reference to a buffer, the AVM tries to scope that buffer to the nearest enclosing block with record scoping properties (that is, a FOR EACH block, a DO FOR block, or a REPEAT block). If no block within the procedure has record scoping properties, then the AVM scopes the record to the entire procedure.

The FIND statements are called free references because they don't define a scope for the buffer, they just reference it. Therefore, the AVM has to identify some scope for the record beyond the FIND statement. When a block has record scoping properties, it is a block the AVM might try to scope a record to, when the record is referenced inside the block.
Here's another variation on the testscope.p procedure that demonstrates this rule:
DEFINE VARIABLE fLimit AS DECIMAL     NO-UNDO.

FOR EACH Customer NO-LOCK WHERE Customer.State = "NH"
  BY Customer.CreditLimit DESCENDING:
  IF fLimit = 0 THEN
    fLimit = Customer.CreditLimit.
  DISPLAY Customer.CustNum Customer.Name Customer.CreditLimit.
END.

FIND FIRST Customer WHERE Customer.CreditLimit > fLimit.
DISPLAY Customer.CustNum Customer.Name Customer.CreditLimit.
This procedure is perfectly valid. The first time through the FOR EACH loop, the procedure saves off the CreditLimit for use later in the procedure. Because the fLimit variable is initialized to zero, checking for fLimit = 0 tells you whether it's already been set. When you run it, you see all the New Hampshire Customer records followed by the first Customer with a CreditLimit higher than the highest value for New Hampshire Customers. Because there's no conflict with two blocks trying to use the same buffer at the same time, it compiles and runs successfully.
But the rule that the AVM raises the scope in this situation is a critically important one. In complex procedures, the combination of buffer references you use might force the AVM to scope a record buffer higher in the procedure than you expect. Though this normally does not have a visible effect when you're just reading records, when you get to the discussion of transactions this rule becomes much more important. If you generate another listing file for this procedure, you see the effect of the FIND statement:
{} Line Blk
-- ---- ---
     1    DEFINE VARIABLE fLimit AS DECIMAL     NO-UNDO.
     2
     3    1   FOR EACH Customer NO-LOCK WHERE Customer.State = "NH"
     4    1     BY Customer.CreditLimit DESCENDING:
     5    1     IF fLimit = 0 THEN
     6    1       fLimit = Customer.CreditLimit.
     7    1     DISPLAY Customer.CustNum Customer.Name Customer.CreditLimit.
     8       END.
     9
    10    FIND FIRST Customer WHERE Customer.CreditLimit > fLimit.
    11    DISPLAY Customer.CustNum Customer.Name Customer.CreditLimit.
    12

     File Name          Line     Blk. Type     Tran          Blk. Label
-------------------- ---- --------- ---- --------------------------------
.\testscope.p           0        Procedure     No
     Buffers: sports2000.Customer
     Frames:     Unnamed

.\testscope.p           3        For          No
     Frames:     Unnamed
This tells you that the Customer buffer is scoped at line 0, that is, to the procedure itself. There's no reference to the Customer buffer in the information for the FOR block at line 3 because the AVM has already scoped the buffer higher than that block.
Next is the rule concerning combining FIND statements with strong-scoped, rather than weak-scoped references.