-
Notifications
You must be signed in to change notification settings - Fork 138
feat: CXL documentation
#2260
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: CXL documentation
#2260
Conversation
| No matter where `CXL` is used, it always manifests in queries. | ||
| For example, [a calculated element](./cdl/#calculated-elements) defined in an entity will be resolved | ||
| to the respective calculation in the generated query when the entity is queried. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use expressions in various other places
- translated to EDMX-expressions
- to define projections between types
- projections can be resolved at runtime (runtime views)
- expressions can be evaluated in memory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Query does not mean that it is a database query. There can be multiple vehicles for an expression. Conceptually though, it can be understood as part of a query - whether it is either sent to the database, converted to edmx (and then sent to the backend again), or evaluated in memory.
This is an important point though. Expressions are not only meant for database queries.
Keeping this open -> happy for suggestions on how to formulate this.
The samples all have the corresponding SQL to make transparent what actually happens in the background. This is quite important for humans and especially for LLMs. The SQL is always hidden behind an extra tab, so it is not the focus. If CQL (which CXL is a part of) was really its own language, it would make sense to describe and specify everything in detail from the ground up. Since it is based on SQL, we can use that fact to build on pre-existing knowledge. To the structure of Value vs. Predicate... I don't agree. Predicates are also "values"... or rather, expressions... simply boolean expressions. There are some constructs which require that an expression returns a boolean (case when, ternary, filters, ...), but this boolean can also come from a literal, a ref etc. |
danjoa
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍👍👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new shape looks much better :-)
cds/cxl.md
Outdated
| | `count(x)` | Returns the count of non-null values of `x`. | | ||
| | `countdistinct(x)` | Returns the count of distinct non-null values of `x`. | | ||
|
|
||
| CAP supports a set of [portable functions](../guides/databases/cql-to-sql.md#portable-functions) that can be used in all expressions. Those functions are passed through to the underlying database, allowing you to leverage the same functions for different databases, which greatly enhances portability. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather define the portable functions here (as they are DB-independent and also apply for to remote OData calls). Then link from the database guide to here.
```js
> cds.parse.xpr`TimeStamp'2025-12-12'`
[ { val: '2025-12-12', literal: 'timestamp' } ]
> cds.parse.xpr`Time'2025-12-12'`
[ { val: '2025-12-12', literal: 'time' } ]
> cds.parse.xpr`Date'2025-12-12'`
[ { val: '2025-12-12', literal: 'date' } ]
> cds.parse.xpr`DateTime'2025-12-12'`
Uncaught Error: CDS compilation failed
In 'DateTime'2025-12-12'' at 9-21: Error: Mismatched ‹String›, expecting ‘.’, ‘(’, ‘[’, ‘!=’, ‘?’, ‘*’, ‘+’, ‘-’, ‘/’, ‘<’, ‘<=’, ‘<>’, ‘=’, ‘==’, ‘>’, ‘>=’, ‘||’, ‘and’, ‘between’, ‘in’, ‘is’, ‘like’, ‘not’, ‘or’, ‘over’, ‹EOF›
at Object.throwWithError (/Users/patricebender/SAPDevelop/cxl-bookshop/node_modules/@sap/cds-compiler/lib/base/messages.js:571:13)
at parseExpr (/Users/patricebender/SAPDevelop/cxl-bookshop/node_modules/@sap/cds-compiler/lib/main.js:74:20)
at Object.expr (/Users/patricebender/SAPDevelop/cxl-bookshop/node_modules/@sap/cds-compiler/lib/main.js:129:24)
at expr (/Users/patricebender/SAPDevelop/cxl-bookshop/node_modules/@sap/cds/lib/compile/parse.js:43:27)
at exports.ttl (/Users/patricebender/SAPDevelop/cxl-bookshop/node_modules/@sap/cds/lib/compile/parse.js:83:15)
at Function.expr (/Users/patricebender/SAPDevelop/cxl-bookshop/node_modules/@sap/cds/lib/compile/parse.js:37:27)
at exports.xpr (/Users/patricebender/SAPDevelop/cxl-bookshop/node_modules/@sap/cds/lib/compile/parse.js:52:19)
```
| extend Authors with { | ||
| age = years_between(dateOfBirth, coalesce(dateOfDeath, date( $now ))); | ||
| extend Books with { | ||
| total = price * stock; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add a type
| total = price * stock; | |
| total = price * stock : Decimal(8,2); |
| > cds.parse.expr ` TimeStamp'2026-01-14T10:30:00Z' ` | ||
| { val: '2026-01-14T10:30:00Z', literal: 'timestamp' } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is ISO 8601. Is this portable on all DBs? I.e., will
entity Start : cuid {
start : Timestamp default TimeStamp'2026-01-14T10:30:00Z'
}actually work?
Or rather use ISO/IEC 9075
| > cds.parse.expr ` TimeStamp'2026-01-14T10:30:00Z' ` | |
| { val: '2026-01-14T10:30:00Z', literal: 'timestamp' } | |
| > cds.parse.expr ` TimeStamp'2026-01-14 10:30:00' ` | |
| { val: '2026-01-14 10:30:00', literal: 'timestamp' } |
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CAP Java additionally supports these literal types
- number
- x
- hex
- boolean
- string
- vector
|
|
||
| [Learn more about the `exists` predicate.](./cql.md#exists-predicate){.learn-more} | ||
|
|
||
| The `exists` predicate can be further enhanced by [combining it with infix filters](#exists-infix-filter). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrap as "tip"?

TBD