Bug #6997
OUTPUT BY-REFERENCE records are not cleared
0%
Related issues
History
#1 Updated by Dănuț Filimon over 3 years ago
In start.p, a temporary table main is created which is assigned 1 element, then that table is used as an output parameter with BY-REFERENCE and passed to a non-persistent external procedure.
start.p
DEFINE TEMP-TABLE main NO-UNDO
FIELD field1 AS CHARACTER.
CREATE main.
ASSIGN
main.field1 = "main-table".
RUN test-ttbyref83proc.p (OUTPUT TABLE main BY-REFERENCE).
FOR EACH main.
MESSAGE "MAIN: " + STRING(main.field1).
END.
In the external procedure there are 2 tables like main. The output table received is assigned another element, then it is passed to an internal procedure and another element is created. Finally, all the values are printed.
test-ttbyref83proc.p
DEFINE TEMP-TABLE main NO-UNDO
FIELD field1 AS CHARACTER.
DEFINE TEMP-TABLE main1 NO-UNDO
FIELD field1 AS CHARACTER.
DEFINE OUTPUT PARAMETER TABLE FOR main.
CREATE main.
ASSIGN
main.field1 = "procedure-main-table".
RUN int1(OUTPUT TABLE main BY-REFERENCE).
PROCEDURE int1:
DEFINE OUTPUT PARAMETER TABLE FOR main1.
CREATE main1.
ASSIGN
main1.field1 = "internal-procedure-main-table".
END.
// Records from main should not be displayed
FOR EACH main.
MESSAGE "main NPP1: " + STRING(main.field1).
END.
// This item is not created
CREATE main.
ASSIGN
main.field1 = "should-not-exist".
// Records from main1 should be displayed if any
FOR EACH main1.
MESSAGE "main1 NPP2: " + STRING(main.field1).
END.
The problem is that the FWD converted code has different results compared to the 4GL code. I only remarked this problem when passing a table using OUTPUT and BY-REFERENCE to a persistent/non-persistent procedure and then using the same specification to pass it into an internal procedure.
In test-ttbyref83proc.p, the first FOR EACH main and the last CREATE main are ignored in 4GL, but executed in FWD.
4GL output:
MAIN: main-table MAIN: procedure-main-table MAIN: internal-procedure-main-table
Converted code output:
main NPP1: main-table main NPP1: procedure-main-table main NPP1: internal-procedure-main-table MAIN: main-table MAIN: procedure-main-table MAIN: internal-procedure-main-table MAIN: should-not-exist
#2 Updated by Dănuț Filimon over 3 years ago
- Related to Support #6714: check if there is an optimization opportunity when copying temp-tables based on multiplex id added
#3 Updated by Ovidiu Maxiniuc over 3 years ago
- the CREATE /ASSIGN from
int1are actually performed directly into themainof thestart.pwhich was sent BY-REFERENCE twice. This seems to work correctly; - after leaving
int1, the localmainandmain1are not bound any more (although themainis still bound tostart.p's table as parameter). The creation ofmainrecord which should-not-exist should be created the very same way as the internal-procedure-main-table. If the binding betweenmainandmain1still existed, themain1 NPP2loop would have display it. So it must be created in themaintable which is still bound as output parameter to the table fromstart.p. Actually, there is no difference between the two CREATEs in thetest-ttbyref83proc.pprocedure. The only factor which affects them is the call to internal procedureint1. - personally, I think this is a BUG in OE which this testcase demonstrate. After returning from
RUN int1(OUTPUT TABLE main BY-REFERENCE)., I guess the localmainis unbound from the parameter and themain NPP1and second CREATE does not happen on reference table, but on local table. This fully explain the output from the code when executed on OE.
#4 Updated by Ovidiu Maxiniuc over 3 years ago
I returned to this testcase. I altered the original code a bit and I found more evidences in favour of confirming the bug.
I added a second parameter to int1 and called it twice, like this:
RUN int1(OUTPUT TABLE main BY-REFERENCE, 1).
RUN int1(OUTPUT TABLE main BY-REFERENCE, 2).
PROCEDURE int1:
DEFINE OUTPUT PARAMETER TABLE FOR main1.
DEFINE INPUT PARAMETER a AS INT.
CREATE main1.
ASSIGN main1.field1 = "internal-procedure-main-table: " + STRING(a).
END.
With this, the output changes to:
main NPP1: internal-procedure-main-table: 2 MAIN: main-table MAIN: procedure-main-table MAIN: internal-procedure-main-table: 1
It is now clear that something happens between the two calls to internal procedure: the local main table which was associated with the table from the caller is disconnected so that, in case of the second call, the local table is passed as parameter. Hence, the internal-procedure-main-table: 1 goes to output parameter while internal-procedure-main-table: 2 remains in local main table.
LE: the original code has a small flaw (the main.field1 is displayed while iterating main1 table), but this is really irrelevant as the main1 table is empty.
#5 Updated by Constantin Asofiei over 2 years ago
The problem in this task still exists.