0% found this document useful (0 votes)
85 views65 pages

Code Standard S4 HANA

The document outlines ABAP development standards for S/4 HANA, emphasizing best practices such as avoiding dynamic coding techniques and adhering to naming conventions for packages and transport requests. It introduces the 'code-to-data' paradigm for optimizing application logic execution in the database layer, along with guidelines for using Core Data Services (CDS) to enhance performance and maintainability. Additionally, it provides recommendations for text search functionalities and performance best practices in CDS development.

Uploaded by

ramu s
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
85 views65 pages

Code Standard S4 HANA

The document outlines ABAP development standards for S/4 HANA, emphasizing best practices such as avoiding dynamic coding techniques and adhering to naming conventions for packages and transport requests. It introduces the 'code-to-data' paradigm for optimizing application logic execution in the database layer, along with guidelines for using Core Data Services (CDS) to enhance performance and maintainability. Additionally, it provides recommendations for text search functionalities and performance best practices in CDS development.

Uploaded by

ramu s
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 65

1.

ABAP Development for S/4 HANA Coding and Naming Standards


ABAP offers a bunch of capabilities to make the developers life easier. From a security, support and
maintenance point of view do not use such techniques and have some alternate strategies from
newer versions of SAP .

• Avoid FOR all entries in ABAP statement


• Avoid dynamic call of subroutines (perform xy in <program> if exists)
• Avoid dynamic selection of variables, tables,…
• Avoid dynamic call of methods, classes, function modules
• Avoid dynamic assign of variables outside the visibility of the unit
• Avoid Import/Export of memory -> static methods and attributes of global classes
• Avoid usage of SET/GET parameters
• Avoid definition and use of macros
• Avoid creation of clones
• Avoid generic exception catching

1.1. Package and transport request creation


The transport request creation strategy is covered in a separate document <>.

Packages are designed to help developers modularize, encapsulate, and decouple units in SAP
system. In the programmer, one package would be created per work-stream. Any major bespoke
development would have a sub-package created. Every technical specification document should
have the package information. Developments will not be started without appropriate package.
Naming conventions for Transports will be adhered to with Logical Units of work placed into a
Transport/task.

Use a package hierarchy concept

• For every business functionality use a dedicated enclosed package


• Interfaces to external systems shall be managed in a dedicated interface package separated
by interface partners (e.g. by systems)
• Global functionality in global re-use packages

Separate business behaviors in packages with the main goal to replace or delete each package

Naming concept of packages shall

• Never represent project structures


• Never represent organizational company structures like locations

1.2. Basic Principles of ABAP Development for S/4 HANA

SAP HANA (High Performance Analytical Appliance) is a revolutionary in-memory technology which
has transformed the way ABAP applications are developed. In order to take advantage of the
Hardware and Software innovations at the least part of the application logic must be executed in the
database.

Traditionally ABAP based applications use the “data-to-code paradigm” wherein the orchestration
and calculation logic are performed in the Application Layer. While using data to code paradigm,
ABAP Programs fetches the data from the database tables and buffers them into the internal tables
of the application server. The logic is applied on the application server and the calculations are
performed and eventually either displayed on the presentation sever. All the calculation logic is
wholly implemented in the application server wherein a substantial amount of data may be
transferred from the Database server to the Application server. This work well for traditional
database applications but not for ABAP on HANA
ABAP applications specifically designed for SAP HANA use the “code-to-data paradigm” where some
of the application logic is executed in the database layer. In extreme cases the entire application
logic can be executed in the database layer. The amount of data transfer to the application server
can be kept to a minimum which fundamentally speeds up the process.

1.2.1. Code to Data Paradigm (Code Pushdown Principle)

In ABAP for HANA you can push down data intense computations and calculations to the HANA
DB layer instead bringing all the data to the ABAP layer and the processing the data to do
computations. This is what is termed as Code-to-Data paradigm in the context of developing
ABAP applications optimized for HANA.

1.2.2. Code Push Down to HANA from ABAP using Open SQL
1. Start using the new Open SQL syntax.

SELECT carrid, connid


FROM sflight
INTO CORRESPONDING FIELDS OF @<result>
WHERE carrid = @carrid.
2.
Use aggregate functions
where relevant instead of doing the aggregations in the ABAP layer

SELECT fldate, COUNT( * ), AVG( luggweight ), MAX( luggweight )


FROM sbook
WHERE carrid = 'LH' AND connid = '0400'
GROUP BY fldate
INTO TABLE @itab.

3. Use arithmetic and string expressions within Open SQL statements instead of looping over
the data fetched to do the arithmetic and string operations.

Arithmetic Expressions

SELECT id, num1, num2,


CAST( num1 AS fltp )/CAST( num2 AS fltp ) AS ratio,
DIV( num1, num2 ) AS div,
MOD( num1, num2 ) AS mod,
@OFFSET + abs( num1 - num2 ) AS sum
FROM demo_expressions
ORDER BY SUM DESCENDING
INTO TABLE @DATA(results).

String Expressions

SELECT SINGLE
char1 AS text1,
char2 AS text2,
CONCAT( char1,char2 ) AS concat,
LPAD( char1,10,'x' ) AS lpad,
LENGTH( char1 ) AS length,
LTRIM( char1,' ' ) AS ltrim,
REPLACE( char1,'12',' ' ) AS replace,
RIGHT( char1,3 ) as right,
RTRIM( char1,'3' ) AS rtrim,
SUBSTRING( char1,3,3 ) AS substring
FROM demo_expressions
INTO @DATA(result).

4. Use computed columns in order to push down computations that would otherwise be done in a
long loops
SELECT char1 && '_' && char2 AS
group, MAX( num1 + num2 ) AS
max, MIN( num1 + num2 ) AS min
FROM demo_expressions
GROUP BY char1, char2
HAVING MIN( num1 * num2 ) > 25
ORDER BY group
INTO TABLE @DATA(grouped_having).

5. Use CASE and/or IF..ELSE expressions within the Open SQL in order embed the logic of
conditional expression which in the past would have been done after fetching the results from
the database.

SELECT id, char1, char2,


CASE char1
WHEN 'aaaaa' THEN ( char1 && char2 )
WHEN 'xxxxx' THEN ( char2 && char1 )
ELSE @else
END AS text
FROM demo_expressions
INTO TABLE @DATA(results).

The graphic below provides an overview of the different code pushdown programming techniques
delivered from ABAP 7.4, and enhanced with ABAP 7.5.

1.2.3. Basic principles of the text search in SAP HANA


The main purpose of the text search function in SAP HANA is to provide users with an optimized
usability of search interfaces. In addition to various features common in Internet search engines, this
includes functions with special significance for business applications, such as industry-specific lists of
synonyms.
This involves the following characteristics:
Freestyle search
The user does not need to know the exact database columns in which the search is supposed to be
carried out. For example, you can implement an address search across a single input field and
include all technical characteristics such as street name, ZIP code, town, country, and so on.

Error-tolerant search (fuzzy search)

The user may vary the spelling slightly in his search requests.
In SAP HANA, you can call the fuzzy search by using the CONTAINS predicate with the FUZZY option
in the WHERE clause of a SELECT statement.

Linguistic search and synonym search


Linguistic variants and synonymous terms are included.
Value suggestions
The system can already efficiently identify probable search results while the user is typing and
present these to the user in real time.
Results ranking

The sequence of the search results is optimized in such a way that results with the highest
probability rate are presented at the top of the list.

Search facets

The search results can be counted and grouped according to specific criteria. For example, when
searching for airlines, you can view the distribution of the airlines per country.

Text analysis (particularly sentiment analysis)

You can extract additional information from texts, which allows you to gain insights on semantical
aspects.

1.2.3.1. Calling the Text Search from ABAP Via SQL

Because the text search function in SAP HANA is not part of the standard features of a traditional
database, the CONTAINS statement is unfortunately not yet supported in Open SQL. However, you
can still employ the text search directly from within ABAP if you use Native SQL.
Using the text search via ADBC is pretty simple. To do this, all you need to do is include the
CONTAINS statement in the Native SQL statement

“Use of CONTAINS in Native SQL

lv_sql = | SELECT * FROM SCARR | && | WHERE mandt = '{ sy-mandt }' and | && |
CONTAINS(carrname, '{ search }', fuzzy(0.8))|.
TRY. " Prepare SQL connection and statement

DATA(lo_result) =
cl_sql_connection=>get_connection(
)->create_statement(
)->execute_query( lv_sql ).

lo_result->set_param_table( REF #( lt_result ) ).

" Get result lo_result->next_package( ).

lo_result->close( ).

CATCH cx_sql_exception.

" Error handlingENDTRY.

Similarly, you can also run search requests across attribute views. Although the access via OpenSQL
is not possible here, either—due to the lack of support for the CONTAINS statement—it is
advisable that you first define an external view based on the respective attribute view. This will
facilitate the processing of data types because there is already a representation available in the
ABAP Data Dictionary

1.2.3.2. Freely Defined input helps

You can define an input help in the ABAP Data Dictionary. In general, these input helps can then be
used in both classic Dynpro-based applications and in application interfaces that have been created
using Web Dynpro ABAP or the Floorplan Manager. In this context, you can either create single (so-
called elementary) search helps, or combine multiple input helps into a collective search help. The
individual search helps are then usually displayed on separate tabs. Collective search helps are
particularly useful if you want to extend an existing search help by an optimized variant in SAP HANA
(this variant will then be hidden in other databases).

The data retrieval process in a search help can be modified using a search help exit where fuzzy
search function can be implemented.

1.2.4. Core Data Services


ABAP Core Data Services (CDS) is a new data dictionary infrastructure that was introduced with SAP
Net Weaver 7.40. It allows for defining and consuming semantically rich data models.
1.2.4.1.
Principles of ABAP Core Data
Services

Without CDS, Intensive calculations are done on the application layer avoiding costly computations
in the database. This results in rather simple SQL queries between application and database layer.
The drawback is however that lots of data needs to be transferred back and forth between those
two layers. Often, this is very time-consuming. CDS allows for a data centric approach. Intensive
computations are pushed into the database by using complex views and functions. Depending on
the use case,this may dramatically reduce execution time and simplify application coding.

1.2.4.2. Types of CDS Views


There are 3 types of CDS Views

1) Define View.
 Define View with Join.
 Define View with Association.
 Define View with Parameters.
 Annotations
2) Extend View.
3) Define Table Function with Parameters.
Define View

Defines a CDS view in the ABAP CDS in a CDS source code. A CDS is implemented using a query select
statement. The annotation AbapCatalog.sqlViewName must be specified before the view itself is
defined using DEFINE VIEW.
Define View with Joins

Defining a join between two data sources of a CDS view in ABAP CDS using join expression.

Both inner and outer joins are possible.

Define View with Associations.

Defining an association of the name _assoc in a SELECT statement of a CDS view. An association
connects the first elementary data source data source specified as the initial data source
(after FROM using the ON condition cond_exp) to the data source data_source specified as the
target data source (in the definition of the association). The target data source cannot be built using
joins.
Define View with Parameters

Defining a parameterized view with $parameters.pname: data type/data element in


a SELECT statement of a CDS view. As a developer, you can now parameterize your CDS views. It
means you can define one general views which produce context-specific result sets by using
parameter values passed at execution time. This means that you do no longer need to create a view
for each context!

Defines Input parameters pname1, pname2 in a CDS View in ABAP CDS in a comma separated list.
Each input parameter must be typed with a data type parameter type.

Extend View

Extend view is used to extend standard or custom CDS view without making any changes to the
original CDS view. In SQL view of original CDS view the classical append view is created as .APPEND in
ABAP Dictionary.(similar as append structure is used to extend DDIC tables.)

Define Table Functions with parameter.

A CDS table function is defined in CDS source code of a CDS data definition in the ABAP Development
Tools (ADT) using the statement DEFINE TABLE_FUNCTION in the ABAP Core Data Services
(CDS) DDL.

Best Practices for CDS Views


✅ Structure & Clean Design
Avoid SELECT * – always define specific field lists
Avoid nested views for performance (unless using reuse views)

Use associations instead of joins

✅ Example (Interface View)

✅ Example with UI Annotations


6. Behavior Definition Guidelines
Best Practice Recommendation
Use strict mode Enforces RAP standards
Enable draft only if required Avoid performance overhead if unnecessary
Always lock with lock master Prevent concurrent changes
Use determinations and validations Encapsulate logic where it belongs
7. Performance Best Practices in CDS
Do ✅ Avoid ❌
Use associations with filters Unfiltered associations
Use view entities (define view entity) Old define view with SQL view names
Use annotations for UI control ABAP logic for UI decisions
Use explicit field list SELECT *
Use buffering where possible Avoid deep CDS nesting
A CDS table function includes the following:

 The CDS entity

A CDS table function is declared as a CDS entity using DEFINE TABLE_FUNCTION. As a data
type in ABAP Dictionary, the CDS entity represents a structured type with the elements of
the CDS table function as components and can be used like any CDS entity.

 An AMDP function implementation

CDS table functions are implemented in Native SQL in an AMDP method and the
implementation is managed as an AMDP function by the AMDP framework in the database
system.

1.2.4.3. CDS Development Environment

At the start of the project, all developers will agree to use the latest version of the ABAP
Development Tools for SAP NetWeaver (in short: ADT). After that, only update the version when all
developers agree to do so.

1.2.4.4. CDS View Useful References


1.2.4.5. CDS Views Performance recommendations
 Keep CDS views simple (in particular serviceQuality A and B = #BASIC views)
 In transactional processing, only use simple CDS views accessed via CDS key
 Expose only required fields –define associations to reach additional fields when requested
 Perform expensive operations (e.g. calculated fields) after data reduction (filtering,
aggregation)
 Avoid joins and filters on calculated fields
 Test performance of CDS views. Test with reasonable (= realistic) test data

1.2.4.6. ABAP CDS - General Syntax Rules

The general syntax rules for the CDS DDL and CDS DCL for defining CDS objects in ABAP CDS are as
follows:

Keywords

Keywords must be all uppercase, all lowercase, or in lowercase with an uppercase initial letter. Other
mixes of uppercase and lowercase are not allowed.

Names:

Names are not case-sensitive.

A name can have a maximum of 30 characters.

A name can consist of letters, numbers, underscores (_), and slashes (/).
Support lInks:

Link: https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/abencds_annotations.html

https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABENCDS.html

https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABENABAP_RAP.html

RAP - Managed and Unmanaged Behavior Definitions


RAP business objects of the implementation types managed and unmanaged are realized through the same
set of keywords. These keywords are listed in the following sections, structured by their position within the
behavior definition. Some keywords are used differently in managed and unmanaged RAP BOs, or they are
handled by the RAP framework in managed scenarios and need to be implemented in unmanaged scenarios.
These differences are described in the respective topics.
 managed
 The transactional buffer and the standard BO operations are handled by the managed RAP BO
provider.
 Recommended for development scenarios in which all essential parts are developed from scratch,
without a large amount of existing code (also known as greenfield development) with standard
implementation.
 See also: managed RAP business object
 unmanaged
 The transactional buffer and the standard BO operations must be implemented in the ABAP behavior
pool.
 Recommended for development scenarios in which business logic already exists and is intended to be
reused (also known as brownfield development).
 See also: unmanaged RAP business object
 projection
 A RAP projection behavior definition is based on a managed or unmanaged RAP BO and represents a
direct projection of its base behavior definition. It exposes a subset of the base behavior definition's
operations and characteristics. In a business application, a projection BDEF provides the means to
define service-specific behavior for a BO projection.
 See also: RAP BDL - projection behavior definitions.
 abstract
 A RAP abstract behavior definition mainly serves as typing mechanism for deep action or function
parameters. Only a limited range of syntax elements is available, such as associations and type
mapping. It is not possible to define any transactional behavior in an abstract behavior definition.
 See also: RAP abstract behavior definition
 interface
 Defines the behavior of a RAP BO interface, which serves as interface for stable consumption and is
typically released as released API.
 See also: RAP Interface Behavior Definition.
A name must start with a letter, slash character, or underscore. Underscores are recommended as
the naming convention for ASSOCIATIONS.

The separator for names with multiple parts is a period (.). Names with multiple parts can be paths,
columns with a prefixed data source, and annotations.

The following CDS keywords cannot be used as names:

ALL, AND, AS, ASSOCIATION, AVG, CASE, CAST, CROSS, COUNT, DISTINCT, EXISTS, EXTEND, FROM, F
ULL, GROUP, HAVING, INNER, JOIN, KEY, LEFT, MAX, MIN, NOT, NULL, ON, OR, ORDER, RIGHT, SELEC
T, SUM, UNION, VIEW, WHEN, WHERE

Literals: Numeric literals must always be specified in full and a decimal point (.) used as a decimal
separator if necessary.

Character literals are enclosed in single quotation marks (').

Comments: Two forward slashes (//) or two hyphens (--) introduce a comment, which continues
until the end of the line.

Comments within lines or that span multiple lines are enclosed by the characters /* and */.

Separators: Statements can be closed using a semicolon (;). This is optional.

Protected words: Certain keywords are protected and cannot be used as self-defined names. The
reserved names that cannot be used are specified in the database table TRESE.

Note

The closing semicolon after a statement is optional because one piece of CDS source code can
currently only contain a single statement.

Examples

SELECT, select, and select are all valid ways of specifying a keyword. seLect and SeLect, on the other
hand, produce syntax errors.

MYVIEW, myview, and myView all identify the same operand.

0.5 is a valid numeric literal, but .5 is not.

1.2.4.7. ABAP CDS Entities


ABAP CDS entities are data models based on the data definition language (DDL) specification and are
managed by ABAP Dictionary.
The following types of ABAP CDS entities are supported:
ABAP CDS Views
ABAP CDS Table Functions

Defining ABAP CDS Views

The structure of such a view is defined by specifying the relevant database tables and the set of
table fields to be used in the view.

A CDS view is defined for existing database tables and views, or for other CDS views in the ABAP
Dictionary, using the DEFINE VIEW DDL statement. A CDS view serves to dene the structure of a CDS
database view and represents a projection onto one or several database tables or database views in
the ABAP Dictionary.

Defining the CDS view in the DDL editor


In the DDL editor, you can only dene one ABAP CDS entity in one data definition or metadata
extension.

Note
CDS database views and CDS entities are part of one and the same namespace. Therefore, you must
assign different names for a CDS database view and the entity.

ABAP CDS Table Functions

ABAP CDS table functions dene table functions that are implemented natively on the database and
can be called in CDS. As such, they support the HANA platform code pushdown capabilities in ABAP
CDS.
Defining ABAP CDS Table Functions
A CDS table function is defined using the ABAP CDS statement DEFINE TABLE FUNCTION and can be
used as the data source in ABAP SQL read statements.

Each CDS table function includes the following components:


The actual CDS entity of the table function that is generated in the ABAP Dictionary
The CDS table function implementation (ABAP class library)

Note: In contrast to the CDS views, the CDS table functions can be implemented using Native SQL.
This implementation is done within an AMDP method of an AMDP class and is managed as an AMDP
function by the AMDP framework in the database system.

1.2.5. AMDP – ABAP Managed Database Procedures

ABAP managed Database procedures

• AMDPs are introduced to easily enable us to get the best out of ABAP Development
for HANA.
• AMDPs are allowing developers to write database procedures directly in ABAP environment
using ABAP methods and ABAP data types.
• Push down data intense computations and calculations to the HANA DB layer
• Avoid bringing all the data to the ABAP layer.
AMDP Guidelines
1.
AMDP classes will be
created using ABAP Development tool (ADT) only.
2. If it is an AMDP then must contain the interface tag as INTERFACE
“IF_AMDP_MARKER_HDB”.
3. Should always pass by value and AMDP won’t support pass by reference.
4. Method definition should as follows
METHODS: <Method Name>
IMPORTING:
VALUE (Input value) TYPE <InType>
EXPORTING:
VALUE (Output value) TYPE <OutType>

5. Method implementation should as follows.


METHOD <meth> BY DATABASE PROCEDURE
FOR <db> -- HANA database (HDB)
LANGUAGE <db_lang> -- SQLScript s
[OPTIONS <db_options>] -- READ only
[USING <db_entities>]. -- Table
name
< Insert SQLScript code here >
ENDMETHOD.

6. Should always have an exception handling while implementing the method.


DECLARE EXIT HANDLER FOR SQLEXCEPTION -- Exit Handler for All SQL Exceptions
BEGIN

<Error_Message> = SELECT
‘E’ as MESSAGE_TYPE, “Set Message Type as Error
::SQL_ERROR_CODE as MESSAGE_CODE, “Pass Error code received to Message Code
::SQL_ERROR_MESSAGE as MESSAGE_TEXT “SQL error message to Message text
FROM dummy;
END;

1.2.5.1. Handling Internal-table inside AMDP


While developing AMDP class there must be a situation like how to handle internal table
inside AMDP.

Well below is the example for that in short and sweet manner.

1.2.5.2. AMDP: Avoiding FOR ALL ENTRIES and pushing calculation


to Database Layer
Scenario: Suppose we have customer numbers in an internal table based on that you need
to fetch data from KNA1 details inside AMDP.
Steps: AMDP Definition:
AMDP Implementation:

Calling AMDP In Program:


Same logic we can also use by Enhanced Open SQL statement like below

https://community.sap.com/t5/technology-blog-posts-by-members/sap-abap-new-syntax/ba-p/13879225
1.2.5.3.
AMDP: Avoiding DELETE

DUPICATES and pushing calculation to Database Layer using by ROW_NUMER

1.2.5.4. CDS TABLE Function: Avoiding DELETE DUPICATES and pushing calculation to
Database Layer using by CDS TABLE functions.

Create a CDS table function with table fields.

AMDP definition and implementation


Output:

We can get the unique values of LAND1 irrespective of customer number and name
ADBC – ABAP Database Connectivity

 ADBC is an API for the Native SQL interface of the AS ABAP that is based on ABAP
Objects. With ADBC, we can do the following:
 Access to entire SQL functionality of underlying DB system.
 Dynamic creation and execution of native SQL statements via respective API methods.
 Clean concept for multiple DB connections (connections are associated to connection
objects).
 Exception handling – API method have well-defined exceptions that can be handled.
 Native SQL can be used via EXEC SQL (and related) statements or the ABAP Objects
based ADBC (ABAP Database Connectivity) API.
 Class CL_SQL_CONNECTION offers methods like Create, Update and Insert etc. to work
with the underlying database. It is suggested to use ADBC as it works faster than the open
SQL.

Basic Features of ADBC

Usage of ADBC

1 Choose database connection Call method GET_CONNECTION()

(only when accessing secondary DB) of class CL SQL CONNECTION

2 Create a statement object Instantiation of class


CL_SQL_STATEMENT
3 Fill string variable with SQL syntax Use either CONCATENATE or

string templates/string expressions

4 Issue native SQL call Call method execute_query()

of class CL_SQL_STATEMENT

5 Assign target variable Call method set_param()

for result set or set_param table()

of class CL_SQL_RESULT_SET

6 Retrieve result set Call method next_package()

of class CL_SQL_RESULT_SET

7 Close result and release resources Method close()

of class CL_SQL_RESULT_SET

The logical sequence to issue a native SQL query using ADBC is shown in the above figure.

Some steps can be combined in practice when chaining method calls in ABAP or when using string

Expressions or string templates. In addition, the first step, getting a database connection, is
necessary only when using a secondary database connection for the native SQL call. A typical piece
of code using ADBC and classical string concatenation to construct the native SQL string looks as
follows:

Typical call sequence:

Required data declarations:

DATA:

Lo_sql TYPE REF TO cl_sql_statement,

Lv_sql TYPE string,

Lx_sql TYPE REF TO cx_sql_exception

Lo_result TYPE REF TO cl_sql_result_set,

Lr_flight TYPE REF TO data,

Lt_flight TYPE STANDARD TABLE OF sfilight.


Create statement object (and DB

connection if necessary)
TRY.

CREATE OBJECT lo_sql

EXPORTING con_ref = cl_sql_connection=>get_connection (‘HANADB’).

Execute query: (passing SQL query as string)

CONCATENATE 'SELECT * FROM SFLIGHT WHERE ''mandt=' ' , sy-mandt,

‘‘AND carrid = ‘LH’ ‘INTO lv_sql.

Lo_result = lo_sql->execute_query (lv_sql).

Assign internal table for result:

GET REFERENCE OF lt_flight INTO lr_flight.

Retrieve result:

Lo_result->set.param_table (lr_flight).

Lo_result->next_package ().

Close Result:

Lo_result->close ().

Handle exceptions:

CATCH cx_sql_exception INTO …

ENDTRY.

Limitations:

1. No syntax check at compile time and need to handle exception CX_SQL_EXCEPTION

2. No hashed or sorted tables as target and need to use standard table (probably with hashed
or sorted secondary key)

3. Developer is responsible for

 Client handling specify client explicitly in WHERE clauses, join conditions, etc.
 Accessing correct database schema
 Releasing DB resources (e g. result set)
 Proper locking and commit handling -DB transaction t ABAP LUW
 ABAP table buffers are bypassed
 Syntax differences to Open SQL
1. New syntax

1.1. Inline Declarations


Description Before 7.40 From 7.40 and onwards
Data statement DATA text TYPE string. DATA(text) = `ABC`.
text = `ABC`.
Loop at into work DATA wa like LINE OF itab. LOOP AT itab INTO DATA(wa).
area LOOP AT itab INTO wa. …
… ENDLOOP.
ENDLOOP.
Call method DATA a1 TYPE … oref->meth(
DATA a2 TYPE … IMPORTING p1 = DATA(a1)
oref->meth( IMPORTING p1 = a1 IMPORTING p2 = DATA(a2) ).
IMPORTING p2 = a2
).

Loop at assigning FIELD-SYMBOLS: <line> type … LOOP AT itab


LOOP AT itab ASSIGNING <line>. ASSIGNING FIELD-SYMBOL(<line>).
… …
ENDLOOP. ENDLOOP.
Read assigning FIELD-SYMBOLS: <line> type … READ TABLE itab
READ TABLE itab ASSIGNING FIELD-SYMBOL(<line>).
ASSIGNING <line>.
Select into DATA itab TYPE TABLE OF dbtab. SELECT * FROM dbtab
table SELECT * FROM dbtab INTO TABLE DATA(itab)
INTO TABLE itab WHERE fld1 = @lv_fld1.
WHERE fld1 =lv_fld1.
Select single SELECT SINGLE f1 f2 SELECT SINGLE f1 AS my_f1,
into FROM dbtab F2 AS abc
INTO (lv_f1, lv_f2) FROM dbtab
WHERE … INTO DATA(ls_structure)
WRITE: / lv_f1, lv_f2. WHERE …
WRITE: / ls_structure-
my_f1, ls_structure-abc.
1.2.
Table Expressions
If a table line is not found, the exception CX_SY_ITAB_LINE_NOT_FOUND is raised. No sy-subrc.

Description Before 7.40 From 7.40 and onwards


Read READ TABLE itab INDEX idx wa = itab[ idx ].
Table index INTO wa.
Read READ TABLE itab INDEX idx wa = itab[ KEY key INDEX idx ].
Table using USING KEY key
key INTO wa.
Read READ TABLE itab wa = itab[ col1 = … col2 = …].
Table with WITH KEY col1 = …
key col2 = …
INTO wa.
Read READ TABLE itab wa = itab[ KEY key col1 = …
Table with WITH TABLE KEY key col2 = …].
key COMPONENTS col1 = …
components col2 = …
INTO wa.
Does record READ TABLE itab … IF line_exists( itab[ … ] ).
exist? TRANSPORTING NO FIELDS. …
IF sy-subrc = 0. ENDIF.

ENDIF.
Get table DATA idx type sy-tabix. DATA(idx) =
index READ TABLE … line_index( itab[ … ] ).
TRANSPORTING NO FIELDS.
idx = sy-tabix.

NB: There will be a short dump if you use an inline expression that references a non-existent record.

SAP says you should therefore assign a field symbol and check sy-subrc.

ASSIGN lt_tab[ 1 ] to FIELD–SYMBOL(<ls_tab>).


IF sy–subrc = 0.

ENDIF.

NB: Use itab [ table_line = … ] for untyped tables.


3.3.
Conversion Operator CONV

I. Definition

CONV dtype|#( … )

dtype = Type you want to convert to (explicit)

# = compiler must use the context to decide the type to convert to (implicit)

II. Example

Method cl_abap_codepage=>convert_to expects a string

Before 7.40

DATA text TYPE c LENGTH 255.

DATA helper TYPE string.

DATA xstr TYPE xstring.

helper = text.

xstr = cl_abap_codepage=>convert_to( source = helper ).

From 7.40 and onwards

DATA text TYPE c LENGTH 255.

DATA(xstr) = cl_abap_codepage=>convert_to( source = CONV string( text )).

OR

DATA(xstr) = cl_abap_codepage=>convert_to( source = CONV #( text ) ).


3.4.
Value Operator VALUE

I. Definition

Variables: VALUE dtype|#( )

Structures: VALUE dtype|#( comp1 = a1 comp2 = a2 … )

Tables: VALUE dtype|#( ( … ) ( … ) … ) …

II. Example for structures

TYPES: BEGIN OF ty_columns1, “Simple structure


cols1 TYPE i,
cols2 TYPE i,
END OF ty_columns1.

TYPES: BEGIN OF ty_columnns2, “Nested structure


coln1 TYPE i,
coln2 TYPE ty_columns1,
END OF ty_columns2.

DATA: struc_simple TYPE ty_columns1,


struc_nest TYPE ty_columns2.

struct_nest = VALUE t_struct(coln1 = 1


coln2-cols1 = 1
coln2-cols2 = 2 ).

OR

struct_nest = VALUE t_struct(coln1 = 1


coln2 = VALUE #( cols1 = 1
cols2 = 2 ) ).

III. Examples for internal tables

Elementary line type:

TYPES t_itab TYPE TABLE OF i WITH EMPTY KEY.

DATA itab TYPE t_itab.

itab = VALUE #( ( ) ( 1 ) ( 2 ) ).
Structured line type (RANGES table):
DATA itab TYPE RANGE OF i.

itab = VALUE #( sign = ‘I’ option = ‘BT’ ( low = 1 high = 10 )


( low = 21 high = 30 )
( low = 41 high = 50 )
option = ‘GE’ ( low = 61 ) ).

3.5. FOR operator

I. Definition

FOR wa|<fs> IN itab [INDEX INTO idx] [cond]

II. Explanation

This effectively causes a loop at itab. For each loop the row read is assigned to a work area (wa) or
field-symbol(<fs>).

This wa or <fs> is local to the expression i.e. if declared in a subrourine the variable wa or <fs> is a
local variable of

that subroutine. Index like SY-TABIX in loop.

Given:

TYPES: BEGIN OF ty_ship,


tknum TYPE tknum, “Shipment Number
name TYPE ernam, “Name of Person who Created the Object
city TYPE ort01, “Starting city
route TYPE route, “Shipment route
END OF ty_ship.
TYPES: ty_ships TYPE SORTED TABLE OF ty_ship WITH UNIQUE KEY tknum.
TYPES: ty_citys TYPE STANDARD TABLE OF ort01 WITH EMPTY KEY.

GT_SHIPS type ty_ships. -> has been populated as follows:

Row TKNUM[C(10)] Name[C(12)] City[C(25)] Route[C(6)]


1 001 John Melbourne R0001
2 002 Gavin Sydney R0003
3 003 Lucy Adelaide R0001
4 004 Elaine Perth R0003
III.

Example 1

Populate internal table GT_CITYS with the cities from GT_SHIPS.

Before 7.40

DATA: gt_citys TYPE ty_citys,


gs_ship TYPE ty_ship,
gs_city TYPE ort01.

LOOP AT gt_ships INTO gs_ship.


gs_city = gs_ship–city.
APPEND gs_city TO gt_citys.
ENDLOOP.

From 7.40 and onwards

DATA(gt_citys) = VALUE ty_citys( FOR ls_ship IN gt_ships (ls_ship–city ) ).

IV. Example 2

Populate internal table GT_CITYS with the cities from GT_SHIPS where the route is R0001.

Before 7.40

DATA: gt_citys TYPE ty_citys,


gs_ship TYPE ty_ship,
gs_city TYPE ort01.

LOOP AT gt_ships INTO gs_ship WHERE route = ‘R0001’.


gs_city = gs_ship–city.
APPEND gs_city TO gt_citys.
ENDLOOP.

From 7.40 and onwards

DATA(gt_citys) = VALUE ty_citys( FOR ls_ship IN gt_ships

WHERE ( route = ‘R0001’ ) (ls_ship–city ) ).

Note: ls_ship does not appear to have been declared but it is declared implicitly.
V. FOR with THEN and UNTIL|WHILE
FOR i = … [THEN expr] UNTIL|WHILE log_exp

Populate an internal table as follows:

TYPES:
BEGIN OF ty_line,
col1 TYPE i,
col2 TYPE i,
col3 TYPE i,
END OF ty_line,
ty_tab TYPE STANDARD TABLE OF ty_line WITH EMPTY KEY.

Before 7.40

DATA: gt_itab TYPE ty_tab,


j TYPE i.
FIELD-SYMBOLS <ls_tab> TYPE ty_line.

j = 1.
DO.
j = j + 10.
IF j > 40. EXIT. ENDIF.
APPEND INITIAL LINE TO gt_itab ASSIGNING <ls_tab>.
<ls_tab>–col1 = j.
<ls_tab>–col2 = j + 1.
<ls_tab>–col3 = j + 2.
ENDDO.

From 7.40 and onwards

DATA(gt_itab) = VALUE ty_tab( FOR j = 11 THEN j + 10 UNTIL j >


40 ( col1 = j col2 = j + 1 col3 = j + 2 ) ).

3.6. Reduction operator REDUCE

II. Note

While VALUE and NEW expressions can include FOR expressions, REDUCE must include at
least one FOR expression. You can use all kinds of FOR expressions in REDUCE:

 with IN for iterating internal tables


 with UNTIL or WHILE for conditional iterations
III. Example 1
Count lines of table that meet a condition (field F1 contains “XYZ”).

Before 7.40

DATA: lv_lines TYPE i.

LOOP AT gt_itab INTO ls_itab where F1 = ‘XYZ’.


lv_lines = lv_lines + 1.
ENDLOOP.

From 7.40 and onwards

DATA(lv_lines) = REDUCE i( INIT x = 0 FOR wa IN gt_itab

WHERE( F1 = ‘XYZ’ ) NEXT x = x + 1 ).


IV. Example 2

Sum the values 1 to 10 stored in the column of a table defined as

follows DATA gt_itab TYPE STANDARD TABLE OF i WITH EMPTY

KEY.
gt_itab = VALUE #( FOR j = 1 WHILE j <= 10 ( j ) ).

Before 7.40

DATA: lv_line TYPE i,


lv_sum TYPE i.

LOOP AT gt_itab INTO lv_line.


lv_sum = lv_sum + lv_line.
ENDLOOP.

From 7.40 and onwards

DATA(lv_sum) = REDUCE i( INIT x = 0 FOR wa IN itab NEXT x = x + wa).


V. Example 3

Using a class reference – works because “write” method returns reference to instance object
From 7.40 and onwards

TYPES outref TYPE REF TO if_demo_output.

DATA(output) = REDUCE outref( INIT out = cl_demo_output=>new( )


text = `Count up:`
From 7.40 and onwards

FOR n = 1 UNTIL n > 11


NEXT out = out->write( text )
text = |{ n }| ).

output->display( ).

1. Numeric calculation assignment (7.54)


Assignment Before 7.54 Since 7.54
DATA(num) = 2. DATA(num) = 2.

+=, -=, *=, /= num = num + 1. num += 1.

2. String assignment (7.54)


Assignmen
Before 7.54 Since 7.54
t
DATA text TYPE string
DATA text TYPE string.
.
text = 'Concatenate'.
&&= text = 'concatenate'.
text &&= | Me!|.
text = text && | Me!|

3. ASSIGN … ELSE UNASSIGN (7.57)


Before 7.57 Since 7.57
DATA(field) = 'exists'. DATA(field) = 'exists'.
ASSIGN ('field') TO FIELD-
ASSIGN ('field') TO FIELD-SYMBOL(<fs>).
SYMBOL(<fs>).
IF <fs> IS ASSIGNED.
IF <fs> IS ASSIGNED.
...

ENDIF.
ENDIF.
ASSIGN ('nofield') TO <fs> ELSE
ASSIGN ('nofield') TO <fs>.
UNASSIGN.
IF <fs> IS ASSIGNED
AND sy-subrc = 0. "assigned on 2nd
IF <fs> IS ASSIGNED.
assign
...

ENDIF.
ENDIF.

4. ASSIGN struct-(comp) (7.57)


Before 7.57 Since 7.57

BEGIN OF tystruc, ASSIGN struc TO <struc>.


comp1 TYPE i, comp2 TYPE i, DATA(name) = 'COMP1'.
END OF tystruc
DO 1000 TIMES. "runs in approx.
50 ms
FIELD-SYMBOLS: <struc> TYPE any, <comp> ASSIGN <struc>-
TYPE any. (name) TO <comp>.
ENDDO.

ASSIGN struc TO <struc>. "Or alternatively


DATA(name) = '<struc>-comp1'.
DO 1000 TIMES. "Runs in approx.
DO 1000 TIMES. "runs in approx. 60 ms 50 ms
ASSIGN (name) TO <comp>. ASSIGN <struc>-(1) TO <comp>.
ENDDO. ENDDO.

5. RETURN [expr] for functional methods (7.58)


Before 7.58 Since 7.58

METHOD square. "IMPORTING root TYPE i METHOD square. "IMPORTING root TYPE i
"RETURNING VALUE(r) TYPE i. "RETURNING VALUE(r) TYPE i.
DATA square type i. TRY.
TRY. RETURN ipow( base = root exp = 2 ).
square = ipow( base = root exp = 2 ). CATCH cx_sy_arithmetic_error.
CATCH cx_sy_arithmetic_error. RETURN 0.
square = 0. ENDTRY.
ENDTRY.
ENDMETHOD.
r = square.
ENDMETHOD.

6. Data Types
New Data
Version Description
Type
 8-byte integers with signs
 Initial value: 0
INT8  Value range: -9,223,372,036,854,775,808
7.50 to +9,223,372,036,854,775,807
 Output length: 20
(ABAP & DDIC)

 Time stamp (exact to 100 ns)


 Initial value: 0
 Value range: 0001-01-
UTCLONG 01T00:00:00.0000000 to 9999-12-
7.54 31T23:59:59.9999999
(ABAP & DDIC)  Valid Places: 27

 Decimal floating point number


DECFLOAT16  Initial value: 0
7.54  Valid Places: 16
(ABAP[7.02] &
DDIC)
 Decimal floating point number
 Initial value: 0
7.54 DECFLOAT34
 Valid Places: 34
(ABAP[7.02] &
DDIC)

 Date in internal format of database


DATN  Initial value: 0 (DATS has initial value
7.54 00000000)
(DDIC)

 Time in internal format of database


TIMN  Initial value: 0 (TIMNS has initial value
7.54 000000)
(DDIC)

 Geometric data in EWKB representation


GEOM_EWKB  Initial value: Empty string
7.54
(DDIC)

7. Enumerated Types (7.51)

Syntax

TYPES BEGIN OF ENUM enum_type [STRUCTURE struc] [BASE TYPE dtype].


TYPES val1 [VALUE IS INITIAL],
TYPES val2 [VALUE val],
TYPES val3 [VALUE val],
...
TYPES END OF ENUM enum_type [STRUCTURE struc].

Description

Defines a list of allowed values.


Description

Defines a list of allowed values.

Example

Syntax checker flags invalid assignment:

TYPES: BEGIN OF ENUM planet,


mercury,
venus,
earth,
mars,
jupiter,
saturn,
uranus,
neptune,
END OF ENUM planet.

DATA planet type planet.

planet = earth.
planet = Nebula. "Syntax error: Field "NEBULA" is unknown

8. Virtual Sort (7.52)


Syntax

cl_abap_itab_utilities=>virtual_sort( IMPORTING IM_VIRTUAL_SOURCE


IM_FILTER_INDEX
RETURNING RT_VIRTUAL_INDEX )

Description

Description

For the given source table(s) and filter criteria a structure of index numbers is returned.
These index numbers are in the required order to effectuate the requested sort. This
index structure can be used to create a new (combined) sorted table while leaving the
original table(s) unsorted.

Examples

Single Table

For full example see class cl_demo_virtual_sort_simple.

ITAB
CO CO CO CO
L1 L2 L3 L4
6 4 G I
1 7 D F
6 9 A B
2 4 H B
1 4 A H
4 3 I J
10 8 E E
2 1 E D
9 5 C G
1 1 G B
DATA(v_index) = cl_abap_itab_utilities=>virtual_sort(
im_virtual_source = VALUE #(( source = REF
#( itab )
components = VALUE #( ( name = 'col1' ) (
name = 'col2' )
) ) ) ).
"Result: v_index = (10, 5, 2, 8, 4, 6, 1, 3, 9,
7)

DATA sorted_tab TYPE itab. "Sort by COL1, COL2 Ascending


sorted_tab = VALUE #( FOR idx IN v_index ( itab[ idx ] ) ).

COL1 COL2 COL3 COL4


1 1 G B
1 4 A H
1 7 D F
2 1 E D
2 4 H B
4 3 I J
6 4 G I
6 9 A B
9 5 C G
10 8 E E

v_index = cl_abap_itab_utilities=>virtual_sort(
im_virtual_source = VALUE #(
( source = REF #( itab )
components = VALUE #(
( name = 'col3'
astext = abap_true
descending = abap_true )
( name = 'col4'
astext = abap_true
descending = abap_true ) )
) ) ).
"Result: v_index = (6, 4, 1, 10, 7, 8, 2, 9, 5, 3)

sorted_tab = VALUE #( FOR idx IN v_index ( itab[ idx ] ) ).


"Sort by COL3, COL4 Descending

COL1 COL2 COL3 COL4


4 3 I J
2 4 H B
6 4 G I
1 1 G B
10 8 E E
2 1 E D
1 7 D F
9 5 C G
1 4 A H
6 9 A B

Two tables
For full example see class cl_demo_virtual_sort_combined.
ITAB1 ITAB2
COL1 COL2 COL1 COL2
0 0 X X
1 1 X X
1 1 Y Y
1 1 X Y
0 0 X X
1 0 Y Y
1 0 X Y
1 0 X Y
0 0 Y X
1 1 Y Y

v_index = cl_abap_itab_utilities=>virtual_sort(
im_virtual_source = VALUE #(
( source = REF #( itab1 )
components = VALUE #( ( name = 'col1' )
( name = 'col2' ) ) )
( source = REF #( itab2 )
components = VALUE #( ( name = 'col1'
astext = abap_true
descending = abap_true )
( name = 'col2'
astext = abap_true
descending = abap_true ) ) )
) ).
"Result: v_index = (9, 1, 5, 6, 7, 8, 3, 10, 4, 2)

TYPES: BEGIN OF test_line,


col11 TYPE i,
col12 TYPE i,
col21 TYPE string,
col22 TYPE string,
END OF test_line,
test_tab TYPE STANDARD TABLE OF test_line WITH EMPTY KEY.
DATA sorted_tab1 TYPE itab1.
sorted_tab1 = VALUE #( FOR idx IN v_index ( itab1[ idx ] ) ).
DATA sorted_tab2 TYPE itab2.
sorted_tab2 = VALUE #( FOR idx IN v_index ( itab2[ idx ] ) ).

FINAL(comb_tab) = VALUE test_tab( FOR i = 1 UNTIL i > 10


( col11 = sorted_tab1[
i ]-col1
col12 = sorted_tab1[
i ]-col2
col21 = sorted_tab2[
i ]-col1
col22 = sorted_tab2[
i ]-col2 ) ).

COL11 COL12 COL21 COL22


0 0 Y X
0 0 X X
0 0 X X
1 0 Y Y
1 0 X Y
1 0 Y Y
1 1 Y Y
1 1 Y Y
1 1 X Y
1 1 X X

9. Indicators (7.55)

Syntax

TYPES dtype TYPE struct WITH INDICATORS ind [{TYPE type}]. […AS
BITFIELD from 7.56]

UPDATE dbtab FROM TABLE itab INDICATORS [NOT] SET STRUCTURE set_ind.

Description

When used with “TYPES” it adds a component ind at the end of the structure struc the
same number of first-level components.

This can be used together with UPDATE dbtab to only update the components flagged
for update.

Example

For full example see class cl_demo_update_set_indicator.

DB table DEMO_UPDATE:
I COL COL COL COL
D 1 2 3 4
A 1 10 100 0
B 2 20 200 0
C 3 30 300 0
D 4 40 400 0
E 5 50 500 0
F 6 60 600 0

TYPES ind_wa TYPE demo_update WITH INDICATORS col_ind


TYPE abap_bool.
DATA ind_tab TYPE TABLE OF ind_wa.

ind_tab = VALUE #(
( id = 'D' col2 = 7777 col_ind-col2 = abap_true )
( id = 'E' col3 = 8888 col_ind-col3 = abap_true )
( id = 'F' col4 = 9999 col_ind-col4 = abap_true ) ).

UPDATE demo_update FROM TABLE _tab INDICATORS


SET STRUCTURE col_ind.

ind_tab:
ID COL1 COL2 COL3 COL4 COL_IND
D 0 7777 0 0 X
E 0 0 8888 0 X
F 0 0 0 9999 X

DB table DEMO_UPDATE:
I
COL1 COL2 COL3 COL4
D
A 1 10 100 0
B 2 20 200 0
C 3 30 300 0
D 4 7777 400 0
E 5 50 8888 0
F 6 60 600 9999

10. MOVE-CORRESPONDING … EXPANDING NESTED


TABLES KEEPING TARGET LINES (7.56)

Example

For full example see class cl_demo_move_crrspndng_itab.

Given 2 internal tables

MOVE-CORRESPONDING itab1 TO itab2.


MOVE-CORRESPONDING itab1 TO itab2 KEEPING TARGET LINES.
MOVE-CORRESPONDING itab1 TO itab2 EXPANDING NESTED TABLES.
MOVE-CORRESPONDING itab1 TO itab2 EXPANDING NESTED TABLES
KEEPING TARGET LINES.
11. LOOP AT … STEP n (7.57)

Description

STEP can be used with LOOP, FOR, APPEND, DELETE, INSERT, VALUE and NEW.
For LOOP and FOR, if n is negative, then the loop starts at the last line of the table and
goes backwards with a step size of n.

Example

For full example see class cl_demo_loop_at_itab_using_stp.

DATA itab TYPE HASHED TABLE OF i WITH UNIQUE KEY table_line


WITH NON-UNIQUE SORTED KEY sec_key
COMPONENTS table_line
##TABKEY[PRIMARY_KEY][SEC_KEY].

itab = VALUE #( ( 4 ) ( 3 ) ( 7 ) ( 11 ) ( 1 ) ( 5 ) ).

LOOP AT itab ASSIGNING <fs> STEP 2.


tabix = sy-tabix.
result = VALUE #( BASE result ( tabix = tabix value = <fs> )
).
ENDLOOP.
"result = [(0, 0, 0) (4, 7, 1)] Note tabix is always 0.

LOOP AT itab ASSIGNING <fs> STEP -2.


tabix = sy-tabix.
result = VALUE #( BASE result ( tabix = tabix value = <fs> )
).
ENDLOOP
"result = [(0, 0, 0) (5, 11, 3)] Note tabix is always 0.
12. CORRESPONDING Operator with MAPPING and DEFAULT (7.58)

Syntax

CORRESPONDING #( struc1 MAPPING t1 = [s1] DEFAULT expr…)

Explanation

Where struc1 is the source structure and s1 is a component of the source structure.

When s1 is supplied the result of the expression (expr) is only assigned if s1 is initial.
Else s1 is assigned.

When s1 is not supplied then the result of the expression is always assigned regardless
of whether s1 is initial.

Example

For full example see class cl_demo_corr_op_map_default.

DATA: BEGIN OF struc1,


id1 TYPE i,
a TYPE string,
b TYPE string,
c TYPE i,
d TYPE string,
e TYPE i,
END OF struc1.

DATA: BEGIN OF struc2,


id2 TYPE i,
a TYPE string,
b TYPE string,
c TYPE i,
d TYPE string,
z TYPE i,
END OF struc2.

"Empty internal table


DATA itab1 LIKE TABLE OF struc1 WITH EMPTY KEY.

"Filling structure
struc1 = VALUE #( id1 = 1 a = 'a' b = '' c = 2 d = '' e = 0 ).
struc2 = CORRESPONDING #(
struc1 MAPPING
id2 = id1
b = b DEFAULT 'ha' && 'llo'
c = c DEFAULT 1 + 5
d = d DEFAULT VALUE #( itab1[ 1 ]-d DEFAULT
'hi' )
z = DEFAULT 9.
struc2:
Component Value
ID2 1
a a
b hallo src b is initial
c 2 src c is not initial
itab1[1]-d invalid. Would shortdump without
d hi
DEFAULT
z 9 src e is initial

You might also like