This commit is contained in:
danrega
2024-12-19 12:24:38 +01:00
parent 78e8e9ca89
commit c60e30931a
3 changed files with 314 additions and 13 deletions

View File

@@ -437,15 +437,16 @@ MODIFY ENTITIES OF zdemo_abap_rap_ro_m
<tr>
<td>
Assigning incompatible structures
Assigning incompatible structures and internal tables
</td>
<td>
- 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.
-
<br>
@@ -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
```
</td>
@@ -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
```
</td>
@@ -521,6 +559,11 @@ DATA(strtab) = VALUE string_table( LET mark = '!' IN
( |abc{ mark }| )
( |def{ mark }| )
( |ghi{ mark }| ) ).
*Result:
*abc!
*def!
*ghi!
```
</td>
@@ -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.

View File

@@ -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).
```
<p align="right"><a href="#top">⬆️ back to top</a></p>

View File

@@ -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( ).
```
<br>
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.
```
</td>
</tr>
</table>
@@ -4326,3 +4436,54 @@ ENDTRY.
<p align="right"><a href="#top">⬆️ back to top</a></p>
## Programmatically Releasing APIs
<table>
<tr>
<td> Class </td> <td> Details/Code Snippet </td>
</tr>
<tr>
<td> <code>CL_ABAP_API_STATE</code> </td>
<td>
- 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.
<br>
```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.
```
</td>
</tr>
</table>
<p align="right"><a href="#top">⬆️ back to top</a></p>