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: 
<<06: Unstructured returns, sorting and performance08: Data types, Operation table, ....... >>

Hello everybody,

due to work on other things I had to stopped my blog series on BPath quite some time ago with lesson 6. Unfortunately there are - beside several nice additional features - some features pending which are quite useful when working with BPath. So I will give an insight on the main features for designing BPath statements here and may continue with additional features in some further lesson.

The old blog series was published under my personal blog, but starting with this blog I moved the blogs to the Webclient UI Framework blog as BPath is actually a feature realized together with BOL / GenIL.

All described features require BPath of version 2.3 at least, but I suppose there is hardly a lesser version out somewhere.

Before we take a look on the main part of this lesson, we do a brief look on a new feature which in a way rounds up the performance considerations described in lesson 6.

Parser Reuse

This is a change to improve performance in certain use cases.

When started, the parser has to build up the parse table and when the parser receives the source code a preparsing is done. The first step is unnecessary for all but the first execution if several BPATH statements are executed in a sequence, the second step is unecessary in case the source code has not changed.

To allow a reuse of the parser object and consequently an omitting of the unecessary steps, the parser object might be instantiated under the control of the application and handed over to the corresponding BOL method as in the following ABAP example:

Data MyParser type ref to CL_WCF_BPATH_PARSER.
create object MyParser.
LV_SOURCECODE = 'SearchResFlightRel/*$'.
MyResult1 = lv_object->GET_PROPERTIES_BY_BPATH(
  IV_BPATH_STATEMENT = LV_SOURCECODE
  IO_PARSER          = MyParser ).
MyResult2 = lv_other_object->GET_PROPERTIES_BY_BPATH( 
  IV_BPATH_STATEMENT = LV_SOURCECODE 
  IO_PARSER          = MyParser ).

The second call reuses the parsing tables of the first call and - since the source code is the same - the preparsing tables also.

Model Check Mode

There was demand for a mode which does not execute the query as such but ...

  • checks syntax
  • checks validity of used relations and attributes against model
  • returns the (empty) data structure

Till version 2.2 the parser knew two modi, 1 which checks the syntax of the source code (and does some preparsing) and 3 which executes the query. Now there is a new mode 2, which attempts to fulfill above requirements. Please note that the modi 2 and 3 do a preparsing before execution, this means internally a run in mode 1 is executed before.

Since mode 2 runs against the model and not against actual objects/collections, the object name (plus namespace which is otherwise defaulted with '') is required instead of object or collection instance. An example syntax looks as follows:

DATA: lv_bol_core TYPE REF TO cl_crm_bol_core.
lv_bol_core = cl_crm_bol_core=>get_instance( ).
MyResult = lv_bol_core->GET_PROPERTIES_BY_BPATH(
  IV_BPATH_STATEMENT = LV_SOURCECODE
  IV_BASE_NAMESPACE  = ''
  IV_BASE_OBJECTNAME = 'UIFSearchResFlight'
  IV_EVAL_MODE = 2 ).

Please note that the GET_PROPERTIES_BY_BPATH of BOL core is called, the above can not work on an instantiated BOL object or collection, as the signature of the corresponding methods do not have a IV_BASE_OBJECTNAME parameter. Btw, you may call GET_PROPERTIES_BY_BPATH on the BOL core directly also in execution mode (default or 3). You have to handover the object/collection using the IV_BASE_ENTITY or IV_BASE_COLLECTION parameter then.

Some technical comments to the mode:

  • the syntax check is the same in all three modi
  • in case the return type is a table, the table will contain exactly one row. The fields in this row should be empty except the cases described below. The same applies to returned structures.
  • The relation check as well as the data structure return has some limitations due to the flexibility of GenIL as well as BPATH:
    • The parent relation leads to an unambiguous object type only with an instantiated object. As for the model the relation may be ambiguous (the parent of an address might be a contact or a business partner). Since it is unclear with which object type to proceed and whether the relations / attribute accesses which are following are correct, the model checks stops whenever a parent relation is used with more then 1 possible parent. It is recommended to make the parent relation unique in these cases (see next chapter).
    • The return type of some functions may be unknown at design time, e.g. in the following example:
      ~*/SearchResFlightRel{!RetVal:=if(@CONNID=14,1,"Hello")}
      At run time the type is determined with the first access.
    • Dereferenced targets on the left side of an assignment are leading to fields where the name is not known at design time, as in:
      ~*/SearchResFlightRel{!1:="F_"+@FLDATE;!1^!=1}
      The model check generates a field named 'UNKNOWNFIELDNAME n ' into the result structure, the type information should be correct. Note that several dereferenced assignments will lead to several entries as above and that one dereferenced assignment may lead to more than one added field at run time but only to one within model check.
    • Dereferenced targets on the right side of an assignment are leading to fields where the type is not known at design time, as in:
      ~*/SearchResFlightRel{!1:=if(@CONNID=14,"CONNID","FLDATE");!Ret=!1^!}
      In these cases the model check creates a field with type string containing the value: 'UNKNOWN DATATYPE'.

To use the syntax check or model check the exceptions caused by snytax errors have to be caught.

Parser Exceptions

Exception
Syntax Check
Model Check
Execution
Description
Example
CX_CRM_GENIL_MODEL_ERROR2
X
attribute unknown
~*/./@NoAttribute
CX_CRM_UNSUPPORTED_RELATION
X
X
relation unknown
~*/PlumpaQuatsch
CX_WCF_BPATH_PARSING_ERROR
X
X
X
General parsing error
~*/+-*^1

The CX_WCF_BPATH_PARSING_ERROR exception provides more information with the TEXT_ID according to the following table:

TextID
1
2
3
Description
CX_WCF_BPATH_PARSING_ERROR
X
X
X
Current token is not allowed at this place
(possible entries will be listed)
Example: ~*/$
INCOMPATIBLE_OPERATION_TYPES
X
X
operation is not supported with
specified types
Example: ~*/.{!A=Today()*"Hello"}
NUMBER_OF_PARAMS_MISSMATCH
X
X
Number of parameters in statement
does not match function declaration
Example: ~*/.{!A=Upper()}
PARAMETER_WRONG
X
X
Parameter type does not match
function declaration
Example: ~*/.{!A=Upper(1)}
PARENT_OBJECT_NAME_INCORRECT
X
*)
specified parent object name is incorrect
Example: ~*/.._NoNsEnSe
PARENT_REL_NOT_UNAMBIGOUS
X
*)
parent is either not there (we are already
on root) or not unambiguous
Example: ~*/..
UNSUPP_TYPE_IN_TARGET_STRUCT
X
X
creation of a target of used type is
not supported
UNSUPPORTED_FUNCTION
X
X
There is no such thing as a function
with this name
Example: ~*/.{!A=Test(1)}

*) both dumps do not appear in code execution (more exactly PARENT_REL_NOT_UNAMBIGOUS only if no parent was found), but it is likely that the code is not fitting to the object structures and consequently it can not be guaranteed that the code is executed without problems and/or dumps.

Typically the dumps returns the code position as source code extract, where the program pointer is visualized with '_^_'.

Attributed parent relation

To avoid the problems described above, the parent relation ('..') may have an attribute which should hold the object name of the parent as in the following (hardly usable) example:

~*/SearchResFlightRel/FlightBookRel/.._UIFFlight/*$
Code Example 33, .._OBJECT, attributed parent relation

Please note, that this is not a syntax change, for BPATH the relation name is '.._UIFFlight'. The object name of the parent object is used to identify the object on which the check is proceeded during model check. As for normal statement execution, the object name information is ignored.

Attribute Longtext

Using a double @ as prefix, BPATH will return the result of the GET_TEXT method as result, instead of the attribute directly. This is the longtext, if available, otherwise an empty string. Result type will be always string.

~*/SearchResFlightRel/FlightBookRel{!A=@@CUSTTYPE;!B=@@CARRID;!D=@@CLASS;!E=@@FORCURKEY}$
Code Example 34, @@CARRID, attribute longtext

That's it for today. The content of the next lesson has to be assembled first. The remaining part of version 2.3 contains rather technical stuff. And with version 2.4 it gets really complicated, and also a bit in pretty unexplored universes.

Best regards, Juergen

14 Comments