Skip to content
Open
Changes from 13 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 153 additions & 4 deletions java/working-with-cql/query-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ In the [CDS Query Language (CQL)](/cds/cql) builder, the lambda expression `o ->
To target components of a structured document, we recommend using path expressions with infix filters.
:::


### Filters {#target-entity-filters}

Besides using infix filters in path expressions, the `Select`, `Update`, and `Delete` builders support filtering the [target entity set](#target-entity-sets) via the `where` method. Using `where` is equivalent to defining an infix filter on the last segment of a path expression in the statement's `from` / `entity` clause. For statements that have both, an infix filter on the last path segment and a `where` filter, the resulting target filter is the conjunction (`and`) of the infix filter and the `where` filter.
Expand Down Expand Up @@ -1309,11 +1308,67 @@ The Query Builder API supports using expressions in many places. Expressions con

### Entity References {#entity-refs}

Entity references specify entity sets. They can be used to define the target entity set of a [CQL](../../cds/cql) statement. They can either be defined inline using lambda expressions in the Query Builder (see [Target Entity Sets](#target-entity-sets)) or via the `CQL.entity` method, which is available in an _untyped_ version as well as in a _typed_ version that uses the generated [model interfaces](../cqn-services/persistence-services#model-interfaces). The following example shows an entity reference describing the set of *authors* that have published books in the year 2020:
Entity references specify entity sets and can define the target entity set of a [CQL](../../cds/cql) statement or serve as an argument for event handlers.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use active voice instead of passive voice. Change "They can be used" to "You can use them" for better clarity and directness.

Suggested revision:

Entity references specify entity sets and you can use them to define the target entity set of a [CQL](../../cds/cql) statement or serve as an argument for event handlers.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sentence structure is awkward and uses passive voice. Consider revising to:

"Entity references specify entity sets. You can use them to define the target entity set of a CQL statement or as arguments for event handlers."


A reference consists of _segments_ that define the path from the entity's root to a certain part of it. Each segment has the _identifier_ with the name of the entity or an element and an optional filter _predicate_. These predicates might include other references. The references are not bound to the particular model and are not checked against it while they are being built.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use active voice instead of passive voice. Change 'References are not bound to the particular model and are not checked against it while they are being built' to 'The system does not bind references to a particular model and does not check them against it during construction.'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use present tense instead of future tense. The phrase "are not checked against it while they are being built" should be "are not checked against it during construction" to maintain present tense throughout.

Suggested revision:

The references are not bound to the particular model and are not checked against it during construction.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence uses passive voice and is unclear. Consider revising to:

"The system does not bind references to a particular model and does not check them against it while building them."


References are either _absolute_ or _relative_. Absolute references always have the fully qualified name of the type in their first segment.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use active voice instead of passive voice. Change 'References are either absolute or relative' to 'References can be either absolute or relative' to make it more active and direct.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use active voice instead of passive voice. Change "References are either absolute or relative" to "References can be either absolute or relative" to make the sentence more direct and engaging.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use active voice instead of passive voice. Change "References are either absolute or relative" to "References can be either absolute or relative" to make the sentence more direct and engaging.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use active voice instead of passive voice. Change 'References are either absolute or relative' to 'References can be either absolute or relative' to make it more active and clear.


The simplest kind of absolute reference is a reference to the entity set, for example, to all books.

```java
import com.sap.cds.ql.CQL;
Books_ books = CQL.entity(Books_.class); // {"ref":["sap.capire.bookshop.Books"]}

StructuredTypeRef ref = bookWithId.asRef(); // or CqnStructuredTypeRef which is a cleaner equivalent type
```

The method `asRef()` seals the reference and makes it immutable.

Relative references point to the elements of the entity, for example, the title of a book, where the type is known in advance or specified elsewhere. In CQL statements, relative references are members of its select list and relate to the statement source that is an absolute reference.

```java
CqnElementRef title = CQL.entity(Books_.class).title(); // {"ref":["title"]}
CqnElementRef dynamicTitle = CQL.get(Books.TITLE); // {"ref":["title"]}
```

New references are constructed with [model interfaces](../cqn-services/persistence-services#model-interfaces) or via API that is also used to build [CQL statements](/java/working-with-cql/query-api#concepts). For most of application code, the model interfaces are the recommended way to do this.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve clarity by restructuring this sentence. Consider: 'New references are constructed using model interfaces or via the API that builds CQL statements. For most application code, model interfaces are the recommended approach.'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve clarity by restructuring this sentence. Consider: "For most application code, model interfaces are the recommended way to construct new references." This makes the recommendation clearer and more direct.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve clarity by restructuring this sentence. Consider: "For most application code, model interfaces are the recommended way to construct new references." This makes the recommendation clearer and more direct.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve clarity by restructuring this sentence. Consider: 'New references are constructed using model interfaces or via the API that builds CQL statements. For most application code, model interfaces are the recommended approach.'


References with multiple segments represent navigation within a structured entity or between different entities via its associations. For example, the following is a reference that represents the path from the book to its chapters.

```java
CqnStructuredTypeRef ref = CQL.entity(Books_.class).filter(b -> b.ID().eq("...")).chapters(c -> c.ID().eq("...")).pages(p -> p.ID().eq("...")).asRef();
```

References can be represented as JSON following an [Expression](../../cds/cxn) notation. The following is the JSON representation of the reference above:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use active voice and improve clarity. Change 'References can be represented as JSON following an Expression notation' to 'You can represent references as JSON using Expression notation.'


```json
{
"ref": [
{
"id": "sap.capire.bookshop.Books",
"where": [
{ "ref": ["ID"]}, "=", {"val": "..."}
]
},
{
"id": "chapters",
"where": [
{ "ref": ["ID"]}, "=", {"val": "..."}
]
},
{
"id": "pages",
"where": [
{ "ref": ["ID"]}, "=", {"val": "..."}
]
}
]
}
```

Below is an example of how this can be used together to build a CQL statement:

```java
// bookshop.Books[year = 2020].author // [!code focus]
Authors_ authors = CQL.entity(Books_.class).filter(b -> b.year().eq(2020)).author(); // [!code focus]

Expand All @@ -1325,8 +1380,102 @@ StructuredType<?> authors =
Select.from(authors).columns("name"); // [!code focus]
```

You can also get [entity references](query-execution#entity-refs) from the result of a CDS QL statement to address an entity via its key values in other statements.
An existing reference can be reused as an object or a variable, or a new reference can be built on top of it.

Given a simple reference pointing to the book created as follows.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Given a simple reference pointing to the book created as follows.
For the upcoming examples, let's assume a simple reference pointing to the book created as follows:


```java
// {"ref":[{"id":"sap.capire.bookshop.Books","where":[{"ref":["ID"]},"=",{"val":"..."}]}]}
CqnStructuredTypeRef ref = CQL.entity(Books_.class).filter(b -> b.ID().eq("...")).asRef(); // [!code focus]
```

You can use `CQL.entity(...)` method to cast the reference to required type and use its methods to extend it further.

```java
// {"ref":[{"id":"sap.capire.bookshop.Books","where":[{"ref":["ID"]},"=",{"val":"..."}]},"author"]}
CqnStructuredTypeRef refToAuthor = CQL.entity(Books_.class, ref).author().asRef(); // [!code focus]
```

With `CQL.to(...)` the same is produced dynamically.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use active voice and improve clarity. Change 'With CQL.to(...) the same is produced dynamically' to 'Use CQL.to(...) to produce the same result dynamically.'


```java
// {"ref":[{"id":"sap.capire.bookshop.Books","where":[{"ref":["ID"]},"=",{"val":"..."}]},"author"]}
CqnStructuredTypeRef toAuthor = CQL.to(ref.segments()).to("author").asRef(); // [!code focus]
```

This new reference might be used as the root of its own statement to read or change the author.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use active voice and improve clarity. Change "This new reference might be used as the root of its own statement" to "You can use this new reference as the root of its own statement" to be more direct and actionable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use active voice and improve clarity. Change "This new reference might be used" to "You can use this new reference" to be more direct and actionable.


To navigate to the parent, you can strip segment from the end of the ref.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarity improvement: The sentence 'To navigate to the parent, you can strip segment from the end of the ref' is missing an article. It should read: 'To navigate to the parent, you can strip a segment from the end of the ref.'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use active voice and improve clarity. Change 'To navigate to the parent, you can strip segment from the end of the ref' to 'To navigate to the parent, strip the segment from the end of the reference.' Also, 'segment' should be 'a segment' for proper grammar.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve sentence structure for better readability. Change "To navigate to the parent, you can strip segment from the end of the ref" to "To navigate to the parent, you can strip a segment from the end of the reference." Note the addition of the article "a" and using "reference" instead of "ref" for consistency.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grammar error: Add an article. Change "strip segment from the end" to "strip a segment from the end" for proper grammar.


```java
// {"ref":[{"id":"sap.capire.bookshop.Books","where":[{"ref":["ID"]},"=",{"val":"..."}]}]}
CqnStructuredTypeRef toParent = CQL.to(
refToAuthor.segments().subList(0, refToAuthor.segments().size() - 1)).asRef(); // [!code focus]
```

The `rootSegment()` method can be used to construct the reference starting with the root of the existing reference when you need to navigate to different parts of the same structured type, for example, from the author of the book to its pages.

```java
CqnStructuredTypeRef toPagesOfTheBook = CQL.to(List.of(refToAuthor.rootSegment())).to("chapters").to("pages").asRef();
```

You can use the `CQL.entity(...)` to use the convenience of model interfaces for this with additional casts.

```java
CqnStructuredTypeRef toPagesOfTheBook = CQL.entity(Books_.class,
CQL.to(List.of(refToAuthor.rootSegment())).asRef()).chapters().pages().asRef();
```

References can be copied to produce new references with in-place modification of its segments as follows.

```java
StructuredTypeRef ref = CQL.entity(Books_.class).filter(b -> b.ID().eq("...")).chapters(c -> c.ID().eq("...")).pages(p -> p.ID().eq("...")).asRef();
RefBuilder<StructuredTypeRef> builder = CQL.copy(ref);
builder.segments().forEach(s -> {
// add new predicate to each segment
s.filter(CQL.and(CQL.get(Books.GENRE).eq("Fiction"), s.filter().orElse(null)));
});

StructuredTypeRef copy = builder.build(); // new reference is ready
```

Test this code thoroughly and ensure that you do not omit the filters or change the reference so that it becomes inconsistent.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarity improvement: The phrase 'Test this code thoroughly and ensure that you do not omit the filters or change the reference so that it becomes inconsistent' is vague and unclear. Consider revising to: 'Ensure thorough testing when modifying references to avoid omitting filters or creating inconsistent reference states.'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Test this code thoroughly and ensure that you do not omit the filters or change the reference so that it becomes inconsistent.
Ensure thorough testing when modifying references to avoid omitting filters or creating inconsistent reference states.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve clarity and fix grammar. Change 'Test this code thoroughly and ensure that you do not omit the filters or change the reference so that it becomes inconsistent' to 'Test this code thoroughly to ensure you do not omit filters or make the reference inconsistent.'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve sentence structure and clarity. Consider: "Test this code thoroughly and ensure that you do not omit filters or make the reference inconsistent." This removes redundancy and improves flow.


References can be analyzed using the [`CqnAnalyzer`](/java/working-with-cql/query-introspection#cqnanalyzer) to bind it back to the model, for example, to find annotations or extract filter values. References can be introspected with [`CqnVisitor`](/java/working-with-cql/query-introspection#cqnvisitor).

:::warning Limitation
The references are not comparable between each other. They cannot be used as map keys or set values.
:::

### Element References {#element-refs}

An element reference points to an element of the entity. Such references are usually _relative_, they do not have the name of the entity in their root. They can include filters in their segments except _in the last one_.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix grammar and improve clarity. Change 'Such references are usually relative, they do not have the name of the entity in their root' to 'Such references are usually relative; they do not include the entity name in their root.' Use a semicolon to properly connect the related clauses.

Most of the time, they exist as members of the [select list](#projections) of a statement or part of the statement, for example, of an expand predicate.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use active voice instead of passive voice. Change 'Such references are usually relative, they do not have the name of the entity in their root. They can include filters in their segments except in the last one' to 'Such references are usually relative and do not have the entity name in their root. You can include filters in their segments except in the last one.'


The following example illustrates the difference:

```java
CqnSelect statement = Select.from(Books_.class, b -> b.filter(f -> f.ID().eq("...")))
.columns(b -> b.author().placeOfBirth());

CqnStructuredTypeRef absoluteRef = statement.ref(); // Books(ID=...)

CqnElementRef relativeRef = statement.items().getFirst().asRef(); // author/placeOfBirth
```

Element references can be extended with the same APIs as the entity references.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Element references can be extended with the same APIs as the entity references.
Element references can be extended with the same APIs as the [entity references](#entity-refs).


```java
CqnElementRef extendedRef = CQL.to(relativeRef.segments()).get("name"); // author/placeOfBirth/name
```

You can create _absolute_ element references, but they are rarely used.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sentence uses passive voice. Consider revising to:

"You rarely use absolute element references."


```java
CqnElementRef nameOfAuthor = CQL.entity(Books_.class).filter(f -> f.ID().eq("...")).author().name();
```

Element references share the same features and limitations as entity references and cannot be used with [`CqnAnalyzer`](/java/working-with-cql/query-introspection#cqnanalyzer).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use active voice and improve clarity. Change "Element references share the same features and limitations as entity references and cannot be used with" to "Element references have the same features and limitations as entity references and you cannot use them with" to make it more direct and clear.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use active voice and improve clarity. Change 'Element references share the same features and limitations as entity references and cannot be used with CqnAnalyzer' to 'Element references have the same features and limitations as entity references. You cannot use them with CqnAnalyzer.'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use active voice instead of passive voice. Change 'Element references share the same features and limitations as entity references and cannot be used with [CqnAnalyzer]' to 'Element references share the same features and limitations as entity references, and you cannot use them with [CqnAnalyzer]'.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve sentence structure and clarity. The sentence "Element references share the same features and limitations as entity references and cannot be used with [CqnAnalyzer]" could be clearer by separating the concepts.

Suggested revision:

Element references share the same features and limitations as entity references. However, you cannot use them with [`CqnAnalyzer`](/java/working-with-cql/query-introspection#cqnanalyzer).


### Values

Expand Down
Loading