Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
<<03: Functions and Assignments05. Sub, String,Get-function(s), global variables >>

Hello,

we are already at the fourth lesson of our course on BPath. With the third lesson (BPath. Lesson 03: Functions and Assignments) we entered the world of assignments, which we further discover with this contribution.

Our Example Data Model

Before we kneel ourselves even more into BPath examples a small picture showing the data structures we run our example BPath statements against. The examples are basically using the colorized objects and relations:

Enhanceable Structures, Aggregations, Dereferencation

Within the last lessons you learned how to declare the return type of your BPath query and you also learned how to assign data to target fields. Now you might ask yourself what happens, when you use a target field which is actually not existing. Well, good question, easy answer: It is added. But only if you use enhanceable structures:

~*CRMS_BOL_UIF_TRAVEL_BOOK_KEY/SearchResFlightRel{!Newfield=Index()}/FlightBookRel/*$
Code Example 18,~*STRUC, enhanceable structure

Mind the star! If you place a star between tilde and structure name you are able to add artificial fields to the structure. The new field will be added as soon as it is used as assignment target somewhere in the BPATH. The type of the new field follows the type of the right side of the assignment. If the new field is used a second time the field will correspond to the already added field.

In case you do the same coding against a non-enhanceable structure (by omitting the star), you will receive an error message.


A special type of enhanceable structure is the empty strcuture:

~*/SearchResFlightRel{!Newfield=Index()}/FlightBookRel/$
Code Example 19, ~*/, Empty Struc

As long as there is no attribute added, the structure will exist only virtually. If there are attributes added, the structure is created from scratch.
Be carefully with the * / move-corresponding operation in this respect, since a move-corresponding to an empty structure makes no sense.

Coming to a different topic, accumulations and aggregations. You might argue that we have already built an aggregation within the last lesson. That's right, but there is one more point to capture:

~*/SearchResFlightRel{!VALUE=0}$/FlightBookRel{!VALUE:=!VALUE+1}/*
Code Example 20, Rel$/SecondRel, Accumulations

Did you notice the difference?

Now the dollar appears no more at the end, but after the first relation. Why that? Well, the dollar indicates when an entry has to be written to our return table. And now we do not want to write an entry for every booking we find, just for every flight.

Note, that all assignments are done on the way downward. This means the left assignment is done first and then the corresponding increment operations. But what, if we want to use the data coming from the subtree for calculations higher (e.g. calculating the average). Well this can not be done this way (actually I am still searching for a feasible way to make it possible and readable), but a solution is to do the calculation on the lower level and each calculation overwritten the former one, so the last one wins:

~*/SearchResFlightRel{!VALUE=0;!WEIGHT=0}$/FlightBookRel{!VALUE:=!VALUE+1;!WEIGHT:=!WEIGHT+(1000*@LUGGWEIGHT);!AVG=!WEIGHT%!VALUE}/*
Code Example 21, aggregations

In this example the test against division by zero can be omitted, since the calculation is only done, if value is at least 1, but in general this problem has to be kept in mind.

Again note, that for all aggregation assignments := has to be used.

Let us make BPath a bit more complicated and introduce dereferencation. This feature is mainly usable for transpositions, means exchanging columns and rows (storing row data in columns). So the feature might be pretty helpful if you want to export data Excel using a dynamic second dimension.

~*/SearchResFlightRel{!TEST="HALLO"}$/FlightBookRel{!CTX="PS"+INDEX();!CTX^!=@PASSNAME}/*
Code Example 22,* !x^!=, dereferencation

Here again the dollar moves to the front, to the SearchResFlightRel relation. Since otherwise the return structure is empty at this point, a test field is introduced. The second assignment block first fills the CTX field with a newly constructed field name as PS1, PS2, ... The second assignment takes the content of CTX dereferences it as target and fills it with the Passname of the current attribute structure. In our example one of the flights has about 450 bookings (probably a 747), so the fields PS1, PS2, ... PS450 would be added and filled to the return structure.

It is also possible to use dereferenation within a expression (with the read part), and it is also possible to dereference attribute fields (!TEST^@).

Performance has to be kept in mind here. First of all all new fields are added one by one. Secondly, as in our example where we return a table, the structure for row x (which has say 100 fields added) is not necessarily the same as for row x+1 (with 102 fields). Hence they can not be added to the same table. In fact a new table with the structure for row x+1 has to be constructed and all old entries have to be converted to this new structure. This might cause a performance problem in case the number of fields is constantly rising together with the row number.

Note that dereferencation typically uses assignments with "=", otherwise the content might be not cleared for the next row.

Object Retrieval

In case you have taken a look at the BOL interface definitions you might have noticed that GET_PROPERTIES_BY_BPATH is not the only method which is using BPath. There is a method called GET_RELATED_ENTITIES_BY_BPATH which is obviously also using BPath. Signature is pretty much similar, but instead a data reference it returns a reference to an IF_BOL_ENTITY_COL entity. In other words it returns a Business Collection (actually it returns a CL_CRM_BOL_ENTITY_COL). The sense should be straight forward; instead of returning the actual data, the source objects are collected.

Even though this functionality was there from the beginning, it was never enhanced as it counterpart GET_PROPERTIES_BY_BPATH. The basic functionality as filtering should work, some of the further enhancements as assignments have no expression on collections (as we can not dynamically construct objects). Some of the coming functionalities are also of no use when returning Business Collections.

Note, that from a syntax perspective there is no difference between bothcalls. Functionality related to data (as assignments) would be executed also with the GET_PROPERTIES call. This means the data as such is assembled internally, but afterwards never used.

For a demonstration of this functionality we use example 12 ( SearchResFlightRel/FlightBookRel[INDEX()<=(SIZE()%2)]/*$ 😞

DATA lv_bpath_result_col type  ref to IF_BOL_ENTITY_COL.
lv_sourcecode =
'SearchResFlightRel/FlightBookRel[INDEX()<=(SIZE()%2)]/*$'.
lv_bpath_result_col =  lv_result2->GET_RELATED_ENTITIES_BY_BPATH
( IV_BPATH_STATEMENT = lv_sourcecode ).

The next lesson covers a lot of functions including string functions and it introduces the possibility to start sub-queries. We also introduce GET() which allows another interesting usage of dereferencing.