diff --git a/05_Constructor_Expressions.md b/05_Constructor_Expressions.md
index 7e3a726..201e3b1 100644
--- a/05_Constructor_Expressions.md
+++ b/05_Constructor_Expressions.md
@@ -437,15 +437,16 @@ MODIFY ENTITIES OF zdemo_abap_rap_ro_m
|
-Assigning incompatible structures
+Assigning incompatible structures and internal tables
|
- The example makes use of the `BASE` addition, and includes a `CORRESPONDING` expression.
-- The `s1` structure is assigned the identically named components of the `s2` structure.
-- Other components are assigned by explicitly specifying them.
+- The `s1` structure is assigned the identically named components of the `s2` structure. Other components are assigned by explicitly specifying them.
+- Another example performs an assignment with internal tables, using a table iteration with a `FOR` loop.
+-
@@ -465,6 +466,37 @@ DATA:
END OF s2.
s1 = VALUE #( BASE CORRESPONDING #( s2 ) comp4 = 4 comp5 = 5 ).
+
+DATA itab1 LIKE TABLE OF s1 WITH EMPTY KEY.
+DATA itab2 LIKE TABLE OF s2 WITH EMPTY KEY.
+
+itab1 = VALUE #( ( comp1 = 1 comp2 = 2 comp3 = 3 comp4 = 4 comp5 = 5 )
+ ( comp1 = 10 comp2 = 20 comp3 = 30 comp4 = 40 comp5 = 50 )
+ ( comp1 = 100 comp2 = 200 comp3 = 300 comp4 = 400 comp5 = 500 ) ).
+
+itab2 = VALUE #( ( comp1 = 7 comp2 = 8 comp3 = 9 )
+ ( comp1 = 70 comp2 = 80 comp3 = 90 )
+ ( comp1 = 700 comp2 = 800 comp3 = 900 ) ).
+
+itab1 = VALUE #( BASE itab1 FOR wa IN itab2 ( CORRESPONDING #( wa ) ) ).
+
+*Result:
+*COMP1 COMP2 COMP3 COMP4 COMP5
+*1 2 3 4 5
+*10 20 30 40 50
+*100 200 300 400 500
+*7 8 9 0 0
+*70 80 90 0 0
+*700 800 900 0 0
+
+"Note: If BASE is not specified, the target table is initialized first.
+"itab1 = VALUE #( FOR wa IN itab2 ( CORRESPONDING #( wa ) ) ).
+
+*Result:
+*COMP1 COMP2 COMP3 COMP4 COMP5
+*7 8 9 0 0
+*70 80 90 0 0
+*700 800 900 0 0
```
|
@@ -497,6 +529,12 @@ DATA(itab) = VALUE itab_type( ( col1 = 'a' col2 = 1 col3 = 30 )
DATA(it1) = VALUE itab_type( FOR wa IN itab ( col1 = wa-col1 && 'z'
col2 = wa-col2 + 1 ) ).
+
+*Result:
+*COL1 COL2 COL3
+*az 2 0
+*bbz 3 0
+*cccz 4 0
```
@@ -521,6 +559,11 @@ DATA(strtab) = VALUE string_table( LET mark = '!' IN
( |abc{ mark }| )
( |def{ mark }| )
( |ghi{ mark }| ) ).
+
+*Result:
+*abc!
+*def!
+*ghi!
```
@@ -1734,6 +1777,7 @@ ENDCASE.
- The conditions for the table key components can be specified as follows:
- Hash keys: Only the comparison operator `=` is allowed
- Sorted key: `=`/`EQ`, `<>`/`NE`, `<`/`LT`, `>`/`GT`, `<=`/`LE`, `>=`/`GE`
+ - When filtering using single values, you can also use `IS [NOT] INITIAL`.
- Multiple comparisons can be combined using `AND`; boolean operators such as `NOT` or `OR` cannot be specified.
- Notes on the filter table:
- The line types of the source and filter table need not be identical.
diff --git a/06_Dynamic_Programming.md b/06_Dynamic_Programming.md
index 7144f3f..bd5dae9 100644
--- a/06_Dynamic_Programming.md
+++ b/06_Dynamic_Programming.md
@@ -1951,7 +1951,8 @@ SORT it BY VALUE abap_sortorder_tab( FOR wa IN comp_names ( name = condense( to_
### Dynamic ABAP SQL Statements
```abap
-"Dynamic SELECT list
+"--------------------- Dynamic SELECT list ---------------------
+
DATA(select_list) = `CARRID, CONNID, FLDATE`.
DATA fli_tab TYPE TABLE OF zdemo_abap_fli WITH EMPTY KEY.
@@ -1959,13 +1960,15 @@ SELECT (select_list)
FROM zdemo_abap_fli
INTO CORRESPONDING FIELDS OF TABLE @fli_tab.
-"Dynamic FROM clause
+"--------------------- Dynamic FROM clause ---------------------
+
DATA(table) = 'ZDEMO_ABAP_FLI'.
SELECT *
FROM (table)
INTO TABLE @fli_tab.
-"Excursion: Compatible target data objects
+"--------------------- Excursion: Compatible target data objects ---------------------
+
"In the examples above, the data object/type is created statically.
"Creating an anonymous data object with a CREATE DATA statement
@@ -1994,35 +1997,44 @@ SELECT *
FROM (table)
INTO TABLE NEW @DATA(dref_tab).
-"Dynamic WHERE clause
+"--------------------- Dynamic WHERE clause ---------------------
+
"The example includes a WHERE clause that is created as an internal
"table with a character-like row type.
DATA(where_clause) = VALUE string_table( ( `CARRID = 'LH'` )
( `OR` )
( `CARRID = 'AA'` ) ).
-"A string as an alternative
-"DATA(where_clause) = `CARRID = 'LH' OR CARRID = 'AA'`.
-
SELECT *
FROM zdemo_abap_fli
WHERE (where_clause)
INTO TABLE NEW @DATA(tab_dyn_where).
-"Dynamic ORDER BY clause
+"A string as an alternative
+DATA(where_clause_string) = `CARRID = 'LH' OR CARRID = 'AA'`.
+
+SELECT *
+ FROM zdemo_abap_fli
+ WHERE (where_clause_string)
+ INTO TABLE NEW @DATA(tab_dyn_where_str).
+
+"--------------------- Dynamic ORDER BY clause ---------------------
+
SELECT *
FROM zdemo_abap_fli
ORDER BY (`FLDATE`)
INTO TABLE NEW @DATA(tab_dyn_order).
-"SELECT statement with miscellaneous dynamic specifications
+"----- SELECT statement with miscellaneous dynamic specifications -----
+
SELECT (`CARRID, CONNID, FLDATE`)
FROM (`ZDEMO_ABAP_FLI`)
WHERE (`CARRID <> ``AA```)
ORDER BY (`FLDATE`)
INTO TABLE NEW @DATA(tab_dyn_misc).
-"Further dynamic specifications in other ABAP SQL statements
+"--------------------- Dynamic INSERT statement ---------------------
+
"Creating a structure to be inserted into the database table
SELECT SINGLE *
FROM (table)
@@ -2031,13 +2043,97 @@ dref_struc->('CARRID') = 'YZ'.
INSERT (table) FROM @dref_struc->*.
+"--------------------- Dynamic UPDATE statement ---------------------
+
dref_struc->('CURRENCY') = 'EUR'.
UPDATE (table) FROM @dref_struc->*.
+"--------------------- Dynamic MODIFY statement ---------------------
+
dref_struc->('SEATSOCC') = 10.
MODIFY (table) FROM @dref_struc->*.
+"--------------------- Dynamic DELETE statement ---------------------
+
DELETE FROM (table) WHERE (`CARRID = 'YZ'`).
+
+"--------------------- Dynamic UPDATE ... SET ... statement ---------------------
+
+"Inserting demo data into the database table to work with
+TYPES carr_tab TYPE TABLE OF zdemo_abap_carr WITH EMPTY KEY.
+INSERT ('ZDEMO_ABAP_CARR') FROM TABLE @( VALUE carr_tab( ( carrid = 'WX' carrname = 'WX Airways' )
+ ( carrid = 'XY' carrname = 'Air XY' )
+ ( carrid = 'YZ' carrname = 'YZ Airlines' ) ) ).
+
+"Note that erroneous dynamic specifications can lead to runtime errors
+"In the following example, the final inverted comma is missing in the dynamic
+"set clause.
+DATA(set_clause) = `CURRCODE = 'EUR`.
+DATA(where_cl) = `CARRID = 'WX' OR CARRID = 'XY' OR CARRID = 'YZ'`.
+
+TRY.
+ UPDATE ('ZDEMO_ABAP_CARR') SET (set_clause) WHERE (where_cl).
+ CATCH cx_sy_dynamic_osql_syntax INTO DATA(error).
+ DATA(error_text) = error->get_text( ).
+ENDTRY.
+
+"Correcting the dynamic specification
+"The example sets the value for a component for all entries.
+"The example additionally specifies a (dynamic) WHERE clause
+"to restrict the range of entries where the update is performed.
+"The database table is also specified dynamically.
+set_clause = `CURRCODE = 'EUR'`.
+
+UPDATE ('ZDEMO_ABAP_CARR') SET (set_clause) WHERE (where_cl).
+
+"--------------------- Dynamic UPDATE ... INDICATORS ... statement ---------------------
+
+"The statement changes values of specific fields without overwriting existing values of
+"other fields.
+
+"Notes on the example:
+"- A structured type is created with the WITH INDICATORS addition.
+"- An internal table from which to update a database table is created.
+"- The table includes the indicator structure comp_ind.
+"- The table is populated, and two components are flagged as
+" to be updated.
+"- Other fields remain unchanged. Note that key fields must be
+" included in ind_tab (indicator setting for key fields has
+" no effect).
+"- The UPDATE statement includes dynamically specified
+" indicator syntax. Additionally, the database table is specified
+" dynamically.
+
+"Structured type with WITH INDICATORS addition
+TYPES ind_wa TYPE zdemo_abap_carr WITH INDICATORS comp_ind TYPE abap_bool.
+
+DATA ind_tab TYPE TABLE OF ind_wa.
+
+"Filling internal table; only CURRCODE and URL should be updated
+ind_tab = VALUE #( ( carrid = 'WX'
+ carrname = 'WX Airways'
+ currcode = 'USD'
+ url = 'some_url_wx'
+ comp_ind-currcode = abap_true
+ comp_ind-url = abap_true )
+ ( carrid = 'XY'
+ carrname = 'Air XY'
+ currcode = 'USD'
+ url = 'some_url_xy'
+ comp_ind-currcode = abap_true
+ comp_ind-url = abap_true )
+ ( carrid = 'YZ'
+ carrname = 'YZ Airlines'
+ currcode = 'USD'
+ url = 'some_url_yz'
+ comp_ind-currcode = abap_true
+ comp_ind-url = abap_true ) ).
+
+DATA(dyn_ind) = `SET STRUCTURE comp_ind`.
+
+UPDATE ('ZDEMO_ABAP_CARR') FROM TABLE @ind_tab INDICATORS (dyn_ind).
+
+DELETE FROM ('ZDEMO_ABAP_CARR') WHERE (where_cl).
```
⬆️ back to top
diff --git a/22_Released_ABAP_Classes.md b/22_Released_ABAP_Classes.md
index bdc8f49..3ea6697 100644
--- a/22_Released_ABAP_Classes.md
+++ b/22_Released_ABAP_Classes.md
@@ -38,6 +38,7 @@
- [Units of Measurement](#units-of-measurement)
- [Programmatic ABAP Test Cockpit (ATC) Check](#programmatic-abap-test-cockpit-atc-check)
- [Handling Number Ranges](#handling-number-ranges)
+ - [Programmatically Releasing APIs](#programmatically-releasing-apis)
This ABAP cheat sheet contains a selection of [released](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreleased_api_glosry.htm) ABAP classes that are available in [ABAP for Cloud Development](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_for_cloud_dev_glosry.htm). It serves as a quick introduction, along with code snippets to explore the functionality in action.
@@ -515,6 +516,115 @@ DATA(random_num2) = cl_abap_random_int=>create( seed = cl_abap_random=>seed( )
max = 1000 )->get_next( ).
```
+
+
+The following example explores the generation of arbitraty numeric values.
+- It uses dynamic programming techniques. Find more information in the [Dynamic Programming](06_Dynamic_Programming.md) cheat sheet.
+- The class names are constructed dynamically. They all begin with `CL_ABAP_RANDOM_`.
+- An object is created dynamically based on the constructed class name.
+- This object is assigned the result of a dynamic method call. The error handling is included as the `min` and `max` parameters are not available for all methods.
+- The `get_next` method returns an appropriately typed data object, e.g. in case of `CL_ABAP_RANDOM_DECFLOAT34`, a data object of type `decfloat34` is returned. As a generic returning parameter is not possible, the example uses a data object of type `string`. So, the value returned is converted to type `string`. Note that are special conversion rules (e.g. the minus character for negative values are added at the end by default).
+- The resulting string values are added to an internal table for display purposes.
+- The example also includes static method calls.
+
+
+```abap
+CLASS zcl_some_class DEFINITION
+ PUBLIC
+ FINAL
+ CREATE PUBLIC .
+
+ PUBLIC SECTION.
+ INTERFACES if_oo_adt_classrun.
+ PROTECTED SECTION.
+ PRIVATE SECTION.
+ENDCLASS.
+
+CLASS zcl_some_class IMPLEMENTATION.
+ METHOD if_oo_adt_classrun~main.
+
+ TYPES: BEGIN OF random_values,
+ class TYPE string,
+ random_value TYPE string,
+ END OF random_values.
+ DATA random_value_table TYPE TABLE OF random_values WITH EMPTY KEY.
+
+ DATA(cl_name_parts) = VALUE string_table( ( `DECFLOAT16` )
+ ( `DECFLOAT34` )
+ ( `FLOAT` )
+ ( `INT` )
+ ( `INT8` )
+ ( `PACKED` )
+ ( `PACKED_DEC` ) ).
+
+ LOOP AT cl_name_parts INTO DATA(wa).
+
+ IF wa CS `PACKED_DEC`.
+ FIND PCRE `\d` IN wa.
+ IF sy-subrc <> 0.
+ DELETE cl_name_parts INDEX sy-tabix.
+ DO 14 TIMES.
+ APPEND wa && sy-index TO cl_name_parts.
+ ENDDO.
+ CONTINUE.
+ ENDIF.
+ ENDIF.
+
+ DATA(cl_name) = `CL_ABAP_RANDOM_` && wa.
+ DATA oref TYPE REF TO object.
+
+ TRY.
+ CALL METHOD (cl_name)=>create
+ EXPORTING
+ seed = cl_abap_random=>seed( )
+ min = 1
+ max = 1000
+ RECEIVING
+ prng = oref.
+ CATCH cx_sy_dyn_call_param_not_found.
+ CALL METHOD (cl_name)=>create
+ EXPORTING
+ seed = cl_abap_random=>seed( )
+ RECEIVING
+ prng = oref.
+ ENDTRY.
+
+ DATA value_conv2string TYPE string.
+
+ CALL METHOD oref->('GET_NEXT') RECEIVING value = value_conv2string.
+
+ APPEND VALUE #( class = cl_name random_value = value_conv2string ) TO random_value_table.
+ ENDLOOP.
+
+ out->write( random_value_table ).
+
+ DATA(a) = cl_abap_random_decfloat16=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(b) = cl_abap_random_decfloat34=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(c) = cl_abap_random_float=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(d) = cl_abap_random_int=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(e) = cl_abap_random_int8=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(f) = cl_abap_random_packed=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(g) = cl_abap_random_packed=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(h) = cl_abap_random_packed_dec1=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(i) = cl_abap_random_packed_dec2=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(j) = cl_abap_random_packed_dec3=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(k) = cl_abap_random_packed_dec4=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(l) = cl_abap_random_packed_dec5=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(m) = cl_abap_random_packed_dec6=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(n) = cl_abap_random_packed_dec7=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(o) = cl_abap_random_packed_dec8=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(p) = cl_abap_random_packed_dec9=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(q) = cl_abap_random_packed_dec10=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(r) = cl_abap_random_packed_dec11=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(s) = cl_abap_random_packed_dec12=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(t) = cl_abap_random_packed_dec13=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+ DATA(u) = cl_abap_random_packed_dec14=>create( seed = cl_abap_random=>seed( ) )->get_next( ).
+
+ ENDMETHOD.
+
+ENDCLASS.
+```
+
@@ -4326,3 +4436,54 @@ ENDTRY.
⬆️ back to top
+## Programmatically Releasing APIs
+
+
+
+| Class | Details/Code Snippet |
+
+
+ CL_ABAP_API_STATE |
+
+
+- You can use the class to release APIs programmatically. Note that you can also achieve this using ADT tools.
+- Find more information in the class documentation.
+- The code snippets uses various methods offered by the class and illustrates the following aspects: creating an instance of the API state handler for a specified API (a demo class is inserted), releasing the API for ABAP for Cloud Development (by also specifying a transport request), retrieving release information, and deleting the release state for the specified API again.
+
+
+
+```abap
+TRY.
+ DATA(api_state) = cl_abap_api_state=>create_instance( api_key = VALUE #( object_type = 'CLAS' object_name = 'ZCL_DEMO_TEST' ) ).
+
+ api_state->release( use_in_cloud_development = abap_true
+ use_in_key_user_apps = abap_false
+ request = 'SOME_TR_REQ' ).
+
+ DATA(rel_info) = api_state->get_release_info( ).
+
+ DATA(is_released) = api_state->is_released( use_in_cloud_development = abap_true
+ use_in_key_user_apps = abap_false ).
+
+ IF is_released = abap_true.
+ api_state->delete_release_state( request = 'SOME_TR_REQ' ).
+
+ rel_info = api_state->get_release_info( ).
+
+ is_released = api_state->is_released( use_in_cloud_development = abap_true
+ use_in_key_user_apps = abap_false ).
+
+ ENDIF.
+
+ CATCH cx_abap_api_state INTO DATA(error).
+ DATA(error_text) = error->get_text( ).
+ENDTRY.
+```
+
+ |
+
+
+
+
+
+⬆️ back to top