In an ABAP program I have noticed unexpected persistence of data when displaying a local table using the class cl_salv_table
.
To reproduce I have created a minimal code sample. The program does an insert, displays data in an ALV, then does a ROLLBACK WORK
.
I expect the inserted value to be present in the database BEFORE the rollback, and absent AFTER the rollback.
However, if between the insert and the rollback, an ALV grid is displayed, the data is persisted beyond the rollback, and immediately visible to other transactions.
Is this expected behaviour, and if so, how can I avoid this? We do use this class quite often and it looks like we may inadvertently commit values to database when we don't actually want to.
This is the code:
*&---------------------------------------------------------------------*
*& Report zok_alv_commit
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zok_alv_commit.
SELECTION-SCREEN BEGIN OF BLOCK b1.
PARAMETERS: p_showtb TYPE boolean AS CHECKBOX DEFAULT abap_false.
SELECTION-SCREEN END OF BLOCK b1.
START-OF-SELECTION.
DATA: lt_table TYPE TABLE OF zok_alv,
ls_table TYPE zok_alv.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Create new GUID and insert into table
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
TRY.
ls_table-guid = cl_system_uuid=>create_uuid_c22_static( ).
CATCH cx_uuid_error.
" Error creating UUID
MESSAGE e836(/basf/dps3_apodata).
ENDTRY.
WRITE: |Create guid { ls_table-guid } |, /.
INSERT zok_alv FROM ls_table.
APPEND ls_table TO lt_table.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" The important bit: show something in an ALV
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
IF p_showtb = abap_true.
cl_salv_table=>factory(
IMPORTING r_salv_table = DATA(lo_alv)
CHANGING t_table = lt_table
).
lo_alv->display( ).
ENDIF.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Check existence in table before and after rollback
" Expectation: If the ALV is shown above, the data is already committed,
" so the ROLLBACK WORK will not have an effect.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
SELECT SINGLE guid FROM zok_alv INTO @DATA(lv_ignored) WHERE guid = @ls_table-guid.
IF sy-subrc = 0.
WRITE: 'GUID exists on DB before rollback.', /.
ELSE.
WRITE: 'GUID does NOT exist on DB before rollback.', /.
ENDIF.
ROLLBACK WORK.
SELECT SINGLE guid FROM zok_alv INTO @lv_ignored WHERE guid = @ls_table-guid.
IF sy-subrc = 0.
WRITE: 'GUID exists on DB after rollback.', /.
ELSE.
WRITE: 'GUID does NOT exist on DB after rollback.', /.
ENDIF.
It requires a table ZOK_ALV
with only MANDT
and a 22-character field GUID
as primary key, nothing else.
When executing the code with p_showtb
unchecked:
As you can see, the value is not present after the rollback, and not present in the table - as expected.
When executing the code with p_showtb
checked:
At this point, already, the id is visible in SE16 in another session:
(I leave the ALV screen with Back (F3)
at this point)
The code confirms, the value is still present, even after the rollback:
Even after leaving the program, the values persist in the DB.
To answer the 2 questions:
1) Yes, this is the "expected behavior" as stated in the database commit documentation :
a database commit is performed implicitly in the following situation: Completion of a dialog step ...
(it means that any display does a database commit)
This is because when the screen is displayed, SAP doesn't do anything except waiting for the user action, so the workprocess which was used to execute the ABAP code prior to the display can be reused for executing the ABAP code of requests from other users.
So that the workprocess can be reused, the memory of the workprocess (variables) is to be switched, it's called the roll-out/roll-in, which also requires that some system database tables are updated for internal SAP stuff and a database commit is needed for that. This is better explained in the documentation of SAP LUWs. I read that somewhere but I don't remember exactly where.
2) No, you can't "avoid this behavior", but considering your current logic of insert + display + rollback the insert, you can do one of these solutions but I recommend only the first one in your case, not the second one:
CALL FUNCTION '...' DESTINATION 'NONE' KEEPING LOGICAL UNIT OF WORK
(cf documentation). It's not recommended because it's for internal use only. It's counter-performing because it occupies 2 workprocesses at the same time. It's dangerous because "the worst case scenario may be a system shutdown".If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With