One final question before you move on: The Bin record buffer is scoped to the two blocks inside the main DO block, but at what level is the Warehouse record buffer scoped? Look back through the entire procedure to come up with an answer before looking at this excerpt from the listing file:


     File Name       Line Blk. Type   Tran            Blk. Label            
-------------------- ---- ----------- ---- --------------------------------
.\h-BinCheck.p          0 Procedure   No                                    
    Buffers: Sports2020.Warehouse

.\h-BinCheck.p         14 For         No                                    
.\h-BinCheck.p         19 Do          No                                    
.\h-BinCheck.p         21 For         No                                    
    Buffers: Sports2020.Bin

.\h-BinCheck.p         23 Do          No                                    
.\h-BinCheck.p         31 Repeat      No                                    
    Buffers: Sports2020.Bin

.\h-BinCheck.p         36 Do          No                                    
.\h-BinCheck.p         49 Do          No                                    
.\h-BinCheck.p         51 Do          No 

You see the two blocks where the Bin buffer is scoped. You also see that the Warehouse buffer is scoped to the entire procedure (line 0). Why is this?

There are several free references to the Warehouse buffer that are not in blocks that provide record scoping. This includes, among others, the final DO block of the procedure. As a result, the AVM raises the scope of the buffer all the way to the procedure itself because there is no other block to scope it to. In your sample procedure, which is only reading records from the database and not updating them, it does not make a lot of difference. If the procedure had a transaction that updated the Warehouse record, though, you might find that the record and the record lock on it are held much longer than you expected or wanted, resulting in record contention between different users accessing the table at the same time.

What could you do to avoid this? Define a strong scope for the Warehouse record wherever it is used.

To define a strong scope for the Warehouse record:

  1. First make the first DO block around the FIND Warehouse statement scope the buffer to the block:
    DO FOR Warehouse:
     
      FIND Warehouse WHERE Warehouse.WarehouseNum = Bin.WarehouseNum.
  2. Press SHIFT+F2 to do a syntax check. This is what you get:

    Why did this error happen? You tried to force the scope of the buffer to this block, but the free reference in the DO block at the end of the procedure still forces the scope up to the top, and those two conflict.

  3. Change the final DO block to place a strong scope there:
    DO FOR Warehouse:
      FIND Warehouse WHERE Warehouse.WarehouseNum = iEntry.
  4. Now a syntax check succeeds. If you compile the procedure and get a listing file, you see that the Warehouse buffer is scoped all over the place:
         File Name       Line Blk. Type   Tran            Blk. Label            
    -------------------- ---- ----------- ---- --------------------------------
    .\h-BinCheck.p          0 Procedure   No                                    
    .\h-BinCheck.p         14 For         No                                    
        Buffers: Sports2020.Warehouse
    
    .\h-BinCheck.p         19 Do          No                                    
    .\h-BinCheck.p         21 For         No                                    
        Buffers: Sports2020.Bin
    
    .\h-BinCheck.p         23 Do          No                                    
        Buffers: Sports2020.Warehouse
    
    .\h-BinCheck.p         31 Repeat      No                                    
        Buffers: Sports2020.Warehouse
                 Sports2020.Bin
    
    .\h-BinCheck.p         36 Do          No                                    
    .\h-BinCheck.p         49 Do          No                                    
    .\h-BinCheck.p         51 Do          No                                    
        Buffers: Sports2020.Warehouse

Take a look at the scope for each of these blocks:

  • The Warehouse buffer is now scoped to the very first FOR EACH Warehouse block, with its weak scope. the AVM tried to do this before. Because the other references to Warehouse forced the scope up to the procedure level, this weak scope disappeared (that is why it is called weak).
  • It is scoped to the DO FOR Warehouse block because you added that strong-scoped reference.
  • It is also scoped to the REPEAT PRESELECT block. This is another weak scope that did not hold when the buffer scope was forced to the top.
  • It is scoped to the final DO FOR Warehouse block, with its strong-scoped reference you just added.

When you start writing serious procedures that update the database, you will be a lot more successful if you keep your buffer scope small like this. You should get into the habit now.