Jagger
Jagger

Reputation: 10524

Using the same itab on left and right side of VALUE results in empty table. Why?

Here's one for you…

How come this code results in an empty table gt_test2

gt_test2 = VALUE #(
  FOR gs_test1 IN gt_test1 WHERE ( v3 = gs_test3-v3 AND v4 = gs_test3-v4 )
  FOR gs_test2 IN gt_test2 WHERE ( v1 = gs_test1-v1 AND v2 = gs_test1-v2 )
  ( gs_test2 )
).
WRITE / lines( gt_test2 ).

and this one produces a correct result?

DATA: gt_test2_2 LIKE gt_test2.
gt_test2_2 = VALUE #(
  FOR gs_test1 IN gt_test1 WHERE ( v3 = gs_test3-v3 AND v4 = gs_test3-v4 )
  FOR gs_test2 IN gt_test2 WHERE ( v1 = gs_test1-v1 AND v2 = gs_test1-v2 )
  ( gs_test2 )
).
WRITE / lines( gt_test2_2 ).

Is this a bug in ABAP!? I always thought first the right side of an expression is evaluated and then assigned to the left one. In this ABAP construct however it does seem that the left side is somehow used internally while calculating the right one, which leads to an incorrect result.

Minimal working example.

REPORT ZZZ.

TYPES: BEGIN OF ty_test1,
  v1 TYPE char40,
  v2 TYPE char6,
  v3 TYPE char6,
  v4 TYPE char32,
  END OF ty_test1,
  BEGIN OF ty_test2,
    v1 TYPE char40,
    v2 TYPE char6,
    v5 TYPE numc3,
  END OF ty_test2,
  BEGIN OF ty_test3,
    v3 TYPE char6,
    v4 TYPE char32,
  END OF ty_test3.
TYPES: tty_test1 TYPE STANDARD TABLE OF ty_test1 WITH EMPTY KEY,
  tty_test2 TYPE STANDARD TABLE OF ty_test2 WITH EMPTY KEY.

INITIALIZATION.
  DATA(gt_test1) = VALUE tty_test1(
    ( v1 = '1' v2 = '007001' v3 = '0012345678' v4 = '001061' )
    ( v1 = '2' v2 = '007001' v3 = '0999999953' v4 = '001061' )
  ).
  DATA(gt_test2) = VALUE tty_test2(
    ( v1 = '1' v2 = '007001' v5 = '10' )
    ( v1 = '2' v2 = '007001' v5 = '15' )
  ).
  DATA(gs_test3) = VALUE ty_test3( v3 = '0999999953' v4 = '001061' ).

START-OF-SELECTION.
*  DATA: gt_test2_2 LIKE gt_test2.
*  gt_test2_2 =
  gt_test2 =
  VALUE #(
    FOR gs_test1 IN gt_test1 WHERE ( v3 = gs_test3-v3 AND v4 = gs_test3-v4 )
    FOR gs_test2 IN gt_test2 WHERE ( v1 = gs_test1-v1 AND v2 = gs_test1-v2 )
    ( gs_test2 )
  ).
  WRITE / lines( gt_test2 ).
*  WRITE / lines( gt_test2_2 ).

Upvotes: 2

Views: 296

Answers (2)

Suncatcher
Suncatcher

Reputation: 10621

Sandra is right, but you can overcome this limitation with FILTER op, which lacks such disappointing blocker. If you wanna avoid creating new table, you can rethink your sample that way:

...
TYPES: tty_test1 TYPE SORTED TABLE OF ty_test1 WITH NON-UNIQUE KEY primary_key COMPONENTS v1 v2
                                               WITH NON-UNIQUE SORTED KEY filt COMPONENTS v3 v4,
       tty_test2 TYPE SORTED TABLE OF ty_test2 WITH NON-UNIQUE KEY primary_key COMPONENTS v1 v2.
...

gt_test1 = FILTER #( gt_test1 USING KEY filt WHERE v3 = gs_test3-v3 AND v4 = gs_test3-v4 ).
gt_test2 = FILTER #( gt_test2 IN gt_test1 WHERE v1 = v1 AND v2 = v2 ).

Upvotes: 2

Sandra Rossi
Sandra Rossi

Reputation: 13628

With a constructor expression, the target data object is first cleared, hence the result you experienced: the internal table gt_test2 is empty at the time of the FOR loop.

In your case, you may use LET, which is called before the target data object is cleared, to transfer the internal table into an auxiliary internal table.

ABAP Documentation - "VALUE, Internal Tables" :

If the VALUE operator is used as the source of an assignment to an internal table, it is first initialized after the evaluation of a possible LET expression or is assigned the content of itab. Then, line_spec data is then evaluated and inserted directly into the target table.

In assignments of constructor expressions to an internal table, its existing lines cannot be used directly as an argument in line_spec. This is because this table is deleted before line_spec is evaluated or overwritten by the content of itab. If the entire internal table or lines from the left side are needed on the right side, however, they can be saved in local helper variables using a LET expression, since this expression is evaluated first.

Upvotes: 4

Related Questions