Add AMDP cheat sheet

This commit is contained in:
Daniel Reger
2022-12-30 11:07:10 +01:00
parent 9d95ea38e8
commit d63d033810
7 changed files with 849 additions and 1 deletions

437
12_AMDP.md Normal file
View File

@@ -0,0 +1,437 @@
<a name="top"></a>
# 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**<br>
>- 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 <code>METHODS</code> 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 <code>CLASS-METHODS</code> 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 <code>VALUE(...)</code>. [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 <code>RETURNING</code>.
- 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 <code>METHOD</code> 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
<code>RETURNING</code> and having a tabular data type.
- Additionally, the parameters can include elementary and tabular
input parameters.
- No class-based exceptions can be declared using <code>RAISING</code>.
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 <code>OPTIONS READ-ONLY</code> 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 <code>USING</code>.
- 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.

View File

@@ -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) | <ul><li>[Demo RAP scenario with a managed RAP BO, external numbering (zcl_demo_abap_rap_ext_num_m)](./src/zcl_demo_abap_rap_ext_num_m.clas.abap)</li><br><li>[Demo RAP scenario with an unmanaged RAP BO, external numbering (zcl_demo_abap_rap_ext_num_u)](./src/zcl_demo_abap_rap_ext_num_u.clas.abap)</li><br><li>[Demo RAP scenario ("RAP calculator") with a managed, draft-enabled RAP BO, late numbering (zcl_demo_abap_rap_draft_ln_m)](./src/zcl_demo_abap_rap_draft_ln_m.clas.abap) <br>Note that this example can also be checked out using the preview version of an SAP Fiori UI. Check the comments in the class for the steps.</li></ul> |
|[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

View File

@@ -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.
*
***********************************************************************
"! <p class="shorttext synchronized">ABAP cheat sheet: AMDP</p>
"! Example to demonstrate AMDP procedures and functions.<br>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.

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>ZCL_DEMO_ABAP_AMDP</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>ABAP cheat sheet: AMDP</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>5</UNICODE>
</VSEOCLASS>
</asx:values>
</asx:abap>
</abapGit>

View File

@@ -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;

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_DDLS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<DDLS>
<DDLNAME>ZDEMO_ABAP_TABLE_FUNCTION</DDLNAME>
<DDLANGUAGE>E</DDLANGUAGE>
<DDTEXT>ABAP Demo: Table function</DDTEXT>
<SOURCE_TYPE>F</SOURCE_TYPE>
</DDLS>
</asx:values>
</asx:abap>
</abapGit>