Project

General

Profile

Bug #6997

OUTPUT BY-REFERENCE records are not cleared

Added by Dănuț Filimon over 1 year ago. Updated 4 months ago.

Status:
New
Priority:
Normal
Assignee:
-
Target version:
-
Start date:
Due date:
% Done:

0%

billable:
No
vendor_id:
GCD
case_num:
version_reported:
version_resolved:

Related issues

Related to Database - Support #6714: check if there is an optimization opportunity when copying temp-tables based on multiplex id Review

History

#1 Updated by Dănuț Filimon over 1 year 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 1 year 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 1 year ago

It does not make full sense. The BY-REFERENCE should be bound to the target table temporarily, hiding that table. As result:
  • the CREATE /ASSIGN from int1 are actually performed directly into the main of the start.p which was sent BY-REFERENCE twice. This seems to work correctly;
  • after leaving int1, the local main and main1 are not bound any more (although the main is still bound to start.p's table as parameter). The creation of main record which should-not-exist should be created the very same way as the internal-procedure-main-table. If the binding between main and main1 still existed, the main1 NPP2 loop would have display it. So it must be created in the main table which is still bound as output parameter to the table from start.p. Actually, there is no difference between the two CREATEs in the test-ttbyref83proc.p procedure. The only factor which affects them is the call to internal procedure int1.
  • 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 local main is unbound from the parameter and the main NPP1 and 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 1 year 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 4 months ago

The problem in this task still exists.

Also available in: Atom PDF