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