diff --git a/03_ABAP_SQL.md b/03_ABAP_SQL.md
index 58cffcc..84563b4 100644
--- a/03_ABAP_SQL.md
+++ b/03_ABAP_SQL.md
@@ -1113,8 +1113,7 @@ logical expression using `AND` or `OR`. To further
detail out the desired condition, expressions within parentheses are
possible.
-The clause parts that are commented out in the following code snippet
-just demonstrate how the `WHERE` clause might look like.
+For demonstration purposes, various SQL conditions mentioned above are included in a `WHERE` clause:
``` abap
SELECT *
diff --git a/17_SAP_LUW.md b/17_SAP_LUW.md
index 1694c7f..b0bc29d 100644
--- a/17_SAP_LUW.md
+++ b/17_SAP_LUW.md
@@ -368,7 +368,7 @@ The log shows the value 1 for the transaction state after the update task is exe
- Choosing `COMMIT WORK` or `COMMIT WORK AND WAIT` has the same effect: When these statements are called and a `SELECT` statement follows, the number of database table entries is 1 in both cases.
- If the rollback option is selected, the subroutine registered with `ON ROLLBACK` is executed in the current work process.
- The transaction state in the log is 1 for `ON COMMIT` or `ON ROLLBACK` when the corresponding subroutines are called.
- - Note that registered subroutines cannot have a parameter interface, so no parameters can be passed in this type of bundling. Therefore, data can only be passed through external interfaces, such as ABAP memory. In this example, the database table entry created is passed to and from ABAP memory using `EXPORT` and `IMPORT` statements. The subroutines themselves do not implement the writes themselves, but instead call methods of a class.
+ - Note that registered subroutines cannot have a parameter interface, so no parameters can be passed in this type of bundling. Therefore, data can only be passed through external interfaces, such as ABAP memory. In this example, the database table entry created is passed to and from ABAP memory using `EXPORT` and `IMPORT` statements. The subroutines do not implement the writes themselves, but instead call methods of a class.
- The following aspects are valid for all selected options regarding the logs:
- Before the commit is triggered (in the last PAI), the transaction state shows the value 0 for all retrieved transaction states.
- The work process information may change due to the fact that database commits are triggered when completing a dialog step. So you might expect different numbers there, but not necessarily. The new free work process can also be the same as the one before it was freed. However, there will be no different work process information for the update. The numbers will be the same because the update is performed in a single work process.
diff --git a/21_XML_JSON.md b/21_XML_JSON.md
index 0c042e8..8e107df 100644
--- a/21_XML_JSON.md
+++ b/21_XML_JSON.md
@@ -228,11 +228,11 @@ DATA(xml) = CAST cl_sxml_string_writer( writer )->get_output( ).
"
"
" LH
-" 400
+" 400
"
"
" DL
-" 1984
+" 1984
"
"
@@ -250,7 +250,7 @@ TRY.
val->set_value( 'AZ' ).
writer_oo->write_node( val ).
writer_oo->write_node( writer_oo->new_close_element( ) ).
- writer_oo->write_node( writer_oo->new_open_element( name = 'flightNumber' ) ).
+ writer_oo->write_node( writer_oo->new_open_element( name = 'flightnumber' ) ).
val = writer_oo->new_value( ).
val->set_value( '788' ).
writer_oo->write_node( val ).
@@ -263,7 +263,7 @@ TRY.
val->set_value( 'JL' ).
writer_oo->write_node( val ).
writer_oo->write_node( writer_oo->new_close_element( ) ).
- writer_oo->write_node( writer_oo->new_open_element( name = 'flightNumber' ) ).
+ writer_oo->write_node( writer_oo->new_open_element( name = 'flightnumber' ) ).
val = writer_oo->new_value( ).
val->set_value( '407' ).
writer_oo->write_node( val ).
@@ -281,11 +281,11 @@ DATA(xml_oo) = CAST cl_sxml_string_writer( writer_oo )->get_output( ).
"
"
" AZ
-" 788
+" 788
"
"
" JL
-" 407
+" 407
"
"
```
@@ -504,7 +504,7 @@ CALL TRANSFORMATION ... SOURCE ...
```
> **💡 Note**
-> More additions are avaialble such as `PARAMETERS` (for parameter binding) and `OPTIONS` (for predefined transformation options). See the details in the [ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcall_transformation.htm).
+> More additions are available such as `PARAMETERS` (for parameter binding) and `OPTIONS` (for predefined transformation options). See the details in the [ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcall_transformation.htm).
⬆️ back to top
@@ -628,11 +628,10 @@ DATA(conv_string_xco) = xco_cp=>xstring( conv_xstring_xco
> - Creating/Parsing XML Data Using iXML
> - Creating/Parsing XML Data Using sXML
> - XML Transformations using XSLT and Simple Transformations
-> - Creating/Parsing XML Data Using iXML
> - Serializations (ABAP -> XML) and Deserialization (XML -> ABAP) using the identity transformation ID (elementary types, structures, internal tables, data and object references)
> - `CALL TRANSFORMATION` syntax options, sources and targets of transformations
> - Dealing with JSON data
> - Excursions: Converting string <-> xstring, compressing and decompressing binary data
> - uses, apart from the predefined identity transformation (ID), demo XSLT and ST programs. They are not intended to be role models for proper XSLT/ST design.
> - The steps to import and run the code are outlined [here](README.md#🎬-getting-started-with-the-examples).
-> - [Disclaimer](README.md#⚠️-disclaimer)
\ No newline at end of file
+> - [Disclaimer](README.md#-disclaimer)
\ No newline at end of file
diff --git a/README.md b/README.md
index 869269b..d093cfe 100644
--- a/README.md
+++ b/README.md
@@ -229,7 +229,7 @@ There is no guarantee for either the correctness or the completeness of the code
-## 📟 Support and Contribution
+## 📟 Support
This is not intended to be a contribution repository, so please do not create pull requests. If you like to address issues or suggestions, please create an issue. However, this project is provided "as-is": there is no guarantee that raised issues will be answered or addressed in future releases.
diff --git a/src/zbp_demo_abap_rap_ro_u.clas.locals_imp.abap b/src/zbp_demo_abap_rap_ro_u.clas.locals_imp.abap
index e1b4489..d07f01a 100644
--- a/src/zbp_demo_abap_rap_ro_u.clas.locals_imp.abap
+++ b/src/zbp_demo_abap_rap_ro_u.clas.locals_imp.abap
@@ -15,9 +15,11 @@
* and data exchange between a RAP BO consumer, which is a class
* in this case, and RAP BO provider can work. Additionally, it shows
* how the methods for non-standard RAP BO operations might be
-* self-implemented in an ABP. The example is intentionally kept
-* short and simple and focuses on specific RAP aspects. For this reason,
-* the example might not fully meet the requirements of the RAP BO contract.
+* self-implemented in an ABP. The example focuses on specific RAP aspects.
+* For this reason, the example might not fully meet the requirements of
+* the RAP BO contract. Although this unmanaged scenario attempts to
+* replicate some of the functionality of the managed example, the
+* functionality is not fully consistent with the managed scenario.
*
* For demonstration purposes, some of the operations are
* impacted by feature controls and instance authorization as specified
@@ -72,19 +74,11 @@ CLASS lcl_buffer DEFINITION.
cid_ref TYPE string,
cid_target TYPE string,
changed TYPE abap_bool,
+ deleted TYPE abap_bool,
END OF gty_buffer_child.
- TYPES gtt_buffer TYPE TABLE OF gty_buffer
- WITH EMPTY KEY.
-
- TYPES gtt_buffer_child TYPE TABLE OF gty_buffer_child
- WITH EMPTY KEY.
-
- CLASS-DATA:
- "Internal tables serving as transactional buffers for the root and child entities
- root_buffer TYPE STANDARD TABLE OF gty_buffer WITH EMPTY KEY,
- child_buffer TYPE STANDARD TABLE OF gty_buffer_child WITH EMPTY KEY.
-
+ TYPES gtt_buffer TYPE TABLE OF gty_buffer WITH EMPTY KEY.
+ TYPES gtt_buffer_child TYPE TABLE OF gty_buffer_child WITH EMPTY KEY.
"Structure and internal table types to include the keys for buffer preparation methods
TYPES: BEGIN OF root_keys,
key_field TYPE zdemo_abap_rap_ro_u-key_field,
@@ -97,6 +91,11 @@ CLASS lcl_buffer DEFINITION.
tt_root_keys TYPE TABLE OF root_keys WITH EMPTY KEY,
tt_child_keys TYPE TABLE OF child_keys WITH EMPTY KEY.
+ CLASS-DATA:
+ "Internal tables serving as transactional buffers for the root and child entities
+ root_buffer TYPE STANDARD TABLE OF gty_buffer WITH EMPTY KEY,
+ child_buffer TYPE STANDARD TABLE OF gty_buffer_child WITH EMPTY KEY.
+
"Buffer preparation methods
CLASS-METHODS: prep_root_buffer IMPORTING keys TYPE tt_root_keys,
prep_child_buffer IMPORTING keys TYPE tt_child_keys.
@@ -282,7 +281,7 @@ ENDCLASS.
CLASS lhc_root IMPLEMENTATION.
METHOD get_global_authorizations.
- "No implementation on purpose. No global authorization restriction.
+ "No implementation. All users are authorized.
ENDMETHOD.
METHOD create.
@@ -440,14 +439,13 @@ CLASS lhc_root IMPLEMENTATION.
LOOP AT keys REFERENCE INTO DATA(lr_key).
TRY.
lo_lock->enqueue( it_parameter = VALUE #(
- ( name = 'KEY_FIELD' value = REF #(
- lr_key->key_field ) ) ) ).
+ ( name = 'KEY_FIELD' value = REF #( lr_key->key_field ) ) ) ).
CATCH cx_abap_foreign_lock.
- APPEND VALUE #( %key = lr_key->*
+ APPEND VALUE #( %key = CORRESPONDING #( lr_key->* )
%fail-cause = if_abap_behv=>cause-locked )
TO failed-root.
CATCH cx_abap_lock_failure.
- APPEND VALUE #( %key = lr_key->*
+ APPEND VALUE #( %key = CORRESPONDING #( lr_key->* )
%fail-cause = if_abap_behv=>cause-unspecific )
TO failed-root.
ENDTRY.
@@ -461,6 +459,8 @@ CLASS lhc_root IMPLEMENTATION.
METHOD delete.
"Preparing the transactional buffer based on the input BDEF derived type.
lcl_buffer=>prep_root_buffer( CORRESPONDING #( keys ) ).
+ "Preparing the child buffer to mark child instances when parent instances are marked for deletion.
+ lcl_buffer=>prep_child_buffer( VALUE #( FOR wa IN keys ( key_field = wa-key_field ) ) ).
"Processing requested keys sequentially
"Note:
@@ -477,12 +477,14 @@ CLASS lhc_root IMPLEMENTATION.
ASSIGNING FIELD-SYMBOL().
IF sy-subrc = 0.
-
-changed = abap_false.
-deleted = abap_true.
+ "When parent instances are marked for deletion, child instances with the shared key should be marked as well.
+ LOOP AT lcl_buffer=>child_buffer ASSIGNING FIELD-SYMBOL() WHERE instance-key_field = -key_field.
+ -deleted = abap_true.
+ ENDLOOP.
ENDIF.
-
ENDLOOP.
ENDMETHOD.
@@ -498,7 +500,7 @@ CLASS lhc_root IMPLEMENTATION.
"- Line with the shared key value exists in the child buffer
"- If it is true: Sequentially processing the child buffer entries (the example is set up in a way that there can be multiple entries)
IF line_exists( lcl_buffer=>root_buffer[ instance-key_field = -key_field deleted = abap_false ] )
- AND line_exists( lcl_buffer=>child_buffer[ instance-key_field = -key_field ] ).
+ AND line_exists( lcl_buffer=>child_buffer[ instance-key_field = -key_field deleted = abap_false ] ).
LOOP AT lcl_buffer=>child_buffer ASSIGNING FIELD-SYMBOL() WHERE instance-key_field = -key_field.
@@ -510,14 +512,13 @@ CLASS lhc_root IMPLEMENTATION.
"Filling the table for the RESULT parameter based on the FULL parameter
"Note: If the FULL parameter is initial, only the LINK parameter should be provided
IF result_requested = abap_true.
- APPEND VALUE #( %tky = CORRESPONDING #( -%tky )
- key_ch = COND #( WHEN -%control-key_ch NE if_abap_behv=>mk-off
- THEN -instance-key_ch )
+ APPEND VALUE #( key_field = -instance-key_field
+ key_ch = -instance-key_ch
field_ch1 = COND #( WHEN -%control-field_ch1 NE if_abap_behv=>mk-off
THEN -instance-field_ch1 )
field_ch2 = COND #( WHEN -%control-field_ch2 NE if_abap_behv=>mk-off
THEN -instance-field_ch2 )
- ) TO result.
+ ) TO result.
ENDIF.
ENDLOOP.
@@ -837,11 +838,8 @@ CLASS lsc_zdemo_abap_rap_ro_u IMPLEMENTATION.
IF line_exists( lcl_buffer=>root_buffer[ changed = abap_true ] ).
LOOP AT lcl_buffer=>root_buffer ASSIGNING FIELD-SYMBOL() WHERE changed = abap_true AND deleted = abap_false.
-
APPEND CORRESPONDING #( -instance ) TO mod_tab.
-
ENDLOOP.
-
MODIFY zdemo_abap_rapt1 FROM TABLE @( CORRESPONDING #( mod_tab ) ).
ENDIF.
@@ -850,14 +848,26 @@ CLASS lsc_zdemo_abap_rap_ro_u IMPLEMENTATION.
DATA del_tab TYPE lcl_buffer=>tt_root_keys.
IF line_exists( lcl_buffer=>root_buffer[ deleted = abap_true ] ).
-
LOOP AT lcl_buffer=>root_buffer ASSIGNING FIELD-SYMBOL() WHERE deleted = abap_true.
-
APPEND CORRESPONDING #( -instance ) TO del_tab.
-
ENDLOOP.
-
DELETE zdemo_abap_rapt1 FROM TABLE @( CORRESPONDING #( del_tab ) ).
+
+ "Processing database entries of child entity: When the parent instance is deleted,
+ "the corresponding child instances are deleted.
+ SELECT key_field, key_ch
+ FROM zdemo_abap_rapt2 AS db
+ WHERE EXISTS
+ ( SELECT * FROM @del_tab AS it
+ WHERE key_field = db~key_field )
+ INTO TABLE @DATA(child_keys).
+
+ "Deleting entries from database table
+ DELETE zdemo_abap_rapt2 FROM TABLE @( CORRESPONDING #( child_keys ) ).
+ "Deleting instances from child buffer
+ "LOOP AT lcl_buffer=>child_buffer ASSIGNING FIELD-SYMBOL().
+ DELETE lcl_buffer=>child_buffer WHERE instance-key_field = -instance-key_field AND deleted = abap_true.
+ "ENDLOOP.
ENDIF.
"Processing the saving of create-by-association operations.
@@ -865,11 +875,8 @@ CLASS lsc_zdemo_abap_rap_ro_u IMPLEMENTATION.
IF line_exists( lcl_buffer=>child_buffer[ changed = abap_true ] ).
LOOP AT lcl_buffer=>child_buffer ASSIGNING FIELD-SYMBOL() WHERE changed = abap_true.
-
APPEND CORRESPONDING #( -instance ) TO cba_tab.
-
ENDLOOP.
-
MODIFY zdemo_abap_rapt2 FROM TABLE @( CORRESPONDING #( cba_tab ) ).
ENDIF.
ENDMETHOD.
@@ -927,7 +934,7 @@ CLASS lhc_child IMPLEMENTATION.
instance-key_ch = -key_ch
ASSIGNING FIELD-SYMBOL().
- IF sy-subrc = 0.
+ IF sy-subrc = 0 AND -deleted = abap_false.
APPEND VALUE #( %tky = -%tky
field_ch1 = COND #( WHEN -%control-field_ch1 NE if_abap_behv=>mk-off
@@ -964,12 +971,12 @@ CLASS lhc_child IMPLEMENTATION.
"- Line with the full key exists in the child buffer
"- If it is true: Adding the instance to the RESULT parameter considering %control values
IF line_exists( lcl_buffer=>root_buffer[ instance-key_field = -key_field deleted = abap_false ] )
- AND line_exists( lcl_buffer=>child_buffer[ instance-key_field = -key_field instance-key_ch = -key_ch ] ).
+ AND line_exists( lcl_buffer=>child_buffer[ instance-key_field = -key_field instance-key_ch = -key_ch deleted = abap_false ] ).
"Filling the LINK parameter
INSERT VALUE #( target-%tky = CORRESPONDING #( -%tky )
source-%tky = VALUE #( key_field = -key_field
- key_ch = -key_ch )
+ key_ch = -key_ch )
) INTO TABLE association_links.
IF result_requested = abap_true.
@@ -1019,4 +1026,4 @@ CLASS lhc_child IMPLEMENTATION.
ENDMETHOD.
-ENDCLASS.
+ENDCLASS.
\ No newline at end of file