Buffer scope issue with break by

Posted by James Palmer on 03-Nov-2015 05:37

Is this expected behaviour? Consider the code below against sports2000. If the named buffers are scoped to the IP then the buffers are only in scope if they have been explicitly found in that iteration of the query. If not then the buffer is out of scope again. 

Progress 11.5.1 on Windows

If on the other hand I move the definitions to the definitions of the .p then the records are in scope as necessary. 

BLOCK-LEVEL ON ERROR UNDO, THROW.

DEFINE TEMP-TABLE tt-Test NO-UNDO 
  FIELD custnum  LIKE s2k.Customer.CustNum
  FIELD ordernum LIKE s2k.Order.Ordernum
  FIELD linenum  LIKE s2k.OrderLine.Linenum
  INDEX idxbb IS PRIMARY custnum ordernum linenum.

RUN PopulateTT.
RUN DoBreakBy. 

PROCEDURE DoBreakBy:
  DEFINE BUFFER lb-Customer  FOR s2k.Customer. 
  DEFINE BUFFER lb-Order     FOR s2k.Order. 
  DEFINE BUFFER lb-OrderLine FOR s2k.OrderLine. 

  FOR EACH tt-Test
    BREAK BY custnum BY ordernum BY linenum:
    
    IF FIRST-OF(tt-Test.custnum) THEN 
    DO:
      FIND lb-Customer NO-LOCK 
        WHERE lb-Customer.custnum EQ tt-Test.custnum NO-ERROR. 
    END. 
    
    IF FIRST-OF(tt-Test.ordernum) THEN 
    DO:
      FIND lb-Order NO-LOCK 
        WHERE lb-Order.Ordernum EQ tt-Test.Ordernum NO-ERROR. 
    END. 
    
    IF FIRST-OF(tt-Test.linenum) THEN 
    DO:
      FIND lb-OrderLine NO-LOCK 
        WHERE lb-OrderLine.OrderNum EQ tt-Test.Ordernum 
        AND lb-OrderLine.linenum EQ tt-Test.linenum NO-ERROR. 
    END. 
  
    MESSAGE AVAIL lb-Customer SKIP AVAIL lb-Order SKIP AVAIL lb-OrderLine
      VIEW-AS ALERT-BOX.
  END. 

END PROCEDURE.

PROCEDURE PopulateTT:
  FOR EACH s2k.OrderLine NO-LOCK,
    FIRST s2k.Order OF s2k.OrderLine NO-LOCK:
    
    CREATE tt-Test.
    ASSIGN 
      tt-Test.custnum  = s2k.Order.CustNum
      tt-Test.OrderNum = s2k.Order.OrderNum
      tt-Test.linenum  = s2k.OrderLine.Linenum.
  END. 

END PROCEDURE.
  

All Replies

Posted by James Palmer on 03-Nov-2015 05:39

If I whack a "DO FOR lb-Customer, lb-Order, lb-OrderLine" around the for each with the buffers scoped to the IP it works as expected too.

Posted by Simon L. Prinsloo on 03-Nov-2015 05:58

That is expected behaviour.

The buffers will scope to the lowest block in which they are referenced.

When you define them in the IP, they belong to the IP. As they are only referenced in the FOR block, that is the outer most block with scoping capability that reference the buffer and it will control the scope, i.e. the record will go out of scope after each iteration.

But if you reference the buffer before the FOR in the IP or after the END of the FOR block in the IP, the IP will control scope and the records from previous iterations will remain in the buffer.

But if you do not define them in the IP, the IP will share the globally (implicitly or explicitly) defined buffers of the external procedure, which will then manage scope in order to enable sharing of the buffer between the main block and all the IPs. You can however explicitly fix the scope by using a "DO FOR", in which case references to the buffer outside the block should give an error.

Posted by James Palmer on 03-Nov-2015 06:06

Thanks Simon. Makes sense. And I suppose I did know that, just took us by surprise when some code wasn't working.

Posted by Simon L. Prinsloo on 03-Nov-2015 07:15

Yes, I guess when we tell the newbies "You still need to learn what I've already forgotten.", we speak about these type of  things.

This thread is closed