0% found this document useful (0 votes)
71 views114 pages

Abap On Hana

The document outlines the structure and implementation of ABAP behavior definitions (BDEF) for the ABAP RAP (Rapid Application Programming) model, detailing class definitions, methods for CRUD operations, and data handling for entities. It includes examples of data types, response structures, and EML (Entity Manipulation Language) statements for modifying and reading entities in a transactional context. Additionally, it covers the use of local mode for executing operations and managing entity states.

Uploaded by

Sârouche Boù
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
71 views114 pages

Abap On Hana

The document outlines the structure and implementation of ABAP behavior definitions (BDEF) for the ABAP RAP (Rapid Application Programming) model, detailing class definitions, methods for CRUD operations, and data handling for entities. It includes examples of data types, response structures, and EML (Entity Manipulation Language) statements for modifying and reading entities in a transactional context. Additionally, it covers the use of local mode for executing operations and managing entity states.

Uploaded by

Sârouche Boù
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 114

ABAP ON HANA

define root
view entity
define
behavior for

FOR BEHAVIOR OF bdef


bdef

CLASS zbp_demo_abap_rap_draft_m DEFINITION PUBLIC ABSTRACT FINAL FOR BEHAVIOR O


ENDCLASS.

CLASS zbp_demo_abap_rap_draft_m IMPLEMENTATION.


ENDCLASS.

CL_ABAP_BEHAVIOR_HANDLER
ABSTRACT FINAL
CLASS lhc_root DEFINITION INHERITING FROM cl_abap_behavior_handler.
...
ENDCLASS.

... FOR ... FOR ...

RESULT
FOR MODIFY

METHODS, FOR

"Create
METHODS create FOR MODIFY
IMPORTING entities FOR CREATE bdef.

"Read: Specifying a read result is mandatory.


METHODS read FOR READ
IMPORTING keys FOR READ bdef RESULT result.

"Action: action name is preceded by the BDEF name and a tilde after FOR ACTION
METHODS some_action FOR MODIFY
IMPORTING keys FOR ACTION bdef~some_action.

FOR MODIFY FOR


CREATE FOR READ RESULT

IMPORTING

CHANGING
mapped failed reported

mapped
mapped
%cid
failed

reported

reported

ABSTRACT FINAL

adjust_numbers

CL_ABAP_BEHAVIOR_SAVER

COMMIT
ENTITIES
COMMIT ENTITIES
CLASS lsc_bdef DEFINITION INHERITING FROM cl_abap_behavior_saver.
PROTECTED SECTION.

"For final calculations and data modifications involving all


"BOs in the current RAP transaction
METHODS finalize REDEFINITION.

"Checks the consistency of the transactional buffer before


"the save method saves data to the database
METHODS check_before_save REDEFINITION.

"Preliminary IDs are mapped to final keys. Only for late numbering.
METHODS adjust_numbers REDEFINITION.

"Saves the current state of the transactional buffer to the database


METHODS save REDEFINITION.

"Clear the transactional buffer


METHODS cleanup REDEFINITION.
METHODS cleanup_finalize REDEFINITION.

ENDCLASS.

TYPE TABLE FOR TYPE STRUCTURE FOR

FOR

TYPE STRUCTURE FOR


mapped failed reported
TYPE RESPONSE FOR

TYPE TABLE FOR

"Data objects with input derived types (entity = name of a root entity)

"For an EML create operation

DATA create_tab TYPE TABLE FOR CREATE entity.

"For an update operation

DATA update_tab TYPE TABLE FOR UPDATE entity.

"Type for create-by-association operations specifying the name of the entity


"and the association

DATA cba_tab TYPE TABLE FOR CREATE entity\_child.

"For an action execution; the name of the action is preceded by a tilde

DATA action_imp TYPE TABLE FOR ACTION IMPORT entity~action1.

"Data objects with output derived types

"For a read operation

DATA read_tab TYPE TABLE FOR READ RESULT entity.

"For an action defined with a result

DATA action_res TYPE TABLE FOR ACTION RESULT entity~action2.

"Examples for structures and types

DATA create_wa TYPE STRUCTURE FOR CREATE entity.

"For permission retrieval

DATA perm_req TYPE STRUCTURE FOR PERMISSIONS REQUEST entity.

"For retrieving global features

DATA feat_req TYPE STRUCTURE FOR GLOBAL FEATURES RESULT entity.

"Type declaration using a BDEF derived type

TYPES der_typ TYPE TABLE FOR DELETE entity.

"Response parameters
DATA map TYPE RESPONSE FOR MAPPED entity.
DATA fail TYPE RESPONSE FOR FAILED entity.
DATA rep TYPE RESPONSE FOR REPORTED entity.

TYPE TABLE FOR


CREATE

%
%

%data
%key

%data derived type

%
%pid

%is_draft

%cid

%cid_ref %cid
%cid
AUTO FILL
CID %cid
%cid
%key %tky

%tky
%key %tky %key %is_draft
%tky

%control
%control
ABP_BEHV_FLAG mk
IF_ABAP_BEHV x length 1

%control if_abap_behv=>mk-off

CREATE CREATE BY UPDATE DELETE


EXECUTE
MODIFY
MODIFY

...
create;
update;
delete;
action some_act;
...

"Declaration of data objects using BDEF derived types

DATA: cr_tab TYPE TABLE FOR CREATE root_ent, "input derived type
mapped_resp TYPE RESPONSE FOR MAPPED root_ent, "response parameters
failed_resp TYPE RESPONSE FOR FAILED root_ent,
reported_resp TYPE RESPONSE FOR REPORTED root_ent.

"Input derived type for the EML statement is filled using the VALUE operator
"Assumption: key_field is the key field having type i,
"field1 and field2 are data fields with character-like data type.
"Specify %cid even if not used or of interest; it must be unique within a reque

cr_tab = VALUE #(
( %cid = 'cid1' key_field = 1
field1 = 'A' field2 = 'B' )
( %cid = 'cid2'
"Just to demo %data/%key. You can specify fields with or without
"the derived type components
%data = VALUE #( %key-key_field = 2
field1 = 'C'
field2 = 'D' ) ) ).

"EML statement, short form


"root_ent must be the full name of the root entity, it is basically the name of

MODIFY ENTITY root_ent


CREATE "determines the kind of operation
FIELDS ( key_field field1 field2 ) WITH cr_tab "Fields to be respected for
"input derived type and the
"derived type itself
MAPPED mapped_resp "mapping information
FAILED failed_resp "information on failures with instances
REPORTED reported_resp. "messages

FIELDS ( ... ) WITH

WITH
FIELDS %control
if_abap_behv=>mk-on
%control if_abap_behv=>mk-off field2
field2

key_field
failed_resp
reported_resp

%cid

MODIFY

MODIFY ENTITIES OF root_ent "full name of root entity


ENTITY root "root or child entity (alias name if available
CREATE FROM "FROM as further field selection variant
VALUE #( ( %cid = 'cid' "Input derived type created inline
key_field = 3
field1 = 'E'
field2 = 'F'
%control = VALUE #( "Must be filled when using FROM
key_field = if_abap_behv=>mk-on
field1 = if_abap_behv=>mk-on
field2 = if_abap_behv=>mk-on ) ) )
MAPPED DATA(m) "Target variables declared inline
FAILED DATA(f)
REPORTED DATA(r).

ENTITY

FIELDS ( ... ) WITH


FROM FROM
%control

DATA FINAL

%cid %cid_ref %cid

FIELDS ( ... ) WITH

%cid_ref %cid_ref

DELETE
FROM TYPE
TABLE FOR DELETE %cid_ref

MODIFY ENTITIES OF root_ent


ENTITY root
CREATE FIELDS ( key_field field1 field2 ) WITH
VALUE #( ( %cid = 'cid4' key_field = 4
field1 = 'G' field2 = 'H' )
( %cid = 'cid5' key_field = 5
field1 = 'I' field2 = 'J' ) )

UPDATE FIELDS ( field2 ) WITH


VALUE #( ( %cid_ref = 'cid4' field2 = 'Z' ) )

DELETE FROM
VALUE #( ( %cid_ref = 'cid5' ) "Instance referenced via %cid_ref
( key_field = 9 ) ) "Instance referenced via the key
...

MODIFY ENTITIES OF root_ent


ENTITY root
EXECUTE some_action
FROM action_tab
RESULT DATA(action_result) "Assumption: The action is defined with a result p
...

composition [1..*] of root_ent as _child key_field key_field_child


%target

MODIFY ENTITIES OF root_ent


ENTITY root_ent
CREATE FIELDS ( key_field field1 field2 ) WITH
VALUE #( ( %cid = 'cid6' key_field = 6
field1 = 'I' field2 = 'J' ) )
CREATE BY \_child
FIELDS ( key_field_child field1_child field2_child ) WITH
VALUE #( ( %cid_ref = 'cid6'
%target = VALUE #( ( %cid = 'cid_child_1'
key_field_child = 1
field1_child = 'aa'
field2_child = 'bb' )
( %cid = 'cid_child_2'
key_field_child = 2
field1_child = 'cc'
field2_child = 'dd' ) ) ) )
...

RESULT
READ
READ FIELDS ( ... )
WITH FROM
ALL FIELDS WITH

READ ENTITIES OF root_ent


ENTITY root_ent
ALL FIELDS WITH
VALUE #( ( key_field = 1 ) "Derived type TYPE TABLE FOR READ IMPORT only in
( key_field = 2 ) )
RESULT DATA(result)
FAILED DATA(f)
REPORTED DATA(r).

LINK

"Read-by association operation: parent to child


READ ENTITIES OF root_ent
ENTITY root_ent
BY \_child
ALL FIELDS WITH VALUE #( ( key_field = 1 ) )
RESULT DATA(rba_res1)
LINK DATA(links1).
...

"Read-by association operation: child to parent


READ ENTITIES OF root_ent
ENTITY child_ent
BY \_parent
ALL FIELDS WITH VALUE #( ( key_field = 1 key_field_child = 1 ) )
RESULT DATA(rba_res2)
LINK DATA(links2).
...

READ ENTITIES
OPERATIONS
"The statement is taken from the executable example. The example has a
"root entity and a child entity. For both entities, RAP BO instances
"are to be read (read and read-by-association operation).

DATA:
"The following data object is the operand of the dynamic EML statement
"It is an internal table and has a special, RAP-specific type.
op_tab TYPE abp_behv_retrievals_tab,

"More data object declarations (internal tables typed with BDEF


"derived types) that are relevant for the EML statement.
"For both entities (root and child), RAP BO instances are to be
"read. The internal tables are used for components of the internal
"table op_tab further down.
read_dyn TYPE TABLE FOR READ IMPORT zdemo_abap_rap_ro_m,
read_dyn_result TYPE TABLE FOR READ RESULT zdemo_abap_rap_ro_m,
rba_dyn TYPE TABLE FOR READ IMPORT zdemo_abap_rap_ro_m\_child,
rba_dyn_result TYPE TABLE FOR READ RESULT zdemo_abap_rap_ro_m\_child,
rba_dyn_link TYPE TABLE FOR READ LINK zdemo_abap_rap_ro_m\_child.

"Filling the internal tables, i.e. which instances are to be read


"Root entity
"Example:
"- The key is comprised of the field 'key_field'. It is of type i.
"- The %control structure is filled, flagging those fields that
" are to be read. Flagging the key field is not required.
read_dyn = VALUE #(
( %key-key_field = 1
%control = VALUE #(
field1 = if_abap_behv=>mk-on
field2 = if_abap_behv=>mk-on
field3 = if_abap_behv=>mk-on
field4 = if_abap_behv=>mk-on ) )
( %key-key_field = 2
%control = VALUE #(
field1 = if_abap_behv=>mk-on
field2 = if_abap_behv=>mk-on
field3 = if_abap_behv=>mk-on
field4 = if_abap_behv=>mk-on ) ) ).

"Child entity
"Instances to be read for a read-by-association operation
"The shared key is 'key_field'.
rba_dyn = VALUE #(
( %key-key_field = 1
%control = VALUE #(
key_ch = if_abap_behv=>mk-on
field_ch1 = if_abap_behv=>mk-on
field_ch2 = if_abap_behv=>mk-on ) )
( %key-key_field = 2
%control = VALUE #(
key_ch = if_abap_behv=>mk-on
field_ch1 = if_abap_behv=>mk-on
field_ch2 = if_abap_behv=>mk-on ) ) ).

"Filling the internal table that is the operand of the


"dynamic EML statement
"This table has optional and mandatory components.
op_tab = VALUE #(
( "op: Specifies the operation to be executed; is mandatory;
" can be set with the predefined constants, e.g. OP-R-READ
" etc., of interface IF_ABAP_BEHV
op = if_abap_behv=>op-r-read
"entity_name: Specifies the name of the RAP BO entity for which
" the operation is executed; is mandatory
entity_name = 'ZDEMO_ABAP_RAP_RO_M'
"instances: Specifies a reference to an internal table holding
" the input keys; must be appropriately typed; is mandatory
instances = REF #( read_dyn )
"results: Specifies a reference to an internal table with the required
" BDEF derived type for the read results; is mandatory
results = REF #( read_dyn_result ) )
( op = if_abap_behv=>op-r-read_ba
entity_name = 'ZDEMO_ABAP_RAP_RO_M'
"sub_name: Only relevant for specifying association names in
" read-by-association operations; in that context, it is manda
sub_name = '_CHILD'
"full: Optional flag; specifies if all target instances are to be retri
full = abap_true
instances = REF #( rba_dyn )
results = REF #( rba_dyn_result )
"links: Reference to internal table holding the key pairs of the source
" target
links = REF #( rba_dyn_link ) ) ).

READ ENTITIES OPERATIONS op_tab.

COMMIT ENTITIES

COMMIT ENTITIES
COMMIT ENTITIES COMMIT WORK
COMMIT ENTITIES
COMMIT ENTITIES sy-subrc COMMIT
ENTITIES COMMIT WORK
sy-subrc COMMIT ENTITIES

COMMIT ENTITIES

MODIFY ENTITIES OF root_ent


ENTITY root_ent
CREATE FIELDS ( key_field field1 field2 ) WITH
VALUE #( ( %cid = 'cid' key_field = 7
field1 = 'K' field2 = 'L' ) ).

COMMIT ENTITIES.

IF sy-subrc <> 0.
...
ENDIF.

IN LOCAL
MODE

IN LOCAL MODE

MODIFY ENTITIES OF root_ent IN LOCAL MODE


ENTITY root
EXECUTE book
FROM action_tab
...
if_oo_adt_classrun
if_oo_adt_classrun~main

DATA num TYPE i.

num = 2 * 3 * 5 * 53 * 2267.

cl_demo_output=>display( num ).

num
cl_demo_output=>display

0011 0010 0000 0000 0011 0111 0000 0000

32003700 838874880
3604530

DATA text TYPE c LENGTH 2.

text = '2' && '7'.

cl_demo_output=>display( text ).

cl_demo_output=>display 27
27
32003700 32003700
27
DATA hex TYPE x LENGTH 4 VALUE 'CDFFC8FF'.

hex = BIT-NOT hex.

cl_demo_output=>display( hex ).

cl_demo_output=>display
32003700

DATA hex TYPE x LENGTH 4 VALUE '32003700'.


FIELD-SYMBOLS: <num> TYPE i,
<text> TYPE c.
ASSIGN hex TO <num> CASTING.
ASSIGN hex TO <text> CASTING.

cl_demo_output=>new(
)->write_data( hex
)->write_data( <num>
)->write_data( <text> )->display( ).

hex <num>
<text>
32003700 3604530 27

TYPES hex TYPE x LENGTH 4.


FIELD-SYMBOLS:
<hex_text> TYPE hex,
<hex_num> TYPE hex.
DATA: text TYPE c LENGTH 2 VALUE '27',
num TYPE i.

num = text.

ASSIGN text TO <hex_text> CASTING.


ASSIGN num TO <hex_num> CASTING.

cl_demo_output=>new(
)->write_data( text
)->write_data( <hex_text>
)->write_data( num
)->write_data( <hex_num> )->display( ).

text num

27 27
num
num
32003700 text 1B000000 num

<hex_text> <hex_num>
text num

text
'27'
FROM

FROM

@AccessControl.authorizationCheck: #NOT_REQUIRED
define view entity DEMO_CDS_SIMPLE_TREE_VIEW
as select from demo_simple_tree
association [1..1] to DEMO_CDS_SIMPLE_TREE_VIEW as _tree
on $projection.parent = _tree.id
{
_tree,
key id,
parent_id as parent,
name
}

DEMO_SIMPLE_TREE
_tree ON
id parent
parent id

name
ON

define hierarchy DEMO_CDS_SIMPLE_TREE


with parameters
p_id : abap.int4
as parent child hierarchy(
source
DEMO_CDS_SIMPLE_TREE_SOURCE
child to parent association _tree
start where
id = :p_id
siblings order by
id ascending
)
{
id,
parent,
name
}

DEFINE HIERARCHY

SOURCE DEMO_CDS_SIMPLE_TREE_VIEW
CHILD TO PARENT ASSOCIATION _tree
START WHERE
p_id
SIBLINGS ORDER BY

{ ... }

DEFINE HIERARCHY
DEMO_SIMPLE_TREE START WHERE

ON

DEFINE HIERARCHY

FROM

DATA root_id type demo_cds_simple_tree_view-id.

...

SELECT FROM demo_cds_simple_tree( p_id = @root_id )


FIELDS id,
parent,
name,
hierarchy_rank,
hierarchy_tree_size,
hierarchy_parent_rank,
hierarchy_level,
hierarchy_is_cycle,
hierarchy_is_orphan,
node_id,
parent_id
INTO TABLE @FINAL(cds_result).

SELECT

CL_DEMO_SQL_HIERARCHIES
SELECT
NAME
HIERARCHY

DATA root_id TYPE demo_cds_simple_tree_view-id.

...

SELECT FROM HIERARCHY( SOURCE demo_cds_simple_tree_view


CHILD TO PARENT ASSOCIATION _tree
START WHERE id = @root_id
SIBLINGS ORDER BY id
MULTIPLE PARENTS NOT ALLOWED ) "hierarchy
FIELDS id,
parent,
name,
hierarchy_rank,
hierarchy_tree_size,
hierarchy_parent_rank,
hierarchy_level,
hierarchy_is_cycle,
hierarchy_is_orphan,
node_id,
parent_id
INTO TABLE @FINAL(asql_cds_result).

ASSERT asql_cds_result = cds_result.

HIERARCHY( ... )

ASSERT

DEMO_CDS_SIMPLE_TREE_VIEW
_tree

DATA root_id type demo_cds_simple_tree_view-id.

...

WITH
+cte_simple_tree_source AS
( SELECT FROM demo_simple_tree
FIELDS id,
parent_id AS parent,
name )
WITH ASSOCIATIONS (
JOIN TO MANY +cte_simple_tree_source AS _tree
ON +cte_simple_tree_source~parent = _tree~id )
SELECT FROM HIERARCHY( SOURCE +cte_simple_tree_source
CHILD TO PARENT ASSOCIATION _tree
START WHERE id = @root_id
SIBLINGS ORDER BY id
MULTIPLE PARENTS NOT ALLOWED ) "hierarchy
FIELDS id,
parent,
name,
hierarchy_rank,
hierarchy_tree_size,
hierarchy_parent_rank,
hierarchy_level,
hierarchy_is_cycle,
hierarchy_is_orphan,
node_id,
parent_id
INTO TABLE @FINAL(asql_cte_result).

ASSERT asql_cte_result = cds_result.

WITH

cte_simple_tree_source
DEMO_CDS_SIMPLE_TREE_VIEW

DEMO_SIMPLE_TREE
_tree WITH ASSOCIATIONS

WITH
SELECT

SELECT, FROM
HIERARCHY

WITH HIERARCHY
WITH
DATA root_id TYPE demo_cds_simple_tree_view-id.

...

WITH
+tree AS
( SELECT FROM demo_cds_simple_tree( p_id = @root_id )
FIELDS * )
WITH HIERARCHY demo_cds_simple_tree
SELECT FROM +tree "hierarchy
FIELDS id,
parent,
name,
hierarchy_rank,
hierarchy_tree_size,
hierarchy_parent_rank,
hierarchy_level,
hierarchy_is_cycle,
hierarchy_is_orphan,
node_id,
parent_id
INTO TABLE @FINAL(cte_cds_result).

...

WITH
+tree AS
( SELECT FROM HIERARCHY(
SOURCE demo_cds_simple_tree_view
CHILD TO PARENT ASSOCIATION _tree
START WHERE id = @root_id
SIBLINGS ORDER BY id
MULTIPLE PARENTS NOT ALLOWED ) AS asql_hierarchy
FIELDS id,
parent,
name )
WITH HIERARCHY asql_hierarchy
SELECT FROM +tree "hierarchy
FIELDS id,
parent,
name,
hierarchy_rank,
hierarchy_tree_size,
hierarchy_parent_rank,
hierarchy_level,
hierarchy_is_cycle,
hierarchy_is_orphan,
node_id,
parent_id
INTO TABLE @FINAL(cte_asql_result).
...

WITH
+cte_simple_tree_source AS
( SELECT FROM demo_simple_tree
FIELDS id,
parent_id AS parent,
name )
WITH ASSOCIATIONS (
JOIN TO MANY +cte_simple_tree_source AS _tree
ON +cte_simple_tree_source~parent = _tree~id ),
+tree AS
( SELECT FROM HIERARCHY(
SOURCE +cte_simple_tree_source
CHILD TO PARENT ASSOCIATION _tree
START WHERE id = @root_id
SIBLINGS ORDER BY id
MULTIPLE PARENTS NOT ALLOWED ) AS cte_hierarchy
FIELDS id,
parent,
name )
WITH HIERARCHY cte_hierarchy
SELECT FROM +tree "hierarchy
FIELDS id,
parent,
name,
hierarchy_rank,
hierarchy_tree_size,
hierarchy_parent_rank,
hierarchy_level,
hierarchy_is_cycle,
hierarchy_is_orphan,
node_id,
parent_id
INTO TABLE @FINAL(cte_cte_result).

ASSERT cte_cds_result = cds_result.


ASSERT cte_asql_result = cds_result.
ASSERT cte_cte_result = cds_result.

CL_DEMO_SQL_HIERARCHIES
HIERARCHY_DESCENDANTS
HIERARCHY_DISTANCE
CL_DEMO_SQL_HIERARCHIES

DATA root_id TYPE demo_cds_simple_tree_view-id.

DATA sub_id TYPE demo_cds_simple_tree_view-id.

...

SELECT FROM HIERARCHY_DESCENDANTS(


SOURCE demo_cds_simple_tree( p_id = @root_id )
START WHERE id = @sub_id )
FIELDS id,
parent_id,
name,
hierarchy_distance
INTO TABLE @FINAL(descendants).

DEMO_CDS_SIMPLE_TREE_VIEW
p_id sub_id
HIERARCHY_DISTANCE
DISTANCE

HIERARCHY_ANCESTORS
DATA root_id TYPE demo_cds_simple_tree_view-id.

DATA max_id TYPE demo_cds_simple_tree_view-id.

...

SELECT FROM HIERARCHY_ANCESTORS(


SOURCE demo_cds_simple_tree( p_id = @root_id )
START WHERE id = @max_id )
FIELDS id,
parent_id,
name,
hierarchy_distance
INTO TABLE @FINAL(ancestors).

CL_DEMO_SQL_HIERARCHIES
HIERARCHY_DISTANCE

HIERARCHY_PARENT_RANK HIERARCHY_SIBLINGS

DATA root_id TYPE demo_cds_simple_tree_view-id.

DATA sibl_id TYPE demo_cds_simple_tree_view-id.

...

SELECT FROM HIERARCHY_SIBLINGS(


SOURCE demo_cds_simple_tree( p_id = @root_id )
START WHERE id = @sibl_id )
FIELDS id,
parent_id,
name,
hierarchy_sibling_distance
INTO TABLE @FINAL(siblings).

HIERARCHY_SIBLING_DISTANCE
CL_DEMO_SQL_HIERARCHIES
HIERARCHY_DESCENDANTS_AGGREGATE
HIERARCHY_ANCESTORS_AGGREGATE

HIERARCHY_DESCENDANTS_AGGREGATE

TYPES:
BEGIN OF value,
id TYPE i,
amount TYPE p LENGTH 16 DECIMALS 2,
END OF value.

DATA value_tab TYPE SORTED TABLE OF value WITH UNIQUE KEY id.

DATA root_id TYPE demo_cds_simple_tree_view-id.

DATA sub_id TYPE demo_cds_simple_tree_view-id.

...

SELECT FROM HIERARCHY_DESCENDANTS_AGGREGATE(


SOURCE demo_cds_simple_tree( p_id = @sub_id ) AS h
JOIN @value_tab AS v
ON v~id = h~id
MEASURES SUM( v~amount ) AS amount_sum
WHERE hierarchy_rank > 1
WITH SUBTOTAL
WITH BALANCE )
FIELDS id,
amount_sum,
hierarchy_rank,
hierarchy_aggregate_type
INTO TABLE @FINAL(descendants_aggregate).

value_tab
HIERARCHY_DESCENDANTS_AGGREGATE
FROM

DEMO_CDS_SIMPLE_TREE_VIEW value_tab

SUM MEASURES

WHERE

WITH
HIERARCHY_AGGREGATE_TYPE

WITH SUBTOTAL

HIERARCHY_AGGREGATE_TYPE AMOUNT_SUM
WHERE

WITH BALANCE

HIERARCHY_AGGREGATE_TYPE
AMOUNT_SUM
WHERE

WITH

CL_DEMO_SQL_HIERARCHIES

SELECT, FROM
hierarchy_data
GROUP BY GROUP BY
LOOP AT itab IN GROUP FOR
AT NEW ...

spfli_tab SPFLI
LOOP AT GROUP BY

LOOP AT spfli_tab INTO wa


GROUP BY wa-carrid.
... wa-carrid ...
ENDLOOP.

wa wa-
carrid wa

LOOP AT spfli_tab INTO wa


GROUP BY wa-carrid.
...
LOOP AT GROUP wa INTO DATA(member).
... member-... ...
ENDLOOP.
...
ENDLOOP.
wa
member

LOOP AT spfli_tab INTO wa


GROUP BY ( key1 = wa-carrid key2 = wa-airpfrom ).
... wa-carrid ... wa-airpfrom ...
ENDLOOP.

wa

LOOP AT spfli_tab INTO wa


GROUP BY wa-carrid
INTO DATA(key).
... key ...
ENDLOOP.

INTO GROUP BY
wa key
GROUP SIZE GROUP INDEX WITHOUT MEMBERS

key wa

LOOP AT spfli_tab INTO wa


GROUP BY wa-carrid
INTO key.
...
LOOP AT GROUP key INTO member.
... members ...
ENDLOOP.
...
ENDLOOP.

LOOP AT spfli_tab INTO wa


GROUP BY ( key1 = wa-carrid key2 = wa-airpfrom )
INTO DATA(key).
... key-key1 ... key-key2 ...
ENDLOOP.

key key1 key2

NO MEMBERS

LOOP AT spfli_tab INTO wa


GROUP BY ( key1 = wa-carrid key2 = wa-airpfrom
index = GROUP INDEX size = GROUP SIZE )
WITHOUT MEMBERS
INTO DATA(key).
... key-key1 ... key-key2 ... key-index ... key-size ...
ENDLOOP.

GROUP INDEX GROUP SIZE


IF_AMDP_MARKER_HDB
HDB

CLASS cl_some_amdp_class DEFINITION


PUBLIC
FINAL
CREATE PUBLIC.

PUBLIC SECTION.
"Specifying the interface is mandatory
INTERFACES if_amdp_marker_hdb.
...
ENDCLASS.

METHODS CLASS-
METHODS

AMDP OPTIONS

...
PUBLIC SECTION.

METHODS some_amdp_meth
... "Here go the parameters

PRIVATE SECTION.

CLASS-METHODS another_amdp_meth
... "Here go the parameters

...
VALUE(...)

RETURNING

...
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.

...

METHOD

...
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 loo

... "Here goes SQLScript 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
" currently, only HDB (SAP HANA database) is possib
" LANGUAGE SQLSCRIPT -> Defines the programming language of the database
" OPTIONS READ-ONLY -> Specifies database-specific options
" USING db_object. -> Optional addition; specifies database objects;
" can also be AMDP procedures and functions

OPTIONS READ-ONLY
USING

RETURNING

RAISING

...
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.

...

BY DATABASE FUNCTION BY DATABASE PROCEDURE

...
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 loo

... "Here goes SQLScript 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
...

CLASS-METHODS
FOR TABLE FUNCTION
...
PUBLIC SECTION.

CLASS-METHODS:
table_func FOR TABLE FUNCTION some_ddl_source.

...

DEFINE TABLE FUNCTION


... WITH PARAMETERS parameter1,
parameter2, ...
... RETURNS { element1; element2; ...; } ...

IMPLEMENTED BY METHOD
amdp_class=>amdp_method

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

SELECT
SELECT * FROM some_ddl_source INTO ...

OPTIONS READ-ONLY

USING SCHEMA SUPPRESS


SYNTAX ERRORS
USING
CONNECTION
CX_AMDP_CONNECTION_ERROR CONNECTION

CALL_AMDP_METHOD CL_ABAP_DBFEATURES

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.
IF
COND
CASE
SWITCH

DO

WHILE

IF ... ELSEIF ... ELSE ... ENDIF.

IF

DATA(num) = 1 + 1.

"A simple condition: Checking if the value of num is 2


IF num = 2.
... "Statement block
"Here goes some code that should be executed if the condition is true.
ELSE.
... "Statement block
"Here goes some code that should be executed if the condition is false.
"For example, if num is 1, 8, 235, 0 etc., then do something else.
ENDIF.
...
num = 2 ...

NOT AND OR

"Single relational expression


IF num = 1.
...
ENDIF.

"Multiple expressions
IF num = 1 AND flag = 'X'.
...
ENDIF.

IF num = 1 OR flag = 'X'.


...
ENDIF.

"Multiple expressions can be parenthesized explicitly


IF ( num = 1 AND flag = 'X' ) OR ( num = 2 AND flag = 'X' ).
...
ENDIF.

IF

"Some declarations to be used in the IF statement below


DATA(num) = 2. "integer
DATA(empty_string) = ``. "empty string
DATA(flag) = 'x'.
DATA(dref) = NEW string( `ref` ). "data reference variable

"Object reference variable


DATA oref TYPE REF TO object.
"Creating an object and assigning it to the reference variable
oref = NEW zcl_demo_abap_prog_flow_logic( ).

"Declaration of and assignment to a field symbol


FIELD-SYMBOLS <fs> TYPE string.
ASSIGN `hallo` TO <fs>.

"Creating an internal table of type string inline


DATA(str_table) = VALUE string_table( ( `a` ) ( `b` ) ( `c` ) ).

"The following IF statement includes multiple expressions combined by AND to de

"Comparisons
IF 2 = num "equal, alternative EQ
AND 1 <> num "not equal, alternative NE
AND 1 < num "less than, alternative LT
AND 3 > num "greater than, alternative GT
AND 2 >= num "greater equal, alternative GE
AND 2 <= num "less equal, alternative LE

"Checks whether the content of an operand is within a closed interval


AND num BETWEEN 1 AND 3
AND NOT num BETWEEN 5 AND 7 "NOT negates a logical expression
AND ( num >= 1 AND num <= 3 ) "Equivalent to 'num BETWEEN 1 AND 3';
"here, demonstrating the use of parentheses

"Comparison operators CO, CN ,CA, NA, CS, NS, CP, NP for character-like data ty
"see the cheat sheet on string processing

"Predicate Expressions
AND empty_string IS INITIAL "Checks whether the operand is initial. The expres
"is true, if the operand contains its type-depende
AND num IS NOT INITIAL "NOT negates

AND dref IS BOUND "Checks whether a data reference variable contains a valid r
"can be dereferenced;
"Negation (IS NOT BOUND) is possible which is also valid for
AND oref IS BOUND "Checks whether an object reference variable contains a vali

"IS INSTANCE OF checks whether for a


"a) non-initial object reference variable the dynamic type
"b) for an initial object reference variable the static type
"is more specific or equal to a comparison type.
AND oref IS INSTANCE OF zcl_demo_abap_prog_flow_logic
AND oref IS INSTANCE OF if_oo_adt_classrun

AND <fs> IS ASSIGNED "Checks whether a memory area is assigned to a field symb

"See the predicate expression IS SUPPLIED in the executable example.


"It is available in method implementations and checks whether a formal paramete
"of a procedure is filled or requested.

"Predicate function: Some examples


AND contains( val = <fs> pcre = `\D` ) "Checks whether a certain value is cont
"the example uses the pcre parameter fo
"it checks whether there is any non-dig
AND matches( val = <fs> pcre = `ha.+` ) "Compares a search range of the argumen
"the example uses the pcre parameter fo
"it checks whether the value matches th
"and a sequence of any characters

"Predicate functions for table-like arguments


"Checks whether a line of an internal table specified in the table expression
"exists and returns the corresponding truth value.
AND line_exists( str_table[ 2 ] )

"Predicative method call


"The result of the relational expression is true if the result of the functiona
"is not initial and false if it is initial. The data type of the result of the
"i. e. the return value of the called function method, is arbitrary.
"A check is made for the type-dependent initial value.
AND check_is_supplied( )
"It is basically the short form of such a predicate expression:
AND check_is_supplied( ) IS NOT INITIAL

"Boolean Functions
"Determine the truth value of a logical expression specified as an argument;
"the return value has a data type dependent on the function and expresses
"the truth value of the logical expression with a value of this type.

"Function boolc: Returns a single-character character string of the type string


"If the logical expression is true, X is returned. False: A blank is returned.
"Not to be compared with the constants abap_true and abap_false in relational e
"since the latter convert from c to string and ignore any blanks. Note: If the
"expression is false, the result of boolc does not meet the condition IS INITIA
"a blank and no empty string is returned. If this is desired, the function xsdb
"can be used instead of boolc.
AND boolc( check_is_supplied( ) ) = abap_true

"Result has the same ABAP type as abap_bool.


AND xsdbool( check_is_supplied( ) ) = abap_true

"Examples for possible operands

"Data objects as shown in the examples above


AND 2 = 2
AND num = 2

"Built-in functions
AND to_upper( flag ) = 'X'
AND NOT to_lower( flag ) = 'X'

"Numeric functions
AND ipow( base = num exp = 2 ) = 4

"Functional methods
"Method with exactly one return value
AND addition( num1 = 1 num2 = 1 ) = 2
"Calculation expressions
AND 4 - 3 + 1 = num

"String expressions
AND `ha` && `llo` = <fs>

"Constructor expression
AND CONV i( '2.03' ) = num
AND VALUE string_table( ( `a` ) ( `b` ) ( `c` ) ) = str_table

"Table expression
AND str_table[ 2 ] = `b`.

"All of the logical expressions are true.

ELSE.

"At least one of the logical expressions is false.

ENDIF.

IF
IF

ELSE

ELSE ELSEIF
ELSE

ENDIF.

"IF statement with multiple included ELSEIF statements


IF log_exp1.
... "statement_block1

ELSEIF log_exp2.

... "statement_block2

ELSEIF log_exp3.

... "statement_block3

... "further ELSEIF statements

ELSE.

... "statement_blockn

ENDIF.

DATA(num) = 1.
DATA(flag) = 'X'.

IF num = 1.

IF flag = 'X'.
...
ELSE.
...
ENDIF.

ELSE.

... "statement block, e. g.


"ASSERT 1 = 0.
"Not to be executed in this example.

ENDIF.

ASSERT 1 = 0
ELSE ELSE
COND

COND

COND
#

THEN

... COND type( WHEN log_exp1 THEN result1


WHEN log_exp2 THEN result2
...
ELSE resultn ) ...

CASE
CASE

CASE

WHEN CASE

WHEN WHEN op1 OR


op2 OR op3 ...
WHEN
OTHERS.

ENDCASE.

CASE operand.
WHEN op1.
... "statement_block
WHEN op2.
... "statement_block
WHEN op3 OR op4.
... "statement_block
WHEN OTHERS.
... "statement_block
ENDCASE.

CASE TYPE OF
"oref must be an object reference variable with the static type of a class or a
CASE TYPE OF oref.
WHEN TYPE some_class.
... "statement_block
WHEN TYPE some_intf.
... "statement_block
WHEN OTHERS.
... "statement_block
ENDCASE.

SWITCH

SWITCH
COND
SWITCH COND

... SWITCH type( operand


WHEN const1 THEN result1
WHEN const2 THEN result2
...
ELSE resultn ) ...

DO

DO ENDDO

EXIT

DO.
... "statement_block
"To be terminated with an EXIT statement.
ENDDO.

TIMES

DO 5 TIMES.
... "statement_block
ENDDO.

sy-index

CONTINUE CONTINUE.

log_exp
CHECK
CHECK
log_exp.

EXIT EXIT.

RETURN
RETURN

EXIT CHECK

WHILE

WHILE ENDWHILE

DO sy-index

WHILE log_exp.
... "statement_block
ENDWHILE.
LOOP ... ENDLOOP

sy-index
sy-tabix

VALUE REDUCE

SELECT ... ENDSELECT

RETURN

CX_...

TRY

TRY
TRY.
"statement block
ENDTRY.

TRY CATCH

CATCH CATCH

CX_SY_ZERODIVIDE

TRY.
"TRY block
DATA(div1) = 1 / 0.

"Predefined exception class cx_sy_zerodivide as suitable exception class


"If the exception is not handled, the program is terminated and the runti
"COMPUTE_INT_ZERODIVIDE occurs.
CATCH cx_sy_zerodivide.
... "CATCH block
ENDTRY.

"Example for catching an exception in the context of a table expression


TRY.
"Copying a line of an internal table
DATA(line) = some_itab[ 12345 ].

"Predefined exception class cx_sy_itab_line_not_found as suitable excepti


"If the exception is not handled, the program is terminated and the runti
"ITAB_LINE_NOT_FOUND occurs.
CATCH cx_sy_itab_line_not_found.
... "CATCH block
ENDTRY.

"Note on inheritance relationships in exception classes


TRY.
"TRY block
DATA(div2) = 1 / 0.

"A CATCH block is in this example not only valid for cx_sy_zerodivide as
"but also for all derived exceptions classes.
"In the following CATCH block, the predefined exception class cx_sy_arith
"is specified. cx_sy_zerodivide is derived from cx_sy_arithmetic_error.
"Hence, cx_sy_arithmetic_error can be specified and handle the exception,
"Basically, using the exception root class cx_root would be also possible
"choosing an appropriate exception class is recommended. See further down

CATCH cx_sy_arithmetic_error.
... "CATCH block
ENDTRY.

"Multiple classes in a list and CATCH blocks can be specified


"Note: If there are multiple CATCH blocks for exceptions that are in an inh
"relationship, you must pay attention that the more special exceptions are
"before the more general ones.
TRY.
... "TRY block
CATCH cx_abc cx_bla cx_blabla.
... "CATCH block
CATCH cx_la cx_lala.
... "CATCH block
CATCH cx_lalala.
... "CATCH block
ENDTRY.

INTO CATCH

CX_SY_ZERODIVIDE

CX_SY_ARITHMETIC_OVERFLOW
CX_SY_ARITHMETIC_ERROR
CX_SY_ARITHMETIC_ERROR
CX_SY_ARITHMETIC_OVERFLOW CX_SY_ZERODIVIDE
INTO

DATA: exception TYPE REF TO cx_root. "Note the root class


"Note: For a self-defined exception class, the object reference must be typ

TRY.
... "TRY block

"Storing a reference to the exception object.


"Note: The type is cx_root since attributes and methods of the root class
CATCH INTO exception.
... "CATCH block
ENDTRY.

"Inline creation of exception object reference and getting exception texts


TRY.
... "TRY block

"The object reference variable can be created inline, for example, using
CATCH cx_sy_arithmetic_error INTO DATA(error_oref).
... "catch block
"To get exception texts, you can call, for example, the method get_text
DATA(error_text) = error_oref->get_text( ).

ENDTRY.

TRY.
TRY
CATCH
CATCH
TRY

TRY

TRY

TRY
ENDTRY

CX_SY_ZERODIVIDE COMPUTE_INT_ZERODIVIDE

UNCAUGHT_EXCEPTION
TRY

CX
CL

CX_STATIC_CHECK CX_DYNAMIC_CHECK CX_NO_CHECK

CX_ROOT CX_ROOT

CX_SY_ZERODIVIDE
CX_STATIC_CHECK

CX_STATIC_CHECK

TRY

RAISING

CX_SOME_ERROR CX_STATIC_CHECK

"Method definition using the RAISING parameter


CLASS-METHODS: some_meth IMPORTING str TYPE string
RETURNING VALUE(ret_value) TYPE string
RAISING cx_some_error.

...

"Method call: Somewhere in the code of a user that calls the method
"Exception handled locally in a TRY control structure.
TRY.
DATA(val) = some_meth( str = `hallo` ).

CATCH cx_some_error.
...
ENDTRY.

"If it was just like this without the TRY control structure, a warning
DATA(val2) = some_meth( str = `hi` ).

CX_DYNAMIC_CHECK

CX_STATIC_CHECK CX_DYNAMIC_CHECK

CX_SY_NO_HANDLER PREVIOUS
CX_SY_ZERODIVIDE
CX_DYNAMIC_CHECK

CX_NO_CHECK

CX_NO_CHECK

RAISE EXCEPTION

COND THROW

...
"RAISE EXCEPTION statement
"The TYPE addition specifies the type of the exception, i. e. the exception cla
"The statement is also possible without TYPE. In that case, you can use an exis
"Note that there are plenty of additions. Check the ABAP Keyword Documentation.
RAISE EXCEPTION TYPE cx_sy_zerodivide.
...

"THROW addition for the COND operator


... = COND #( WHEN ... THEN ...
WHEN ... THEN ...
ELSE THROW cx_some_error( ) ).
ASSERT

ASSERT ASSERT

ASSERTION_FAILED

"The ASSERT keyword is followed by a logical expression.


"If the expression is false, the program is terminated and an uncatchable excep
"resulting in the runtime error ASSERTION_FAILED.

DATA(flag) = abap_false.

ASSERT flag = abap_true.


"Test class in the test include
CLASS ltc_test_class DEFINITION
FOR TESTING "Defines a class to be used in ABAP Unit
RISK LEVEL HARMLESS "Defines risk level, options: HARMLESS/CRITIC
DURATION SHORT. "Expected test execution time, options: SHORT

...

ENDCLASS.

CLASS ltc_test_class IMPLEMENTATION.


...
ENDCLASS.

FOR TESTING

FOR TESTING
RISK LEVEL ...
CRITICAL
DANGEROUS
HARMLESS
DURATION ...
SHORT
MEDIUM
LONG

CTRL SPACE

"The code in this snippet refers to the test class in the test include.
"Test class, declaration part
CLASS ltc_test_class DEFINITION
FOR TESTING
RISK LEVEL HARMLESS
DURATION SHORT.

...

ENDCLASS.

"Declaring friendship
CLASS cl_class_under_test DEFINITION LOCAL FRIENDS ltc_test_class.

"Test class, implementation part


CLASS ltc_test_class IMPLEMENTATION.
...
ENDCLASS.

DEFERRED
"Test include

CLASS ltc_test_class_1 DEFINITION DEFERRED.


CLASS ltc_test_class_2 DEFINITION DEFERRED.
CLASS cl_class_under_test DEFINITION LOCAL FRIENDS ltc_test_class_1
ltc_test_class_2.

CLASS ltc_test_class_1 DEFINITION


FOR TESTING
RISK LEVEL HARMLESS
DURATION SHORT.
...
ENDCLASS.

CLASS ltc_test_class_1 IMPLEMENTATION.


...
ENDCLASS.

CLASS ltc_test_class_2 DEFINITION


FOR TESTING
RISK LEVEL HARMLESS
DURATION SHORT.
...
ENDCLASS.

CLASS ltc_test_class_2 IMPLEMENTATION.


...
ENDCLASS.

PARTIALLY IMPLEMENTED

"Test double class in a test include


CLASS ltd_test_double DEFINITION FOR TESTING.
PUBLIC SECTION.
INTERFACES some_intf PARTIALLY IMPLEMENTED.
ENDCLASS.

CLASS ltd_test_double IMPLEMENTATION.


METHOD some_intf~some_meth.
...
ENDMETHOD.
ENDCLASS.
FOR TESTING

ABSTRACT

CL_ABAP_UNIT_ASSERT

"Test class in a test include


"Test class declaration part
CLASS ltc_test_class DEFINITION
FOR TESTING
RISK LEVEL HARMLESS
DURATION SHORT.

PRIVATE SECTION.
"Note: As a further component in test classes, usually, a reference varia
"is created for an instance of the class under test.
DATA ref_cut TYPE REF TO cl_class_under_test.

"Test method declaration


METHODS some_test_method FOR TESTING.

ENDCLASS.

"Test class implementation part


CLASS ltc_test_class IMPLEMENTATION.

METHOD some_test_method.
... "Here goes the implementation of the test.
ENDMETHOD.

ENDCLASS.
CL_ABAP_UNIT_ASSERT
CL_ABAP_UNIT_ASSERT

ASSERT_EQUALS
ASSERT_BOUND
ASSERT_NOT_BOUND
ASSERT_INITIAL
ASSERT_NOT_INITIAL
ASSERT_SUBRC sy-subrc
FAIL

ACT ANY

EXP ANY
ASSERT_EQUALS
MSG CSEQUENCE
QUIT INT1
if_abap_unit_constant=>quit-no

"The code in this snippet refers to the production code in the global class.
"It shows a method declaration for a simple calculation in the class under test

"Class declaration part


CLASS cl_class_under_test DEFINITION
PUBLIC
CREATE PUBLIC.

PRIVATE SECTION.

METHODS:
multiply_by_two IMPORTING num TYPE i
RETURNING VALUE(result) TYPE i.

...
"Class implementation part
CLASS cl_class_under_test IMPLEMENTATION.

METHOD multiply_by_two.
result = num * 2.
ENDMETHOD.
...
"The code in this snippet refers to the test class in the test include.
...

"Test class, implementation part


CLASS ltc_test_class IMPLEMENTATION.

"Test method implementation


METHOD some_test_method.
"given
"Creating an object of the class under test
"Assumption: A reference variable has been declared (DATA ref_cut TYPE REF
"A variable declared inline may not be the best choice if there is more tha
"test method in the class that also needs an object of the class under test
"See also the setup method further down in this context.
ref_cut = NEW #( ).
"DATA(ref_cut) = NEW cl_class_under_test( ).

"when
"Calling method that is to be tested
"As an example, 5 is inserted. The result should be 10, which is then check
DATA(result) = ref_cut->multiply_by_two( 5 ).

"then
"Assertion
cl_abap_unit_assert=>assert_equals(
act = result
exp = 10 ).

"Further optional parameters specified


* cl_abap_unit_assert=>assert_equals(
* act = result
* exp = 10
* msg = |The result of 5 multiplied by 2 is wrong. It is { result }.
* quit = if_abap_unit_constant=>quit-no ).

ENDMETHOD.

ENDCLASS.
FOR TESTING

setup
teardown

class_setup
class_teardown

"Test class, declaration part


CLASS ltc_test_class DEFINITION
FOR TESTING
RISK LEVEL HARMLESS
DURATION SHORT.

PRIVATE SECTION.
DATA: ref_cut TYPE REF TO cl_class_under_test.

METHODS:
"special methods
setup,
teardown,

"test methods
some_test_method FOR TESTING,
another_test_method FOR TESTING.

ENDCLASS.

"Test class, implementation part


CLASS ltc_test_class IMPLEMENTATION.

METHOD setup.
"Creating an object of the class under test
ref_cut = NEW #( ).

"Here goes, for example, code for preparing the test data,
"e.g. filling a database table used for test methods.
...
ENDMETHOD.

METHOD some_test_method.

"Method call
DATA(result) = ref_cut->multiply_by_two( 5 ).

"Assertion
cl_abap_unit_assert=>...

ENDMETHOD.

METHOD another_test_method.
"Another method to be tested, it can also use the centrally created instanc

"Calling method
DATA(result) = ref_cut->multiply_by_three( 6 ).

"Assertion
cl_abap_unit_assert=>...

ENDMETHOD.

METHOD teardown.
"Here goes, for example, code to undo the test data preparation
"during the setup method (e.g. deleting the inserted database table entr
...
ENDMETHOD.

ENDCLASS.
PARTIALLY IMPLEMENTED

FINAL

constructor

TEST-SEAM ... END-TEST-SEAM

"The code in this snippet refers to the production code.

...
DATA some_table TYPE TABLE OF dbtab WITH EMPTY KEY.

"TEST-SEAM + name of the test seam ... END-TEST-SEAM define a


"code block that is to be replaced when running unit tests.

TEST-SEAM select_from_db.
SELECT * FROM dbtab
INTO TABLE @some_table.
END-TEST-SEAM.

...

"The code in this snippet refers to the code in the test class.

...

"TEST-INJECTION + name of the test seam ... END-TEST-INJECTION define a code


"block to replace the code block in the production code when running unit tests
"In the example below, the DOC (a database access) is solved by providing local
"test data.

TEST-INJECTION select_from_db.
some_table = VALUE #(
( ... )
( ... ) ).
END-TEST-INJECTION.

...

Ctrl + Shift + F10

Ctrl + Shift + F11


CL_ABAP_TESTDOUBLE
SELECT

zdemo_abap_cds_ve...
WAIT
COMMIT CONNECTION

DB_COMMIT

COMMIT WORK

ROLLBACK CONNECTION

DB_ROLLBACK

ROLLBACK WORK
CALL FUNCTION ... IN UPDATE TASK

COMMIT WORK

FUNCTION zsome_update_fu_mod
IMPORTING
VALUE(values) TYPE some_dbtab.

MODIFY some_dbtab FROM @values.

ENDFUNCTION.

COMMIT WORK AND


WAIT

COMMIT WORK
COMMIT WORK AND WAIT

SET UPDATE TASK


LOCAL

"Synchronous update

DATA(st_a) = VALUE some_type( ... ).

...

"Registering the update function module specified in uppercas


CALL FUNCTION 'ZSOME_UPDATE_FU_MOD' IN UPDATE TASK
EXPORTING values = st_a.

...

"Triggering the synchronous update


COMMIT WORK AND WAIT.

*************************************************************
"Asynchronous update

DATA(st_b) = VALUE some_type( ... ).

...

CALL FUNCTION 'ZSOME_UPDATE_FU_MOD' IN UPDATE TASK


EXPORTING values = st_b.

...

"Triggering the asynchronous update


COMMIT WORK.

*************************************************************
"Local update

"Before update function modules are registered.


SET UPDATE TASK LOCAL.

DATA(st_c) = VALUE some_type( ... ).

...

CALL FUNCTION 'ZSOME_UPDATE_FU_MOD' IN UPDATE TASK


EXPORTING values = st_c.
...

"The update will be synchronous no matter if you use the COMM


"statement with or without the addition AND WAIT.
COMMIT WORK.
"COMMIT WORK AND WAIT.

CALL FUNCTION ... IN BACKGROUND UNIT

PERFORM ... ON COMMIT


COMMIT WORK

PERFORM ... ON
ROLLBACK ROLLBACK WORK

ON COMMIT
COMMIT WORK [AND
WAIT] ROLLBACK WORK

COMMIT WORK [AND WAIT]

COMMIT WORK COMMIT WORK AND WAIT

ROLLBACK WORK

COMMIT WORK
AUTHORITY-CHECK
ENQUEUE_... DEQUEUE_...

CL_ABAP_LOCK_OBJECT_FACTORY

COMMIT ENTITIES COMMIT WORK COMMIT


ENTITIES
COMMIT WORK COMMIT WORK
AND WAIT

ROLLBACK ENTITIES
ROLLBACK WORK

CTRL + SHIFT + A

zdemo_abap_sap_luw

F8
COMMIT WORK COMMIT WORK AND WAIT SET UPDATE TASK
LOCAL

PERFORM ... ON COMMIT PERFORM ... ON


ROLLBACK

COMMIT WORK COMMIT WORK AND WAIT


ROLLBACK WORK
CL_SYSTEM_TRANSACTION_STATE

COMMIT WORK COMMIT


WORK SELECT

COMMIT WORK AND WAIT


COMMIT WORK AND WAIT SELECT

SET UPDATE TASK LOCAL


COMMIT WORK COMMIT
WORK AND WAIT

SET UPDATE TASK


LOCAL
ON
COMMIT

COMMIT WORK COMMIT WORK AND WAIT


SELECT

ON
ROLLBACK

ON COMMIT ON ROLLBACK

EXPORT IMPORT
sy-dynnr
CALL SCREEN
PROCESS BEFORE OUTPUT

PROCESS AFTER INPUT

PROCESS ON HELP-REQUEST

PROCESS ON VALUE-REQUEST
PROCESS BEFORE OUTPUT.
... "Here, for example, modules can be called.

PROCESS AFTER INPUT.


...

"When you implement field or value helps, use the following processin
PROCESS ON HELP-REQUEST.
...

PROCESS ON VALUE-REQUEST.
...

MODULE

FIELD

CHAIN ENDCHAIN

LOOP ENDLOOP
LOOP

CALL SUBSCREEN

MODULE ENDMODULE

MODULE
some_module_9000.
some_module_9000
PROCESS BEFORE OUTPUT MODULE
OUTPUT

PROCESS AFTER INPUT PROCESS ON HELP-REQUEST PROCESS ON


VALUE-REQUEST INPUT

"Flow Logic tab in the screen painter

PROCESS BEFORE OUTPUT.


MODULE pbo_9000.

PROCESS AFTER INPUT.


MODULE pai_9000.

MODULE pbo_9000 OUTPUT.


...
ENDMODULE.

MODULE pai_9000 INPUT.


...
ENDMODULE.
CLNT FLTP

DATA
CLASS-DATA

TABLES

DATA CLASS-DATA

TABLES
PROGRAM some_program.

"Variable declarations
DATA some_dobj TYPE abap_bool.
TABLES some_struct.

CLASS local_class DEFINITION.


PUBLIC SECTION.
CLASS-DATA: another_dobj TYPE i.
...

ENDCLASS.

CLASS local_class IMPLEMENTATION.


...
ENDCLASS.

ok_code

CASE

sy-ucomm

sy-ucomm
CASE

PROGRAM zdemo_program.

"OK field declaration and auxiliary variable, assuming the OK field i


"ok_code in the Element List tab of the dynpro.
DATA: ok_code LIKE sy-ucomm,
save_ok LIKE ok_code.

...

"Dialog modules in the program

"PBO
MODULE pbo_9000 OUTPUT.
...
"Prefill the value for a screen element, e.g. input field
some_input_field = 'Hallo'.
...
ENDMODULE.

"PAI
MODULE pai_9000 INPUT.
save_ok = ok_code.
CLEAR ok_code.

CASE save_ok.
"For example, a button is linked with a function code named PUSH
WHEN 'PUSH'.
...
WHEN 'ENTER'.
...
WHEN 'CANCEL'.
...
WHEN OTHERS.
...
ENDCASE.
ENDMODULE.
...

FIELD

FIELD

FIELD
FIELD
FIELD

PROCESS AFTER INPUT

"Note: More syntax options are possible with the FIELD statement.
"See some of them below and more details in the ABAP Keyword Document

PROCESS AFTER INPUT.


MODULE pai_9000. "neither field_a nor field_b are available
FIELD field_a.
MODULE module_a. "field_a is available, field_b is not
FIELD field_b.
MODULE module_b. "both field_a and field_b are available
FIELD MODULE

mod
dynp_field

FIELD dynp_field MODULE mod ON INPUT.

mod dynp_field

FIELD dynp_field MODULE mod ON REQUEST.

CHAIN ENDCHAIN

CHAIN.
FIELD dynp_field1.
FIELD dynp_field2.
...
MODULE mod ON CHAIN-INPUT.
"Note: ON REQUEST is also possible
ENDCHAIN.

required
E

MODULE mod AT EXIT-COMMAND.

LEAVE

W E MESSAGE

FIELD CHAIN

FIELD

FIELD dynp_field MODULE mod.

mod

CHAIN
CHAIN.
FIELD dynp_field1.
FIELD dynp_field2.
...
MODULE mod.
ENDCHAIN.

mod

PROCESS ON HELP-REQUEST
FIELD dynp_field MODULE mod.

FIELD

mod
HELP_OBJECT_SHOW
PROCESS ON VALUE-REQUEST
FIELD dynp_field MODULE mod.

FIELD

DYNP_VALUES_READ DYNP_VALUES_UPDATE
F4IF_INT_TABLE_VALUE_REQUEST
CALL
SCREEN

SET SCREEN dynnr.

"Assumption: The static next dynpro is 9100.


"With the statement, the next dynpro is dynamically set and 9100 over

SET SCREEN 9200.

***************************

"The current dynpro sequence is terminated.


SET SCREEN 0.

CALL SCREEN dynnr.


"Starting a new dynpro sequence

CALL SCREEN 9300.

STARTING AT ENDING AT

"Opening a dynpro in a modal dialog box


CALL SCREEN dynnr STARTING AT col_up_left line_up.
CALL SCREEN dynnr STARTING AT col_up_left line_up ENDING AT col_u

STARTING AT ENDING AT

col_up_left line_up

col_up_right line_low
col_up_left line_up
col_up_right line_low

LEAVE SCREEN. LEAVE TO SCREEN dynnr.

LEAVE SCREEN.

SET SCREEN

LEAVE TO SCREEN
SET SCREEN
dynnr. LEAVE SCREEN.

LEAVE
CALL
TRANSACTION LEAVE TO TRANSACTION

LEAVE PROGRAM

"Assumption: The next dynpro is statically defined as 9100.


"The following statement ends the processing of the current dynpro.
"Dynpro 9100 is called.
LEAVE SCREEN.

****************************************

"The following statement ends the processing of the current dynpro.


"The statically defined dynpro 9100 is overwritten. Dynpro 9200 is ca
SET SCREEN 9200.
LEAVE SCREEN.

****************************************

"The following statement is a shorter form of the one above.


"It has the same effect.
LEAVE TO SCREEN 9200.

****************************************

"Ending the dynpro sequence


SET SCREEN 0.
LEAVE SCREEN.

LOOP AT SCREEN MODIFY SCREEN

LOOP AT SCREEN

SCREEN
LOOP AT SCREEN

MODIFY SCREEN
LOOP AT SCREEN

SCREEN FROM

MODULE pbo_9000 OUTPUT.


"Assumption: An input field is not marked as required
"(i.e. the value of the component is 0).
"The example makes the input field required.
LOOP AT SCREEN INTO DATA(scr).
IF scr-name = 'SOME_INPUT_FIELD'.
scr-required = '1'.
MODIFY SCREEN FROM scr.
ENDIF.
ENDLOOP.
ENDMODULE.

SET PF-STATUS

"Setting the GUI status (in PBO)


SET PF-STATUS status.

****************************************

"Setting the GUI status and excluding function codes, i.e. th


"specified function codes are deactivated. fcode expects eith
"a character-like data object or an internal table with a fla
"character-like line type.
SET PF-STATUS status EXCLUDING fcode.

sy-
pfkey GET PF-STATUS

"Getting the GUI status


GET PF-STATUS status.
st = sy-pf-key.

****************************************

"The following statement inserts the function codes which are


"inactive in the current GUI status line by line into the
"internal table fcode
GET PF-STATUS status EXCLUDING fcode.

SET TITLEBAR

"Setting a title (in PBO)


"Here, title is not the text content itself, but the name of
"a further UI component of the program.
SET TITLEBAR title.

"The name of the current GUI title is displayed in the system


gui_title = sy-title.

****************************************

"WITH addition
"The placeholders of a GUI title can be replaced by the forma
"content of data objects text1, and so on.
SET TITLEBAR title WITH text1 ... text9.
CONTROLS

CONTROLS contr TYPE TABLEVIEW USING SCREEN dynnr.

LOOP WITH CONTROL

PROCESS BEFORE OUTPUT.


...
LOOP WITH CONTROL contr.
MODULE mod_fill_table.
ENDLOOP.
...
PROCESS AFTER INPUT.
...
LOOP WITH CONTROL contr.
MODULE mod_read_table.
ENDLOOP.
...

REFRESH CONTROL

"Code in an ABAP Program


...
REFRESH CONTROL contr FROM SCREEN dynnr.
...

CONTROLS tabstr TYPE TABSTRIP.

activetab

CALL
SUBSCREEN

activetab

CALL SUBSCREEN

CALL SUBSCREEN sub_area INCLUDING prog dynnr.

CALL
SUBSCREEN
CALL SUBSCREEN sub_area.

"Code in a PBO dialog module


...
"Providing a dynpro number
dynnr = '9400'.
"Assign the activetab component
tabstr-activetab = 'SOME_TAB'.
"Providing teh prgram name
prog = sy-repid.
...

******************************************************

"Code in the flow logic

PROCESS BEFORE OUTPUT.


...
CALL SUBSCREEN sub_area INCLUDING prog dynnr.
...

PROCESS AFTER INPUT.


...
CALL SUBSCREEN sub_area.
...

CL_GUI_TOOLBAR
ADD_BUTTON
FUNCTION_SELECTED

CL_GUI_PICTURE

LOAD_PICTURE_FROM_URL
PICTURE_DBLCLICK

CL_GUI_HTML_VIEWER

SAPEVENT

CL_GUI_TEXTEDIT

FIND_AND_REPLACE

CL_GUI_SIMPLE_TREE

CL_GUI_ALV_GRID
CL_SALV_TABLE

CTRL + SHIFT + A demo_dynpro*

CTRL + SHIFT + A

zdemo_abap_dynpro

F8
MODULE FIELD CHAIN ENDCHAIN LOOP ENDLOOP CALL SUBSCREEN

SET SCREEN CALL


SCREEN LEAVE SCREEN

LOOP AT SCREEN MODIFY SCREEN

GET SET PF-STATUS SET


TITLEBAR
MODULE ... AT EXIT-COMMAND

You might also like