Kbase 15620: ( FOR EACH or PRESELECT ) and BREAK BY " look ahead " buffer
Autor |
  Progress Software Corporation - Progress |
Acesso |
  Público |
Publicação |
  10/05/1998 |
|
( FOR EACH or PRESELECT ) and BREAK BY " look ahead " buffer
DRAFT COPY - Currently under review and edit.
INTRODUCTION:
=============
This KnowledgeBase entry discusses expected behavior of the BREAK BY
option as it affects the 4GL developer.
WHY YOU NEED TO KNOW THIS:
===========================
The BREAK BY option may appear to change the normal FOR EACH or
PRESELECT record buffer availability. If you understand how the
BREAK BY option is implemented, you can design your application
to anticipate the normal buffer contents.
PROCEDURAL APPROACH:
====================
When the BREAK BY option is used, an additional internal buffer is
maintained by PROGRESS. This buffer is used to "look ahead" at the
next row in the query to determine whether a breakpoint will be
encountered based on the fields specified in the BREAK BY and the
values in the current data buffer(s) for the query. The "look ahead"
allows PROGRESS to calculate any aggregate values required before
releasing the last record of a group from the current data buffer(s).
Side-Effects of BREAK BY Implementation:
----------------------------------------
One commonly-encountered side-effect is that sometimes a data
buffer appears to have data outside the FOR EACH or PRESELECT block,
and at other times no data is available. The following example
produces error "No <file-name> record is available. (91)":
FOR EACH customer:
DISPLAY name state.
END.
DISPLAY customer. /* this statement causes the error */
whereas the next example does not:
FOR EACH customer BREAK BY state:
DISPLAY name state.
END.
DISPLAY customer.
This can be explained by the normal behavior of a LEAVE within a
FOR EACH block. If you allow the FOR EACH loop to continue to
the end-of-file condition, the buffer contents will be cleared out
by the time the DISPLAY customer statement is reached.
With the BREAK BY however, the "look ahead" buffer is actually
one record ahead of the data buffer, so *it* encounters the
end-of-file condition, a LEAVE of the FOR EACH block is executed,
and the query's data buffer retains the last record values.
Another side-effect can be seen with sub-procedures called from
within a FOR EACH or PRESELECT with the BREAK BY option.
The "look ahead" buffer cannot be referenced directly by the 4GL
developer. It is strictly a local buffer and cannot span procedures.
Therefore, any break functionality must be performed within the
procedure containing the FOR EACH or PRESELECT statement.
For example, the following code will fail with the error
"BREAK keyword or BY phrase missing for aggregate expression. (574)"
DEFINE NEW SHARED BUFFER pr-order FOR order PRESELECT.
DEFINE NEW SHARED BUFFER pr-ordline FOR order-line PRESELECT.
DO PRESELECT EACH pr-order USE-INDEX cust-order NO-LOCK,
EACH pr-ordline USE-INDEX item-num NO-LOCK
BREAK BY cust-po BY odate:
RUN test1.p.
END. /* do */
/* test1.p */
DEFINE SHARED BUFFER pr-order FOR order PRESELECT.
DEFINE SHARED BUFFER pr-ordline FOR order-line PRESELECT.
FIND FIRST pr-ordline.
IF FIRST-OF(cust-po) THEN DISPLAY pr-ordline.
The above example fails because the FIRST-OF function in the
sub-procedure does not have access to the internal "look ahead"
buffer implemented for the BREAK BY in the main procedure.
Progress Software Technical Support Note # 15620