TABU: Update entries with same key but different component values (#6380)

Co-authored-by: Lars Hvam <larshp@hotmail.com>
This commit is contained in:
Marius Raht 2023-08-02 06:35:20 +02:00 committed by GitHub
parent 34e40c1d9d
commit 9d2bb4da0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 237 additions and 21 deletions

View File

@ -21,7 +21,8 @@ CLASS zcl_abapgit_data_deserializer DEFINITION
IMPORTING
!iv_name TYPE tadir-obj_name
!it_where TYPE string_table
!ir_data TYPE REF TO data
!ir_lc_data TYPE REF TO data
!ir_db_data TYPE REF TO data
RETURNING
VALUE(rs_result) TYPE zif_abapgit_data_deserializer=>ty_result
RAISING
@ -31,6 +32,7 @@ CLASS zcl_abapgit_data_deserializer DEFINITION
!iv_name TYPE tadir-obj_name
!ir_del TYPE REF TO data
!ir_ins TYPE REF TO data
!ir_upd TYPE REF TO data
RAISING
zcx_abapgit_exception .
METHODS read_database_table
@ -112,23 +114,18 @@ CLASS zcl_abapgit_data_deserializer IMPLEMENTATION.
METHOD preview_database_changes.
* method currently distinguishes between records be deleted and inserted (comparison of complete record)
* to-do: compare records based on database key of table to determine updates to existing records
DATA lr_data TYPE REF TO data.
FIELD-SYMBOLS <lg_old> TYPE ANY TABLE.
FIELD-SYMBOLS <lg_new> TYPE ANY TABLE.
FIELD-SYMBOLS <ls_del> TYPE any.
FIELD-SYMBOLS <ls_ins> TYPE any.
FIELD-SYMBOLS <ls_upd> TYPE any.
FIELD-SYMBOLS <lg_del> TYPE ANY TABLE.
FIELD-SYMBOLS <lg_ins> TYPE ANY TABLE.
FIELD-SYMBOLS <lg_upd> TYPE ANY TABLE.
lr_data = read_database_table(
iv_name = iv_name
it_where = it_where ).
ASSIGN lr_data->* TO <lg_old>.
ASSIGN ir_data->* TO <lg_new>.
ASSIGN ir_db_data->* TO <lg_old>.
ASSIGN ir_lc_data->* TO <lg_new>.
rs_result-type = zif_abapgit_data_config=>c_data_type-tabu.
rs_result-name = iv_name.
@ -137,6 +134,7 @@ CLASS zcl_abapgit_data_deserializer IMPLEMENTATION.
rs_result-updates = zcl_abapgit_data_utils=>build_table_itab( iv_name ).
ASSIGN rs_result-deletes->* TO <lg_del>.
ASSIGN rs_result-inserts->* TO <lg_ins>.
ASSIGN rs_result-updates->* TO <lg_upd>.
<lg_del> = <lg_old>.
<lg_ins> = <lg_new>.
@ -145,6 +143,10 @@ CLASS zcl_abapgit_data_deserializer IMPLEMENTATION.
LOOP AT <lg_del> ASSIGNING <ls_del>.
READ TABLE <lg_ins> ASSIGNING <ls_ins> FROM <ls_del>.
IF sy-subrc = 0.
IF <ls_del> <> <ls_ins>.
" Identical key but not identical component values
INSERT <ls_ins> INTO TABLE <lg_upd>.
ENDIF.
DELETE TABLE <lg_del> FROM <ls_del>.
DELETE TABLE <lg_ins> FROM <ls_ins>.
ENDIF.
@ -176,6 +178,7 @@ CLASS zcl_abapgit_data_deserializer IMPLEMENTATION.
FIELD-SYMBOLS <lg_del> TYPE ANY TABLE.
FIELD-SYMBOLS <lg_ins> TYPE ANY TABLE.
FIELD-SYMBOLS <lg_upd> TYPE ANY TABLE.
IF zcl_abapgit_data_utils=>does_table_exist( iv_name ) = abap_false.
zcx_abapgit_exception=>raise( |Table { iv_name } not found for data deserialization| ).
@ -183,6 +186,7 @@ CLASS zcl_abapgit_data_deserializer IMPLEMENTATION.
ASSIGN ir_del->* TO <lg_del>.
ASSIGN ir_ins->* TO <lg_ins>.
ASSIGN ir_upd->* TO <lg_upd>.
IF lines( <lg_del> ) > 0.
DELETE (iv_name) FROM TABLE <lg_del>.
@ -198,6 +202,13 @@ CLASS zcl_abapgit_data_deserializer IMPLEMENTATION.
ENDIF.
ENDIF.
IF lines( <lg_upd> ) > 0.
UPDATE (iv_name) FROM TABLE <lg_upd>.
IF sy-subrc <> 0.
zcx_abapgit_exception=>raise( |Error updating { lines( <lg_upd> ) } records into table { iv_name }| ).
ENDIF.
ENDIF.
ENDMETHOD.
@ -236,11 +247,12 @@ CLASS zcl_abapgit_data_deserializer IMPLEMENTATION.
write_database_table(
iv_name = ls_result-name
ir_del = ls_result-deletes
ir_ins = ls_result-inserts ).
ir_ins = ls_result-inserts
ir_upd = ls_result-updates ).
ASSIGN ls_result-inserts->* TO <lt_ins>.
ASSIGN ls_result-deletes->* TO <lt_del>.
ASSIGN ls_result-updates->* TO <lt_upd>. " not used
ASSIGN ls_result-updates->* TO <lt_upd>.
IF zcl_abapgit_data_utils=>is_customizing_table( ls_result-name ) = abap_true.
IF li_cts_api IS INITIAL.
@ -267,10 +279,11 @@ CLASS zcl_abapgit_data_deserializer IMPLEMENTATION.
* this method does not persist any changes to the database
DATA lt_configs TYPE zif_abapgit_data_config=>ty_config_tt.
DATA ls_config LIKE LINE OF lt_configs.
DATA lr_data TYPE REF TO data.
DATA ls_file LIKE LINE OF it_files.
DATA ls_result LIKE LINE OF rt_result.
DATA ls_config LIKE LINE OF lt_configs.
DATA lr_lc_data TYPE REF TO data.
DATA lr_db_data TYPE REF TO data.
DATA ls_file LIKE LINE OF it_files.
DATA ls_result LIKE LINE OF rt_result.
lt_configs = ii_config->get_configs( ).
@ -278,7 +291,7 @@ CLASS zcl_abapgit_data_deserializer IMPLEMENTATION.
ASSERT ls_config-type = zif_abapgit_data_config=>c_data_type-tabu. " todo
ASSERT ls_config-name IS NOT INITIAL.
lr_data = zcl_abapgit_data_utils=>build_table_itab( ls_config-name ).
lr_lc_data = zcl_abapgit_data_utils=>build_table_itab( ls_config-name ).
READ TABLE it_files INTO ls_file
WITH KEY file_path
@ -286,13 +299,18 @@ CLASS zcl_abapgit_data_deserializer IMPLEMENTATION.
filename = zcl_abapgit_data_utils=>build_data_filename( ls_config ).
IF sy-subrc = 0.
convert_json_to_itab(
ir_data = lr_data
ir_data = lr_lc_data
is_file = ls_file ).
ls_result = preview_database_changes(
lr_db_data = read_database_table(
iv_name = ls_config-name
it_where = ls_config-where
ir_data = lr_data ).
it_where = ls_config-where ).
ls_result = preview_database_changes(
iv_name = ls_config-name
it_where = ls_config-where
ir_lc_data = lr_lc_data
ir_db_data = lr_db_data ).
MOVE-CORRESPONDING ls_file TO ls_result-file. " data file

View File

@ -5,6 +5,9 @@ CLASS ltcl_test DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS FINAL.
PRIVATE SECTION.
METHODS test1 FOR TESTING RAISING cx_static_check.
METHODS preview_database_changes_ins FOR TESTING RAISING cx_static_check.
METHODS preview_database_changes_upd FOR TESTING RAISING cx_static_check.
METHODS preview_database_changes_del FOR TESTING RAISING cx_static_check.
ENDCLASS.
@ -33,4 +36,199 @@ CLASS ltcl_test IMPLEMENTATION.
ENDMETHOD.
METHOD preview_database_changes_ins.
CONSTANTS: lc_msgnr TYPE c LENGTH 3 VALUE '999'.
DATA: li_cut TYPE REF TO zcl_abapgit_data_deserializer,
ls_config TYPE zif_abapgit_data_config=>ty_config,
lr_db_data TYPE REF TO data,
lr_lc_data TYPE REF TO data,
ls_t100 TYPE t100,
ls_result TYPE zif_abapgit_data_deserializer=>ty_result.
FIELD-SYMBOLS: <lt_db_data> TYPE ANY TABLE,
<lt_lc_data> TYPE ANY TABLE,
<lg_ins> TYPE ANY TABLE,
<ls_ins> TYPE t100,
<lg_upd> TYPE ANY TABLE,
<lg_del> TYPE ANY TABLE.
ls_config-type = zif_abapgit_data_config=>c_data_type-tabu.
ls_config-name = 'T100'.
lr_db_data = zcl_abapgit_data_utils=>build_table_itab( ls_config-name ).
ASSIGN lr_db_data->* TO <lt_db_data>.
lr_lc_data = zcl_abapgit_data_utils=>build_table_itab( ls_config-name ).
ASSIGN lr_lc_data->* TO <lt_lc_data>.
" Create test data for INSERT
ls_t100-sprsl = sy-langu.
ls_t100-arbgb = 'AUNIT_ABAPGIT'.
ls_t100-msgnr = lc_msgnr.
ls_t100-text = |abapGit aunit test|.
INSERT ls_t100 INTO TABLE <lt_lc_data>.
CREATE OBJECT li_cut TYPE zcl_abapgit_data_deserializer.
ls_result = li_cut->preview_database_changes(
iv_name = ls_config-name
it_where = ls_config-where
ir_db_data = lr_db_data
ir_lc_data = lr_lc_data ).
ASSIGN ls_result-inserts->* TO <lg_ins>.
ASSIGN ls_result-updates->* TO <lg_upd>.
ASSIGN ls_result-deletes->* TO <lg_del>.
cl_abap_unit_assert=>assert_equals(
exp = 1
act = lines( <lg_ins> ) ).
cl_abap_unit_assert=>assert_equals(
exp = 0
act = lines( <lg_upd> ) ).
cl_abap_unit_assert=>assert_equals(
exp = 0
act = lines( <lg_del> ) ).
LOOP AT <lg_ins> ASSIGNING <ls_ins>.
cl_abap_unit_assert=>assert_equals(
exp = lc_msgnr
act = <ls_ins>-msgnr ).
ENDLOOP.
ENDMETHOD.
METHOD preview_database_changes_upd.
CONSTANTS: lc_msgnr TYPE c LENGTH 3 VALUE '999'.
DATA: li_cut TYPE REF TO zcl_abapgit_data_deserializer,
ls_config TYPE zif_abapgit_data_config=>ty_config,
lr_db_data TYPE REF TO data,
lr_lc_data TYPE REF TO data,
ls_t100 TYPE t100,
ls_result TYPE zif_abapgit_data_deserializer=>ty_result.
FIELD-SYMBOLS: <lt_db_data> TYPE ANY TABLE,
<lt_lc_data> TYPE ANY TABLE,
<lg_ins> TYPE ANY TABLE,
<lg_upd> TYPE ANY TABLE,
<ls_upd> TYPE t100,
<lg_del> TYPE ANY TABLE.
ls_config-type = zif_abapgit_data_config=>c_data_type-tabu.
ls_config-name = 'T100'.
lr_db_data = zcl_abapgit_data_utils=>build_table_itab( ls_config-name ).
ASSIGN lr_db_data->* TO <lt_db_data>.
lr_lc_data = zcl_abapgit_data_utils=>build_table_itab( ls_config-name ).
ASSIGN lr_lc_data->* TO <lt_lc_data>.
" Create test data for UPDATE
ls_t100-sprsl = sy-langu.
ls_t100-arbgb = |AUNIT_ABAPGIT|.
ls_t100-msgnr = lc_msgnr.
ls_t100-text = |abapGit aunit test|.
INSERT ls_t100 INTO TABLE <lt_db_data>.
ls_t100-sprsl = sy-langu.
ls_t100-arbgb = 'AUNIT_ABAPGIT'.
ls_t100-msgnr = lc_msgnr.
ls_t100-text = |abapGit aunit test UPDATE|.
INSERT ls_t100 INTO TABLE <lt_lc_data>.
CREATE OBJECT li_cut TYPE zcl_abapgit_data_deserializer.
ls_result = li_cut->preview_database_changes(
iv_name = ls_config-name
it_where = ls_config-where
ir_db_data = lr_db_data
ir_lc_data = lr_lc_data ).
ASSIGN ls_result-inserts->* TO <lg_ins>.
ASSIGN ls_result-updates->* TO <lg_upd>.
ASSIGN ls_result-deletes->* TO <lg_del>.
cl_abap_unit_assert=>assert_equals(
exp = 0
act = lines( <lg_ins> ) ).
cl_abap_unit_assert=>assert_equals(
exp = 1
act = lines( <lg_upd> ) ).
cl_abap_unit_assert=>assert_equals(
exp = 0
act = lines( <lg_del> ) ).
LOOP AT <lg_upd> ASSIGNING <ls_upd>.
cl_abap_unit_assert=>assert_equals(
exp = lc_msgnr
act = <ls_upd>-msgnr ).
ENDLOOP.
ENDMETHOD.
METHOD preview_database_changes_del.
CONSTANTS: lc_msgnr TYPE c LENGTH 3 VALUE '999'.
DATA: li_cut TYPE REF TO zcl_abapgit_data_deserializer,
ls_config TYPE zif_abapgit_data_config=>ty_config,
lr_db_data TYPE REF TO data,
lr_lc_data TYPE REF TO data,
ls_t100 TYPE t100,
ls_result TYPE zif_abapgit_data_deserializer=>ty_result.
FIELD-SYMBOLS: <lt_db_data> TYPE ANY TABLE,
<lt_lc_data> TYPE ANY TABLE,
<lg_ins> TYPE ANY TABLE,
<lg_upd> TYPE ANY TABLE,
<lg_del> TYPE ANY TABLE,
<ls_del> TYPE t100.
ls_config-type = zif_abapgit_data_config=>c_data_type-tabu.
ls_config-name = 'T100'.
lr_db_data = zcl_abapgit_data_utils=>build_table_itab( ls_config-name ).
ASSIGN lr_db_data->* TO <lt_db_data>.
lr_lc_data = zcl_abapgit_data_utils=>build_table_itab( ls_config-name ).
ASSIGN lr_lc_data->* TO <lt_lc_data>.
" Create test data for DELETE
ls_t100-sprsl = sy-langu.
ls_t100-arbgb = 'AUNIT_ABAPGIT'.
ls_t100-msgnr = lc_msgnr.
ls_t100-text = |abapGit aunit test DELETE|.
INSERT ls_t100 INTO TABLE <lt_db_data>.
CREATE OBJECT li_cut TYPE zcl_abapgit_data_deserializer.
ls_result = li_cut->preview_database_changes(
iv_name = ls_config-name
it_where = ls_config-where
ir_db_data = lr_db_data
ir_lc_data = lr_lc_data ).
ASSIGN ls_result-inserts->* TO <lg_ins>.
ASSIGN ls_result-updates->* TO <lg_upd>.
ASSIGN ls_result-deletes->* TO <lg_del>.
cl_abap_unit_assert=>assert_equals(
exp = 0
act = lines( <lg_ins> ) ).
cl_abap_unit_assert=>assert_equals(
exp = 0
act = lines( <lg_upd> ) ).
cl_abap_unit_assert=>assert_equals(
exp = 1
act = lines( <lg_del> ) ).
LOOP AT <lg_del> ASSIGNING <ls_del>.
cl_abap_unit_assert=>assert_equals(
exp = lc_msgnr
act = <ls_del>-msgnr ).
ENDLOOP.
ENDMETHOD.
ENDCLASS.