From d63d033810bf4ecc900f7dd8097948718523d75d Mon Sep 17 00:00:00 2001 From: Daniel Reger <16720986+danrega@users.noreply.github.com> Date: Fri, 30 Dec 2022 11:07:10 +0100 Subject: [PATCH] Add AMDP cheat sheet --- 12_AMDP.md | 437 ++++++++++++++++++++ README.md | 3 +- src/zcl_demo_abap_amdp.clas.abap | 368 +++++++++++++++++ src/zcl_demo_abap_amdp.clas.xml | 16 + src/zdemo_abap_table_function.ddls.asddls | 13 + src/zdemo_abap_table_function.ddls.baseinfo | 0 src/zdemo_abap_table_function.ddls.xml | 13 + 7 files changed, 849 insertions(+), 1 deletion(-) create mode 100644 12_AMDP.md create mode 100644 src/zcl_demo_abap_amdp.clas.abap create mode 100644 src/zcl_demo_abap_amdp.clas.xml create mode 100644 src/zdemo_abap_table_function.ddls.asddls create mode 100644 src/zdemo_abap_table_function.ddls.baseinfo create mode 100644 src/zdemo_abap_table_function.ddls.xml diff --git a/12_AMDP.md b/12_AMDP.md new file mode 100644 index 0000000..e57cf92 --- /dev/null +++ b/12_AMDP.md @@ -0,0 +1,437 @@ + + +# A Glimpse on AMDP + +- [A Glimpse on AMDP](#a-glimpse-on-amdp) + - [About AMDP](#about-amdp) + - [AMDP Classes](#amdp-classes) + - [AMDP Methods](#amdp-methods) + - [AMDP Procedures](#amdp-procedures) + - [AMDP Functions](#amdp-functions) + - [CDS Table Functions](#cds-table-functions) + - [Further Information](#further-information) + - [Executable Example](#executable-example) + + +This cheat sheet gathers basic information on [ABAP Managed Database +Procedures +(AMDP)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_managed_db_proc_glosry.htm "Glossary Entry"). +Find more details +[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp.htm) +in the ABAP Keyword Documentation. + +## About AMDP + +- AMDP are a class-based framework for managing and calling + + - [database + procedures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendatabase_procedure_glosry.htm "Glossary Entry") + (which is a synonym for [stored + procedures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstored_procedure_glosry.htm "Glossary Entry"), i. + e. the procedures are stored in the database - the [SAP HANA + database](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhana_database_glosry.htm "Glossary Entry") + in this case - and executed there) + - [database + functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendatabase_function_glosry.htm "Glossary Entry") + (which are [SQLScript + functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_script_function_glosry.htm "Glossary Entry") + in the SAP HANA database) + + in [AS ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenas_abap_glosry.htm "Glossary Entry"). + +- "ABAP managed" enters the picture in ABAP with the option of + implementing special [AMDP + procedures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_procedure_glosry.htm "Glossary Entry") + as database procedures and [AMDP + functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_function_glosry.htm "Glossary Entry") + as database functions. +- The implementations are programmed using a database-specific + language. Currently, AMDP only supports database procedures and + functions from the SAP HANA database. That is, + [SQLScript](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_script_glosry.htm "Glossary Entry") + is the programming language of choice. +- AMDP procedures and functions are part of a dedicated [AMDP + class](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_class_glosry.htm "Glossary Entry") + and declared and implemented as part of a method. The classes and + methods have certain characteristics as outlined further down. +- The AMDP framework replicates the procedure or function to the + database system, i. e. despite the fact that the programming happens + in an AMDP class (which is an [ABAP + Repository](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_repository_glosry.htm "Glossary Entry") + object as other global classes, too), the (SQLScript) code is + executed only on the (SAP HANA) database and not in AS ABAP, i. e. + method calls are sent to the database procedure or function. + +> **💡 Note**
+>- The use of AMDP is not recommended if the same task can be + achieved using [ABAP + SQL](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_glosry.htm "Glossary Entry"). +>- AMDP classes can only be edited with the [ABAP Development Tools + (ADT)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenadt_glosry.htm "Glossary Entry"). + +## AMDP Classes + +- As mentioned above, an [AMDP + class](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_class_glosry.htm "Glossary Entry") + is an [ABAP + Repository](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_repository_glosry.htm "Glossary Entry") + object like other global classes. +- However, an AMDP class includes the specification of the interface + `IF_AMDP_MARKER_HDB` for the SAP HANA + database (indicated by `HDB`), which is currently the + only possible database. +- An AMDP class can contain both (one or more) [AMDP + methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_method_glosry.htm "Glossary Entry") + and non-AMDP methods. + +Example for a [declaration part](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeclaration_part_glosry.htm "Glossary Entry") +of an AMDP class: + +```abap +CLASS cl_some_amdp_class DEFINITION +  PUBLIC +  FINAL +  CREATE PUBLIC. + +  PUBLIC SECTION. +    "Specifying the interface is mandatory +    INTERFACES if_amdp_marker_hdb. +... +ENDCLASS. +``` + + +## AMDP Methods + +- Can be created as [instance + methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_method_glosry.htm "Glossary Entry") + using METHODS or [static + methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatic_method_glosry.htm "Glossary Entry") + using CLASS-METHODS in any visibility section. +- Cannot be identified as AMDP methods in the declaration part of the + class since there are no specific additions to the methods. + Exceptions: AMDP function implementations that implement any [CDS table functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_table_function_glosry.htm "Glossary Entry") + as shown further down and method declarations using [`AMDP + OPTIONS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_amdp_options.htm) + that are not dealt with here. + +AMDP method declarations in any visibility section like non-AMDP +methods: + +```abap +... +PUBLIC SECTION. + +  METHODS some_amdp_meth +    ... "Here go the parameters + +PRIVATE SECTION. + +  CLASS-METHODS another_amdp_meth +    ... "Here go the parameters + +... +``` + + +## AMDP Procedures + +Despite the fact that AMDP methods cannot be identified as such from the +[declaration +part](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeclaration_part_glosry.htm "Glossary Entry") +(apart from the exceptions mentioned above), the declaration part of +[AMDP +procedures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_procedure_glosry.htm "Glossary Entry") +has special characteristics: + +- Parameters must be [passed by + value](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpass_by_value_glosry.htm "Glossary Entry") + using VALUE(...). [Passing by + reference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpass_by_reference_glosry.htm "Glossary Entry") + is not allowed. +- Parameter types ... + - must not be generic. + - can only be [elementary data + types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenelementary_data_type_glosry.htm "Glossary Entry") + and [table + types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_type_glosry.htm "Glossary Entry") + with a structured row type (and this type can only contain + elementary data types as components). +- Return values cannot be declared using RETURNING. +- Only input parameters can be flagged as optional parameters. + +Example for an AMDP procedure's declaration part: + +```abap +... +PUBLIC SECTION. + +  "Table type with a structured row type +  TYPES tab_type TYPE STANDARD TABLE OF dbtab WITH EMPTY KEY. + +  METHODS amdp_meth +    IMPORTING VALUE(num) TYPE i, +    EXPORTING VALUE(tab) TYPE tab_type. + +... +``` + +In contrast to the declaration part, the [implementation +part](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_procedure_method_glosry.htm "Glossary Entry") +of an AMDP method has multiple special additions for AMDP purposes +following METHOD and the method name: + +```abap +... +METHOD amdp_meth + BY DATABASE PROCEDURE +  FOR HDB   +  LANGUAGE SQLSCRIPT   +  OPTIONS READ-ONLY +  USING db_object. "see comments further down +                    +"Beginning of the SQLScript code (note that it is not ABAP code although it looks similar) + +  ... "Here goes SAPScript code +      "Note that an AMDP method implementation must not be empty. + +"End of the SQLScript code + +ENDMETHOD. +... + +"Comments: +" BY DATABASE PROCEDURE -> Flags the AMDP method as AMDP procedure +" FOR HDB   -> Definess the database system where the method is to be used; +"             currently, only HDB (SAP HANA database) is possible +" LANGUAGE SQLSCRIPT   -> Defines the programming language of the database system +" OPTIONS READ-ONLY -> Specifies database-specific options +" USING db_object. -> Optional addition; specifies database objects; +"                    can also be AMDP procedures and functions +``` + +Note: + +- In the [restricted ABAP language + version](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrestricted_version_glosry.htm "Glossary Entry") + scope, only reads are allowed. Hence, the addition `OPTIONS READ-ONLY` is mandatory. Furthermore, you must make sure + that the database objects that are specified after `USING` are accessible. +- Generally, in the [unrestricted ABAP language + version](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenunrestricted_version_glosry.htm "Glossary Entry") + scope, more syntax options are allowed for AMDP method declaration + and implementation parts. Check the ABAP Keyword Documentation for + more details as touched on further down. + + + +## AMDP Functions + +[Scalar](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_scalar_function_glosry.htm "Glossary Entry") +and [table +functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_function_glosry.htm "Glossary Entry") +can be managed as [AMDP +functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_function_glosry.htm "Glossary Entry"). +Such [AMDP table +functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_table_function_glosry.htm "Glossary Entry") +have, as the name implies, a tabular [return +value](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreturn_value_glosry.htm "Glossary Entry") +whereas AMDP scalar functions have a scalar or elementary return value +(more information +[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_function_methods.htm)). +Regarding AMDP table functions, there are two types available: + +- Functions that can only be accessed in other AMDP methods (i. e. + other AMDP functions or procedures) and cannot be called directly in + ABAP +- Functions that implement [CDS table + functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_table_function_glosry.htm "Glossary Entry") + that can be accessed in ABAP SQL + +Characteristics of method declaration parts of AMDP functions: + +- Similar to AMDP procedures, the methods can be declared as static or + instance methods in any visibility section. +- The method parameters must include a return value using + RETURNING and having a tabular data type. +- Additionally, the parameters can include elementary and tabular + input parameters. +- No class-based exceptions can be declared using RAISING. + +Example for an AMDP function's declaration part: + +```abap +... +PUBLIC SECTION. + +  "Table type with a structured row type +  TYPES tab_type TYPE STANDARD TABLE OF dbtab WITH EMPTY KEY. + +  METHODS amdp_func +    IMPORTING VALUE(num)       TYPE i, +              VALUE(some_elem) TYPE c LENGTH 3, +    RETURNING VALUE(tab)       TYPE tab_type. + +... +``` + +The implementation part of an AMDP function is similar to the one of +AMDP procedure as shown above. The difference is the use of `BY DATABASE FUNCTION` instead of `BY DATABASE PROCEDURE`: + +```abap +... +METHOD amdp_func +  BY DATABASE FUNCTION     +  FOR HDB +  LANGUAGE SQLSCRIPT +  OPTIONS READ-ONLY +  USING db_object. + +"Beginning of the SQLScript code (note that it is not ABAP code although it looks similar) + +  ... "Here goes SAPScript code; +      "AMDP table function to be called by other AMDP methods only + +"End of the SQLScript code + +ENDMETHOD. + +"Comment: +"  BY DATABASE FUNCTION    -> Flags the AMDP method as AMDP function +... +``` + +### CDS Table Functions + +- Each [CDS table + function](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_table_function_glosry.htm "Glossary Entry") + is linked with an AMDP function in which it is implemented using + SQLScript. +- Can be used as data sources of ABAP SQL read statements. +- Characteristics for method declaration and implementation parts + regarding AMDP functions for CDS table functions: + - Method can only be declared as a static method in the public visibility section of + an AMDP class using `CLASS-METHODS`. + - For the declaration, there is a special form with the addition + `FOR TABLE FUNCTION`. + - The [parameter + interface](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenparameter_interface_glosry.htm "Glossary Entry") + is not specified. Instead, the input parameters are determined + by the [input + parameters](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninput_parameter_glosry.htm "Glossary Entry") + of the CDS table function (i. e. the names and data types - + which are always elementary - specified there are used). As the + return value, a standard table with an empty key is generated + based on the structured row type including the components as + specified in the CDS table function. + +Example for an AMDP functions declaration implementing a CDS table +function: + +```abap +... +PUBLIC SECTION. + +  CLASS-METHODS: +    table_func FOR TABLE FUNCTION some_ddl_source. + +... +``` + +Notes on the [CDS +DDL](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_ddl_glosry.htm "Glossary Entry") +source of a CDS table function: + +- You have defined (and activated) a CDS DDL source, i. e. a [CDS + entity](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_entity_glosry.htm "Glossary Entry"), + with the notation `DEFINE TABLE FUNCTION` +- You can specify optional input parameters using `... WITH PARAMETERS parameter1, parameter2, ...` +- You must specify an element list using `... RETURNS { element1; element2; ...; } ...`. The elements determine the + components of the structured data type represented by a CDS table + function. +- You have specified the `IMPLEMENTED BY METHOD` addition + followed by a fully qualified method name in the form of + `amdp_class=>amdp_method` using the names of the AMDP + class and method. +- More information + [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_table_functions.htm). + +The CDS DDL source might look like this: + +```abap +//Here go annotations. +define table function some_ddl_source +  returns +  { +    client : abap.clnt; +    field1 : abap.char(5); +    field2 : abap.char(5); +  } +  implemented by method amdp_class=>amdp_method; +``` + +You can then use the CDS table function as source for a +`SELECT` statement, for example: `SELECT * FROM some_ddl_source INTO ...`. + + + +## Further Information + +Notes on using AMDP in environments with restricted language version (in +contrast unrestricted language version): + +AMDP methods ... + +- must include the addition OPTIONS READ-ONLY in the + declaration part. +- must be implemented in SQLScript in any case. +- cannot use the additions [`USING SCHEMA` (F1 for docu standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapmethod_by_db_proc.htm#!ABAP_ADDITION_5@5@) + and [`SUPPRESS SYNTAX ERRORS` (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapmethod_by_db_proc.htm#!ABAP_ADDITION_3@3@) + in the method implementation part +- cannot use [AMDP + macros](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_macros.htm) + and call hints. +- can only use your own entities and entities that are released for + the restricted language version after USING. +- cannot use + [`CONNECTION` (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenamdp_db_connections.htm) + parameters. +- cannot raise the + `CX_AMDP_CONNECTION_ERROR` exception since + the `CONNECTION` parameter is not allowed. + +As mentioned above and hinted in the bullet points above, AMDP has more +options regarding the unrestricted language version. Check the subtopics +[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp.htm). +A fundamental question in on-premise ABAP systems with an unrestricted +language scope can be whether AMDP is supported at all. The constant +`CALL_AMDP_METHOD` of the class +`CL_ABAP_DBFEATURES` can be used to query +whether the current database supports AMDP methods. See the following +snippet: + +```abap +IF NOT cl_abap_dbfeatures=>use_features( +   EXPORTING requested_features = +        VALUE #( ( cl_abap_dbfeatures=>call_amdp_method ) ) ). + +  "Result: Current database system does not support AMDP procedures +  RETURN. +ENDIF. +``` + +This check is not required (and possible) for the SAP BTP ABAP Environment since those +environments are SAP HANA-only anyway and database connections are not +possible. Furthermore, another topic that should be noted is that AMDP +does not support [implicit client +handling](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_client_handling.htm). +Therefore, the parameter interface of AMDP methods usually contains an +input parameter for the client ID. See more information +[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenamdp_client_handling.htm) (or [here for the F1 docu for standard ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenamdp_client_handling.htm)). +The client handling is not dealt with in this cheat sheet and not +relevant in the executable example. + + +## Executable Example +[zcl_demo_abap_amdp](./src/zcl_demo_abap_amdp.clas.abap) + +Note the steps outlined [here](README.md#-getting-started-with-the-examples) about how to import and run the code. \ No newline at end of file diff --git a/README.md b/README.md index 27ac9bf..d92767d 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,8 @@ ABAP cheat sheets[^1] ... |[ABAP for RAP: Entity Manipulation Language (ABAP EML)](08_EML_ABAP_for_RAP.md)| Setting EML in the context of RAP, standard (create, read, update, delete) and non-standard operations (actions) | | |[Excursion Down to Bits and Bytes](09_Bits_and_Bytes.md)|Touches on the technical background of data types and data objects|-| |[ABAP SQL: Working with Hierarchies](10_ABAP_SQL_Hierarchies.md)|Summarizes the functions ABAP SQL offers together with ABAP CDS for working with hierarchical data that is stored in database tables|-| -|[ABAP SQL: Grouping Internal Tables](11_ABAP_SQL_Grouping_Internal_Tables.md)|Touches on the `GROUP BY` clause in ABAP SQL|[zcl_demo_abap_sql_group_by](./src/zcl_demo_abap_sql_group_by.clas.abap) +|[ABAP SQL: Grouping Internal Tables](11_ABAP_SQL_Grouping_Internal_Tables.md)|Touches on the `GROUP BY` clause in ABAP SQL|[zcl_demo_abap_sql_group_by](./src/zcl_demo_abap_sql_group_by.clas.abap)| +|[A Glimpse on AMDP](12_AMDP.md)|Touches ABAP Managed Database Procedures (AMDP): AMDP Procedures and AMDP Functions (including CDS Table Functions)|[zcl_demo_abap_amdp](./src/zcl_demo_abap_amdp.clas.abap) ## 🎬 Getting Started with the Examples diff --git a/src/zcl_demo_abap_amdp.clas.abap b/src/zcl_demo_abap_amdp.clas.abap new file mode 100644 index 0000000..cf6f013 --- /dev/null +++ b/src/zcl_demo_abap_amdp.clas.abap @@ -0,0 +1,368 @@ +*********************************************************************** +* +* ABAP cheat sheet: AMDP +* +* -------------------------- PURPOSE ---------------------------------- +* - Example to demonstrate AMDP procedures and functions. It includes +* a CDS table function. +* - NOTE: +* - The example covers basics regarding AMDP method declarations +* and implementations. +* - The purpose is to give you a rough idea about AMDP. Therefore, +* the SQLScript code used in the method implementations is +* fairly simple. AMDP is not needed in simple cases like these. +* - The example is primarily intended for the SAP BTP ABAP +* environment. For example, in SAP BTP ABAP environment only +* read-only operations are possible. In general, there are more +* syntax options available in the unrestricted ABAP language scope +* in on-premise ABAP systems. Check the ABAP Keyword Documentation +* for more details and examples. +* +* ----------------------- GETTING STARTED ----------------------------- +* - Open the class with the ABAP Development Tools (ADT). +* - Choose F9 to run the class. +* - Check the console output. +* - To understand the context and the ABAP syntax used, check the notes +* included in the class as comments or refer to the respective topic +* in the ABAP Keyword Documentation. +* - Due to the amount of output in the console, the examples include +* numbers (e. g. 1) ..., 2) ..., 3) ...) for the individual example +* sections. Plus, the variable name is displayed in most cases. Hence, +* to easier and faster find the relevant output in the console, just +* search in the console for the number/variable name (STRG+F in the +* console) or use the debugger. +* +* ----------------------------- NOTE ----------------------------------- +* The code presented in this class is only meant for supporting the ABAP +* cheat sheets. It is not intended for direct use in a +* production system environment. The code examples in the ABAP cheat +* sheets are primarily intended to provide a better explanation and +* visualization of the syntax and semantics of ABAP statements and not to +* solve concrete programming tasks. For production application programs, +* a dedicated solution should therefore always be worked out for each +* individual case. There is no guarantee for either the correctness or +* the completeness of the code. In addition, there is no legal +* responsibility or liability for possible errors or their consequences +* which occur through the use of the example code. +* +*********************************************************************** +"!

ABAP cheat sheet: AMDP

+"! Example to demonstrate AMDP procedures and functions.
Choose F9 in ADT to run the class. +CLASS zcl_demo_abap_amdp DEFINITION + PUBLIC + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES: + if_oo_adt_classrun, "Interface for displaying output + if_amdp_marker_hdb. "This interface specification is mandatory for an AMDP class + + "Various internal table type specifications for the parameters of AMDP methods + "Note: Only table and elementary data types are possible for the parameters. + TYPES carr_tab TYPE STANDARD TABLE OF zdemo_abap_carr WITH EMPTY KEY. + + TYPES fli_tab TYPE STANDARD TABLE OF zdemo_abap_fli WITH EMPTY KEY. + + TYPES: + "Structured data type as basis for the table type below + BEGIN OF carr_fli_struc, + carrname TYPE zdemo_abap_carr-carrname, + connid TYPE zdemo_abap_flsch-connid, + cityfrom TYPE zdemo_abap_flsch-cityfrom, + cityto TYPE zdemo_abap_flsch-cityto, + END OF carr_fli_struc, + + "Internal table type + carr_fli_tab TYPE STANDARD TABLE OF carr_fli_struc WITH EMPTY KEY, + + "Structured data type as basis for the table type below + BEGIN OF fli_struc, + carrid TYPE zdemo_abap_flsch-carrid, + connid TYPE zdemo_abap_flsch-connid, + cityfrom TYPE zdemo_abap_flsch-cityfrom, + cityto TYPE zdemo_abap_flsch-cityto, + fltime TYPE zdemo_abap_flsch-fltime, + END OF fli_struc, + + "Internal table type + flsch_tab TYPE STANDARD TABLE OF zdemo_abap_flsch WITH EMPTY KEY. + + "Various instance method declarations + "The selection for instance and static methods is irrelevant for the example. + "It is just meant to visualize that AMDP methods can be declared as either of them. + + "AMDP procedure + "It's a simple AMDP procedure having only an output parameter with tabular type. + "Note the parameter declaration that includes the mandatory passing by value. + "This is true for all of the AMDP method declarations. + METHODS select_carriers + EXPORTING VALUE(carr_tab) TYPE carr_tab. + + "AMDP procedure to call an AMDP table function + "As can be seen in the implementation part, this example method calls the + "AMDP table function get_carr_fli. AMDP table functions can only be called + "by other AMDP methods. + METHODS select_get_carr_fli + IMPORTING VALUE(carrid) TYPE zdemo_abap_fli-carrid + EXPORTING VALUE(carr_fli_tab) TYPE carr_fli_tab. + + "Various static method declarations + + "The purpose of the implementation of the static constructor in this example is to + "fill a demo database table to have data to work with in the example. + CLASS-METHODS class_constructor. + + "AMDP procedure + "This method demonstrates the calling of an AMDP procedure from SQLScript. + "In this example, the selection of data is 'delegated' to another AMDP method get_flights_amdp + "in the same AMDP class. The method declaration includes the addition RAISING with an + "exception class for AMDP-specific exceptions. + CLASS-METHODS get_flights + IMPORTING VALUE(carrid) TYPE zdemo_abap_fli-carrid + EXPORTING VALUE(fli_tab) TYPE fli_tab + RAISING cx_amdp_execution_error. + + "AMDP Table Function for CDS Table Function + "Note that, in this case, a static method declaration is required along with the special + "syntax FOR TABLE FUNCTION. Plus, there are no parameters specified and the declaration + "is made in the PUBLIC visibility section. + CLASS-METHODS flight_analysis FOR TABLE FUNCTION zdemo_abap_table_function. + + PRIVATE SECTION. + + "AMDP procedure + "This method demonstrates the calling of an AMDP procedure from SQLScript as mentioned above. + CLASS-METHODS get_flights_amdp + IMPORTING VALUE(carrid) TYPE zdemo_abap_fli-carrid + EXPORTING VALUE(fli_tab) TYPE fli_tab + RAISING cx_amdp_execution_error. + + "AMDP table function + "AMDP table functions can only be called by other AMDP methods. In this example, + "the AMDP procedure select_get_carr_fli calls this AMDP table function. + METHODS get_carr_fli + IMPORTING VALUE(carrid) TYPE zdemo_abap_flsch-carrid + RETURNING VALUE(carr_fli_tab) TYPE carr_fli_tab. + +ENDCLASS. + +CLASS zcl_demo_abap_amdp IMPLEMENTATION. + + METHOD class_constructor. + "Filling demo database tables. + zcl_demo_abap_flight_tables=>fill_dbtabs( ). + ENDMETHOD. + + + METHOD if_oo_adt_classrun~main. + + DATA(output) = NEW zcl_demo_abap_display( out ). + + output->display( `Demo: ABAP AMDP` ). + + output->display( `1. AMDP procedure` ). + + "Declaring an internal table to store the data that are + "returned by the following method. + "You could also choose to create the internal table inline + "within the method call, + "i. e. like ... IMPORTING carr_tab = DATA(tab) ). + DATA amdp_proc_res TYPE zcl_demo_abap_amdp=>carr_tab. + + "Since the method is declared as an instance method, an instance + "has to be created. Here, the instance constructor NEW is used + "in a standalone method call that includes a chained method call. + NEW zcl_demo_abap_amdp( )->select_carriers( + IMPORTING carr_tab = amdp_proc_res ). + + output->display( input = amdp_proc_res name = `amdp_proc_res` ). + +********************************************************************** + + output->next_section( `2. Calling an AMDP Procedure from SQLScript` ). + + "As can be seen in the method implementation part, this AMDP procedure + "includes an AMDP procedure call from SQLScript. + "In this example, the AMDP procedure get_flights_amdp is called by + "get_flights which is meant to select data from a database table. + "The returned result is displayed. + TRY. + + zcl_demo_abap_amdp=>get_flights( EXPORTING carrid = 'LH' + IMPORTING fli_tab = DATA(call_amdp_res) ). + + CATCH cx_amdp_execution_error INTO DATA(error1). + + out->write( error1->get_text( ) ). + + ENDTRY. + + output->display( input = call_amdp_res name = `call_amdp_res` ). + + +********************************************************************** + + output->next_section( `3. AMDP Table Function for AMDP Method` ). + + "The AMDP procedure select_get_carr_fli calls the AMDP table function + "get_carr_fli in the implementation part. AMDP table functions can + "only be called by other AMDP methods. + TRY. + + NEW zcl_demo_abap_amdp( )->select_get_carr_fli( + EXPORTING carrid = 'LH' + IMPORTING carr_fli_tab = DATA(amdp_tab_func) ). + + CATCH cx_amdp_execution_error INTO DATA(error2). + + out->write( error2->get_text( ) ). + + ENDTRY. + + output->display( input = amdp_tab_func name = `amdp_tab_func` ). + + "Note: When commented in, the following code results in a runtime + "error since you cannot call an AMDP function in ABAP directly. +* NEW ZCL_demo_ABAP_AMDP( )->get_carr_fli( +* EXPORTING carrid = 'LH' ). + +********************************************************************** + + output->next_section( `4. AMDP Table Function for CDS Table Function` ). + + + "The example demonstrates that a CDS table function can be used as a + "data source of ABAP SQL read statements. + "You might want to navigate to the DDL source after FROM by holding + "CTRL and clicking the DDL source name in ADT to see the details. + "Or, just check out the F2 help. + "In this example, the CDS table function is implemented in a way to + "return accumulated data. + "In the method implementation for flight_analysis, first two kinds of + "data sets from two database tables are gathered. These data sets are + "joined using an inner join. There, some expressions are included + "(strings are aggregated, average values are determined). + + SELECT * FROM zdemo_abap_table_function + INTO TABLE @DATA(cds_tab_func). + + output->display( input = cds_tab_func name = `cds_tab_func` ). + + ENDMETHOD. + +********************************************************************** + + METHOD select_carriers + BY DATABASE PROCEDURE + FOR HDB + LANGUAGE SQLSCRIPT + OPTIONS READ-ONLY + USING zdemo_abap_carr. +* Simple data selection + carr_tab = SELECT * + FROM "ZDEMO_ABAP_CARR" + ORDER BY carrid; + ENDMETHOD. + + METHOD get_flights + BY DATABASE PROCEDURE + FOR HDB + LANGUAGE SQLSCRIPT + OPTIONS READ-ONLY + USING zcl_demo_abap_amdp=>get_flights_amdp. +* Another AMDP procedure is called from SQLScript + CALL "ZCL_DEMO_ABAP_AMDP=>GET_FLIGHTS_AMDP"( + CARRID => :CARRID, + FLI_TAB => :FLI_TAB ); + ENDMETHOD. + + METHOD get_flights_amdp + BY DATABASE PROCEDURE + FOR HDB + LANGUAGE SQLSCRIPT + OPTIONS READ-ONLY + USING zdemo_abap_fli. +* Simple data selection + fli_tab = SELECT * + FROM "ZDEMO_ABAP_FLI" + WHERE carrid = :carrid + ORDER BY carrid; + ENDMETHOD. + + METHOD flight_analysis + BY DATABASE FUNCTION + FOR HDB + LANGUAGE SQLSCRIPT + OPTIONS READ-ONLY + USING zdemo_abap_flsch "Two database tables are used and must both be specified here. + zdemo_abap_carr. +* Reading data from two database tables + itab_cities = + SELECT DISTINCT + zdemo_abap_flsch.mandt as client, + zdemo_abap_flsch.carrid as carrier_id, + zdemo_abap_flsch.airpfrom as airport_from, + zdemo_abap_flsch.airpto as airport_to, + zdemo_abap_flsch.fltime as flight_time, + zdemo_abap_flsch.distance as flight_distance, + zdemo_abap_flsch.distid as unit + FROM zdemo_abap_flsch; + + itab_carrier_names = + SELECT DISTINCT + zdemo_abap_carr.mandt as client, + zdemo_abap_carr.carrid as carrier_id, + zdemo_abap_carr.carrname as carrier_name + FROM zdemo_abap_carr; + +* Returning joined data using an inner join + RETURN + SELECT fl.client, fl.carrier_id, ca.carrier_name, +* Departure and destination airports are concatenated; then all results are joined by string aggregation + STRING_AGG( CONCAT(CONCAT(fl.airport_from,' -> '),fl.airport_to), ', ' ORDER BY fl.airport_from) AS connections, +* Retrieving the average flight time of all flights by carrier + AVG( fl.flight_time ) as avg_flight_time, +* Retrieving the average flight distance of all flights by carrier; miles are converted to kilometers + AVG( CASE 'MI' + WHEN fl.unit THEN fl.flight_distance * 1.609 + ELSE fl.flight_distance + END ) AS avg_distance + FROM :itab_cities AS fl + INNER JOIN :itab_carrier_names AS ca + ON ca.client = fl.client + AND ca.carrier_id = fl.carrier_id + WHERE fl.client = ca.client AND fl.carrier_id = ca.carrier_id + GROUP BY fl.client, ca.carrier_name, fl.carrier_id; + ENDMETHOD. + + METHOD get_carr_fli + BY DATABASE FUNCTION + FOR HDB + LANGUAGE SQLSCRIPT + OPTIONS READ-ONLY + USING zdemo_abap_carr zdemo_abap_flsch. +* AMDP table function to be called by other AMDP methods only. +* In the example, joined data from two database table are returned. + RETURN + SELECT ca.carrname, fl.connid, fl.cityfrom, fl.cityto + FROM zdemo_abap_carr as ca + INNER JOIN zdemo_abap_flsch as fl + ON ca.carrid = fl.carrid + WHERE fl.carrid = :carrid + ORDER BY ca.mandt, ca.carrname, fl.connid; + ENDMETHOD. + + METHOD select_get_carr_fli + BY DATABASE PROCEDURE + FOR HDB + LANGUAGE SQLSCRIPT + OPTIONS READ-ONLY + USING zcl_demo_abap_amdp=>get_carr_fli. +* AMDP procedure to call an AMDP table function as specified after USING + carr_fli_tab = SELECT * + FROM "ZCL_DEMO_ABAP_AMDP=>GET_CARR_FLI"( + carrid => :carrid ); + ENDMETHOD. + +ENDCLASS. diff --git a/src/zcl_demo_abap_amdp.clas.xml b/src/zcl_demo_abap_amdp.clas.xml new file mode 100644 index 0000000..596e556 --- /dev/null +++ b/src/zcl_demo_abap_amdp.clas.xml @@ -0,0 +1,16 @@ + + + + + + ZCL_DEMO_ABAP_AMDP + E + ABAP cheat sheet: AMDP + 1 + X + X + 5 + + + + diff --git a/src/zdemo_abap_table_function.ddls.asddls b/src/zdemo_abap_table_function.ddls.asddls new file mode 100644 index 0000000..a5c88b7 --- /dev/null +++ b/src/zdemo_abap_table_function.ddls.asddls @@ -0,0 +1,13 @@ +@AccessControl.authorizationCheck: #NOT_REQUIRED +define table function ZDEMO_ABAP_TABLE_FUNCTION + returns + { + client : abap.clnt; + carrier_id : abap.char(3); + carrier_name : abap.char(20); + connections : abap.string; + avg_flight_time : abap.dec( 10, 2 ); + avg_distance : abap.dec( 10, 2 ); + } + implemented by method + zcl_demo_abap_amdp=>flight_analysis; diff --git a/src/zdemo_abap_table_function.ddls.baseinfo b/src/zdemo_abap_table_function.ddls.baseinfo new file mode 100644 index 0000000..e69de29 diff --git a/src/zdemo_abap_table_function.ddls.xml b/src/zdemo_abap_table_function.ddls.xml new file mode 100644 index 0000000..86574ef --- /dev/null +++ b/src/zdemo_abap_table_function.ddls.xml @@ -0,0 +1,13 @@ + + + + + + ZDEMO_ABAP_TABLE_FUNCTION + E + ABAP Demo: Table function + F + + + +