Introspecting CQN Queries
API to introspect CDS QL statements in Java
Content
Introduction
The CDS Query Introspection API allows to extract key values and information on the CDS entities in references of CQN statements.
The CqnAnalyzer can be constructed from a CDS model:
import com.sap.cds.ql.cqn.CqnAnalyzer;
CdsModel cdsModel = context.getModel();
CqnAnalyzer cqnAnalyzer = CqnAnalyzer.create(cdsModel);
Usage
Given the following CDS model and CQL query:
entity Orders {
key OrderNo : String;
Items : Composition of many OrderItems on Items.parent = $self;
...
}
entity OrderItems {
key ID : Integer;
book : Association to Books;
...
}
Find this source also in cap/samples.
--CQL query
SELECT from Orders[OrderNo = '42'].items[ID = 1]
the corresponding CQN statement can be analyzed using the analyze
method of the CqnAnalyzer
:
CqnStatement cqn = context.getCqn();
AnalysisResult result = cqnAnalyzer.analyze(cqn.ref());
Resolving CDS Entities
Based on the AnalysisResult
, information on the CDS entities can be accessed through the Reflection API:
CdsEntity order = result.rootEntity(); // Orders
CdsEntity item = result.targetEntity(); // OrderItems
Extracting Filter Values
Extracting filter values from CQN statements is supported for noncomplex predicates where the values can be unambiguously determined.
The key values of the entities can be extracted as a map using the rootKeys
and targetKeys
method of the AnalysisResult
object:
Map<String, Object> rootKeys = result.rootKeys();
String orderNo = (String) rootKeys.get("OrderNo"); // 42
Map<String, Object> targetKeys = result.targetKeys();
Integer itemId = (Integer) targetKeys.get("ID"); // 1
To extract all filter values of the target entity including nonkey values, the targetValues
method can be used:
Map<String, Object> filterValues = result.targetValues();
For CqnSelect
, CqnUpdate
, and CqnDelete
, values can also be extracted from the statement’s where
condition:
--CQL query
SELECT from Orders[OrderNo = '42'].items where ID = 3 and status = 'open'
CqnSelect select = context.getCqn();
AnalysisResult result = cqnAnalyzer.analyze(select);
Map<String, Object> targetKeys = result.targetKeys();
Integer itemId = (Integer) targetKeys.get("ID"); // 3
Map<String, Object> filterValues = result.targetValues();
String status = (String) filterValues.get("status"); // 'open'
Using the Iterator
The methods prefixed with root
and target
access the first resp. last segment of the CQN statement’s ref.
If the ref has more than two segments, such as:
--CQL query
SELECT from Orders[OrderNo = '42'].items[ID = 1].book
the segment items
can be analyzed using an iterator:
Iterator<ResolvedSegment> iterator = result.iterator();
CdsEntity order = iterator.next().entity();
CdsEntity item = iterator.next().entity();
CdsEntity book = iterator.next().entity();
or a reverse iterator starting from the last segment:
Iterator<ResolvedSegment> iterator = result.reverse();
CdsEntity book = iterator.next().entity();
CdsEntity item = iterator.next().entity();
CdsEntity order = iterator.next().entity();
In the same way, also the filter values for each segment can be extracted using the values
and keys
method instead of the entity
method.