Core Data Services (CDS) push business logic down to the SAP HANA database engine with extraordinary efficiency. However, certain enterprise business calculations cannot be expressed purely in declarative SQL:
CDS Virtual Elements solve this architectural challenge by allowing developers to define non-persisted, transient fields in a CDS Projection View that are calculated on-the-fly by an ABAP class via the SADL (Service Adaptation and Description Layer) framework.
| Evaluation Vector | Pure SQL Expression (CDS) | CDS Virtual Element (SADL Exit) | RAP Custom Query Provider |
|---|---|---|---|
| Execution Location | SAP HANA Database Engine | ABAP Application Server (Post-SQL) | ABAP Application Server (Full Query) |
| Procedural ABAP Logic | No (Declarative SQL only) | Yes (Full ABAP Cloud language) | Yes (Custom paging/sorting/filtering) |
| Pagination ($top / $skip) | Native HANA database pushdown | Native HANA database pushdown | Manually handled in ABAP code |
| Sorting & Filtering ($filter) | Directly filterable in SQL | Requires custom SADL filter transform | Parsed manually via EML request |
| Standard Recommendation | Default whenever possible | Recommended for calculated UI fields | Reserved for remote APIs / non-HANA data |
When an OData client or Fiori Elements app requests a page of 50 records from a projection view with a virtual element:
@ObjectModel.virtualElement: true.if_sadl_exit_calc_element_read~get_calculation_info on the calculation class. The method informs SADL which underlying database fields are needed for calculation.SELECT ... FROM view LIMIT 50 OFFSET 0 including the requested dependency fields.if_sadl_exit_calc_element_read~calculate. The ABAP method loops across the table in-memory and sets the virtual element values.CLASS zcl_calc_sales_criticality DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_sadl_exit_calc_element_read.
ENDCLASS.
CLASS zcl_calc_sales_criticality IMPLEMENTATION.
METHOD if_sadl_exit_calc_element_read~get_calculation_info.
" Crucial: Prevent N+1 select queries by requesting prerequisite fields
INSERT 'DELIVERYSTATUS' INTO TABLE et_requested_orig_elements.
ENDMETHOD.
METHOD if_sadl_exit_calc_element_read~calculate.
DATA(lt_original_data) = it_original_data.
LOOP AT lt_original_data ASSIGNING FIELD-SYMBOL(<row>).
ASSIGN COMPONENT 'DELIVERYSTATUS' OF STRUCTURE <row> TO FIELD-SYMBOL(<status>).
ASSIGN COMPONENT 'DELIVERYCRITICALITY' OF STRUCTURE <row> TO FIELD-SYMBOL(<crit>).
IF <status> IS ASSIGNED AND <crit> IS ASSIGNED.
CASE <status>.
WHEN 'C'. <crit> = 3. " Green (Delivered)
WHEN 'B'. <crit> = 2. " Yellow (Partially Delivered)
WHEN 'A'. <crit> = 1. " Red (Blocked / Delinquent)
WHEN OTHERS. <crit> = 0. " Grey
ENDCASE.
ENDIF.
ENDLOOP.
ct_calculated_data = CORRESPONDING #( lt_original_data ).
ENDMETHOD.
ENDCLASS.
Never execute SELECT SINGLE or external HTTP requests inside the calculate loop! If a client pages through 100 records, executing a SELECT inside the loop results in 100 sequential roundtrips. Always register prerequisite fields in get_calculation_info or perform a single bulk FOR ALL ENTRIES lookup outside the row iteration.
get_calculation_info causes calculate to receive empty or unassigned fields when the Fiori UI does not explicitly include that column in the table view.calculate as a single-record processor rather than a bulk internal table processor severely degrades throughput.Generate CDS annotations, SADL calculation exits, and unit test doubles with our interactive tool.
Launch Virtual Elements Architect ⚡ Get Architecture Suite (80% Off)