Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
horst_keller
Product and Topic Expert
Product and Topic Expert

I just started with blogging about important ABAP News for ABAP 7.50 and - whoosh - I am asked for CDS news. OK then, a blog about the new CDS table functions (but hey, I have also real work to do).

ABAP CDS is the ABAP-specific implementation of SAP's general Core Data Services (CDS) concept. ABAP CDS is open, meaning that you can use it on all database platforms supported by SAP. And yes, CDS views with parameters, introduced with ABAP 7.40, SP08, are supported by all databases with ABAP 7.50.

While openess has its merits, developers working only on the HANA platform might miss some code-push-down capabilities in ABAP CDS. One of these missing capabilities was the usage of database functions in data models built with CDS. Up to now, only CDS views were available. With ABAP 7.50 ABAP CDS also supports CDS table functions as CDS entities. Two problems had to be solved:

  • how to make table functions that are implemented natively on the database callable in CDS
  • how to manage the life cycle of native table functions to be constantly available to a data model built on the application server

Two questions, one answer: ABAP Managed Database Procedures (AMDP), introduced with ABAP 7.40, SP05. AMDP is a class-based framework for managing and calling stored procedures as AMDP procedures in AS ABAP. For the time being, AMDP is supported by the HANA platform only. Before ABAP 7.50, AMDP knew only database procedures without a return value. With ABAP 7.50, AMDP supports also database functions with a tabular return value. And the main purpose of these AMDP-functions is the implementation of CDS table functions. They cannot be called as functional methods in ABAP, while AMDP-procedures can be called as ABAP methods.

In order to create a CDS table function, you have two things to do:

  • define it in a CDS DDL source code,
  • implement it in an AMDP method with a  return value.

Both steps are possible in ADT (Eclipse) only.

The definition in CDS DDL is straight forward, as e.g.:


@ClientDependent: true
define table function DEMO_CDS_GET_SCARR_SPFLI_INPCL
  with parameters @Environment.systemField: #CLIENT
                  clnt:abap.clnt,
                  carrid:s_carr_id
  returns { client:s_mandt; 
            carrname:s_carrname;
            connid:s_conn_id;
            cityfrom:s_from_cit;
            cityto:s_to_city; }
  implemented by method
    CL_DEMO_AMDP_FUNCTIONS_INPCL=>GET_SCARR_SPFLI_FOR_CDS;

A CDS table function has input parameters and returns a tabular result set, that is structured as defined behind returns. You see, that the annotation @ClientDependent can be used to switch on an automatic client handling for Open SQL. You also see a new parameter annotation @Environment.systemField, also available for views, that is handled by Open SQL by implicitly passing the value of sy-mandt to that parameter. Such a CDS table function is a fully fledged CDS entity in the ABAP CDS world and can be used like a CDS view: It is a global structured data type in the ABAP Dictionary and it can be used as data source in Open SQL's SELECT and in CDS views. Behind implemented by method you see the AMDP class and method where the function has to be implemented in.

After activating the CDS table function you can go on implement the functional AMDP method in an AMDP class, that is a class with the marker interface IF_AMDP_MARKER_HDB. An AMDP method for a CDS table function must be a static functional method of a static AMDP class that is declared as follows:


CLASS-METHODS get_scarr_spfli_for_cds

              FOR TABLE FUNCTION demo_cds_get_scarr_spfli_inpcl.

The declaration is linked directly to the CDS table function. The parameter interface is implicitly derived from the table function's definition! Implementation looks like you might expect it:


  METHOD get_scarr_spfli_for_cds
        BY DATABASE FUNCTION FOR HDB
        LANGUAGE SQLSCRIPT
        OPTIONS READ-ONLY
        USING scarr spfli.
    RETURN SELECT sc.mandt as client,
                  sc.carrname, sp.connid, sp.cityfrom, sp.cityto
                  FROM scarr AS sc
                    INNER JOIN spfli AS sp ON sc.mandt = sp.mandt AND
                                              sc.carrid = sp.carrid
                    WHERE sp.mandt = :clnt AND
                          sp.carrid = :carrid
                    ORDER BY sc.mandt, sc.carrname, sp.connid;
  ENDMETHOD.

Nothing really new but BY DATABASE FUNCTION and that  READ-ONLY is a must. Implementation is done in native SQLScript for a HANA database function. And native means, you have to take care for the client. Automatic client handling is done on the Open SQL side only. Of course, a real CDS table function would do more HANA specific things (e.g. wrapping a HANA function) than a simple join as shown in the simple example here! A join you can code also in Open SQL or in a CDS View.

Speaking about Open SQL, last but not least, the usage of our CDS table function as data source of SELECT in an ABAP program:


  SELECT *
        FROM demo_cds_get_scarr_spfli_inpcl( carrid = @carrid )
        INTO TABLE @DATA(result)
        ##db_feature_mode[amdp_table_function].

Not different to an access of a CDS view with parameters. But you must switch off a syntax warning with a pragma to show that you are sure what you are doing, namely coding for HANA only.

Note that we don't need to pass the client explicitly. This is because the according parameter was annotated for implicit passing of the respective system field. Since the CDS table function was annotated as client dependent, the result set of Open SQL's SELECT does not contain a client column - as it is for CDS views. Furthermore all lines of the result set, that do not belong to the current client are implicitly removed. That's why the return list of a client dependent table function must have a client column.  For the sake of performance, the native implementation should deliver only lines of the current client. But since it is native it has to take care for that itself. Confusing? That's when open and native meet. In ABAP, normally the DBI does this handling for you. But this is not possible here.

For more information see

57 Comments
afordham
Participant
0 Kudos
I would like to access data from ABAP in a different schema on the same HANA database.  This will be used to drive a UI that needs to have capabilities like fuzzy search.

If I have to retrieve the data using a CDS table function/AMDP pairing and I need to use annotations like @Search.fuzzinessThreshold, will this involve the database copying all the data from the other schema before performing the search?  The ADMP itself appears to return everything rather than passing the restrictions down (with the exception of parameters).
vidlak
Explorer
0 Kudos


Hello,

is it possible to use correlated subquery in CDS like in ABAP. We would replace ABAP statement with correlated subquery in OData service implementation by OData based on CDS but I cannot find solution with similar performance.

ABAP (old)

select * from A as t1 where date = ( select MAX(date) from A as t2 where t2~key = t1~key )

CDS (new) 2 steps below - which is slow:

1. CDS_A

select key MAX(date) from table A group by key

2. CDS

select * from A as t1 inner join CDS_A as t2 on t1~key = t2~key and t1~date = t2~date

thanks

dharun_kumar
Explorer
0 Kudos
horst.keller Thanks for the informative Blog !

Have a clarification. In AMDP class, we can have multiple Exporting Table Result Sets. Whereas as far as I tried, CDS Table Functions can have only single Return Parameter that too the Structure can be defined only with type Data Elements. Would be great to know if there is any workaround to return multiple Tables from CDS Table Functions.

Thanks in Advance !
jmalla
Contributor
0 Kudos

Hi horst.keller – I am trying to run a table function on our ECC system which is 7.50 SPS 11 on IBM DB6 on AIX

 

However, even when I try to run the SAP table function, I get the error:

"The addressed database does not support the feature AMDP_TABLE_FUNCTION."

So I am not sure table functions and AMDP is supported in our system – but I thought that from ABAP 7.50, the capability is not limited to systems with a Hana database.

Thanks,

Jay

0 Kudos
Hello Horst,

Thanks a lot for a detailed Blog.

I created Table function using the above steps and wrapped it in CDS view using table Function as a data source for the View. Everything is working fine when I am executing the CDS View and the desired output is being fetched.
But when I try to fetch data using SQL from HANA database directly(with HANA DB user) using "SCHEMA"."SQLVIEWNAME" for this CDS view , the output is blank.

Note: For CDS views created without using the Table function as data source, even the SQL query from HDB is giving the same result as CDS View.

Could you please help me in understanding what might be the problem?

Thanks and Regards,

Alex
praveen_gupta2
Explorer
0 Kudos

Hell Horst,

Thanks for sharing such a nice blog.

Just a simple question to you on select statement in AMDP class.

Can we select data from association of CDS view inside AMDP class ??

My scenario is to use standard CDS view entity “I_PLANNEDORDER” inside AMDP class,

now i need some data from same view as well as from published association of this view like “_Material” “_MRPPlant”.

In open SQL we can read association data like this “\_MATERIAL.(ColName) but how can we use similar statement in AMDP to read associated columns.

Your help is much appreciated.

 

Thanks & Regards,

Praveen Gupta

klink_daniel
Explorer
0 Kudos

Hello Horst, hello Community Members,

I would like to implement Unit conversion based on material specific information from MARM table.

I am currently able to achieve this by using table function implemented by AMDP class which is returning a conversion factor for each material and combination of source and target unit, which can then be multiplied with the original quantity in a CDS view.

However, what would be much nicer is buliding this similar to the built-in functions "unit_conversion" and "currency_conversion" which I can use inside the CDS view and pass all information including original quantity.

If possible, can you please point me in the right direction how to implement this?

Thanks,
Daniel