0% found this document useful (0 votes)
211 views14 pages

CDS Concepts & Syntax Guide

This document provides definitions and examples of key concepts in the CDS (Conceptual Data Modeling) language, including: - Entity and type definitions to define structured data models - Examples of entity definitions, type definitions, predefined types, structured types, and arrayed types - Descriptions of virtual elements, literals, delimited identifiers, and calculated elements - Notes on null values, multiline string literals, and escaped characters

Uploaded by

krajiv6
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
211 views14 pages

CDS Concepts & Syntax Guide

This document provides definitions and examples of key concepts in the CDS (Conceptual Data Modeling) language, including: - Entity and type definitions to define structured data models - Examples of entity definitions, type definitions, predefined types, structured types, and arrayed types - Descriptions of virtual elements, literals, delimited identifiers, and calculated elements - Notes on null values, multiline string literals, and escaped characters

Uploaded by

krajiv6
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Definition Language (CDL)

Find here a reference of all CDS concepts and features in the form of compact
examples. The examples are given in CDL, a human-readable syntax for defining
models, and CQL, an extension of SQL to write queries.

Refer also to The Nature of Models and the CSN specification to complete your


understanding of CDS.

Entity and Type Definitions

 Entity Definitions — define entity


 Type Definitions — define type
 Predefined Types
 Structured Types
 Arrayed Types
 Virtual Elements
 Literals
 Delimited Identifiers
 Calculated elements
 Default Values
 Type References
 Constraints
 Enums

Entity Definitions — define entity


Entities are structured types with named and typed elements, representing sets of
(persisted) data that can be read and manipulated using usual CRUD operations.
They usually contain one or more designated primary key elements:

cds
define entity Employees {
key ID : Integer;
name : String;
jobTitle : String;
}

The define keyword is optional, that means define entity Foo is equal to entity Foo.

Type Definitions — define type

You can declare custom types to reuse later on, for example, for elements in entity
definitions. Custom-defined types can be simple, that is derived from one of the
predefined types, structure types or Associations.

cds
define type User : String(111);
define type Amount {
value : Decimal(10,3);
currency : Currency;
}
define type Currency : Association to Currencies;

The define keyword is optional, that means define type Foo is equal to type Foo.

Learn more about Definitions of Named Aspects.

Predefined Types

See list of Built-in Types

Structured Types

You can declare and use custom struct types as follows:

cds
type Amount {
value : Decimal(10,3);
currency : Currency;
}
entity Books {
price : Amount;
}

Elements can also be specified with anonymous inline struct types. For example, the
following is equivalent to the definition of Books above:

cds
entity Books {
price : {
value : Decimal(10,3);
currency : Currency;
};
}

Arrayed Types

Prefix a type specification with array of or many to signify array types.

cds
entity Foo { emails: many String; }
entity Bar { emails: many { kind:String; address:String; }; }
entity Car { emails: many EmailAddress; }
entity Car { emails: EmailAddresses; }
type EmailAddresses : many { kind:String; address:String; }
type EmailAddress : { kind:String; address:String; }

Keywords many and array of are mere syntax variants with identical semantics and


implementations.

When deployed to SQL databases, such fields are mapped to LargeString columns


and the data is stored denormalized as JSON array. With OData V4, arrayed types are
rendered as Collection in the EDM(X).

WARNING

Filter expressions, instance-based authorization and search are not supported on


arrayed elements.

Null Values

For arrayed types the null and not null constraints apply to the members of the


collections. The default is not null indicating that the collections can't hold null values.

WARNING

An empty collection is represented by an empty JSON array. A null value is invalid for an


element with arrayed type.
In the following example the collection emails may hold members that are null. It may
also hold a member where the element kind is null. The collection emails itself must
not be null!

cds
entity Bar {
emails : many {
kind : String null;
address : String not null;
} null; // -> collection emails may hold null values, overwriting default
}

Virtual Elements

An element definition can be prefixed with modifier keyword virtual. This keyword


indicates that this element isn't added to persistent artifacts, that is, tables or views in
SQL databases. Virtual elements are part of OData metadata.

By default virtual elements are annotated with @[Link]: true, not writable for
the client and will be silently ignored. This means also, that they are not accessible in
custom event handlers. If you want to make virtual elements writable for the client,
you explicitly need to annotate these elements with @[Link]: false. Still those
elements are not persisted and therefore, for example, not sortable or filterable.

cds
entity Employees {
...
virtual something : String(11);
}

Literals

Using literals in CDS models is commonly used, for example, to set default values.
The literals in the following table show you how to define these values in your CDS
source.

Kind Example

Null null
Kind Example

Boolean true, false

Numbers 11, 2.4, or 1.34e10

Strings 'foo' or `foo` or ```foo```

Dates date'2016-11-24'

Times time'[Link]Z'

Timestamp timestamp'2016-11-24T[Link].4209753Z'

DateTime '2016-11-24T16:11Z'

Records {"foo":<literal>, ...}

Arrays [<literal>, ...]

Learn more about literals and their representation in CSN.

Multiline String Literals

String literals enclosed in single ticks, for example 'string', are limited to a single line.

Use string literals enclosed in single or triple backticks for multiline strings. Within


those strings, escape sequences from JavaScript, such as \t or \u0020, are supported.
Line endings are normalized. If you don't want a line ending at that position, end a
line with a backslash (\). Only for string literals inside triple backticks, indentation is
stripped and tagging is possible.

Examples:

cds
@documentation: ```
This is a CDS multiline string.
- The indentation is stripped.
- \u{0055}nicode escape sequences are possible,
just like common escapes from JavaScript such as
\r \t \n and more!
```

@data: ```xml
<main>
The tag is ignored by the core-compiler but may be
used for syntax highlighting, similar to markdown.
</main>
```
@escaped: `OK Emoji: \u{1f197}`
entity DocumentedEntity {
// ...
}

Delimited Identifiers

Delimited identifiers allow you to use any identifier, even containing special
characters or using a keyword.

WARNING

Special characters in identifiers or keywords as identifiers should be avoided for best


interoperability.
cds
entity ![Entity] {
bar : ![Keyword];
![with space] : Integer;
}

You can escape ] by ]], for example ![L[C]]R] which will be parsed as L[C]R.

Calculated Elements (beta)

WARNING
This is a beta feature. Beta features aren't part of the officially delivered scope that SAP
guarantees for future releases. For more information, see Important Disclaimers and
Legal Information.

Elements of entities and aspects can be specified with a calculation expression, in


which you can refer to other elements of the same entity/aspect.

Today CAP CDS only supports calculated elements with a value expression. They are
read-only, no value must be provided for them in a WRITE operation. When reading
a calculated element, the result of the expression is returned.

Calculated elements with a value expression come in two variants: "on-read" and
"on-write". The difference between them is the point in time when the expression is
evaluated.

On-read (beta)
cds
entity Employees {
firstName : String;
lastName : String;
name : String = firstName || ' ' || lastName;
name_upper = upper(name);
addresses : Association to many Addresses;
city = addresses[kind='home'].city;
}

For a calculated element with "on-read" semantics, the calculation expression is


evaluated when reading an entry from the entity. Using such a calculated element in
a query or view definition is equivalent to writing the expression directly into the
query, both with respect to semantics and to performance. In CAP, it is implemented
by replacing each occurrence of a calculated element in a query by the respective
expression.

Entity using calculated elements:

cds
entity EmployeeView as select from Employees {
name,
city
};

Equivalent entity:

cds
entity EmployeeView as select from Employees {
firstName || ' ' || lastName as name : String,
addresses[kind='home'].city as city
};

Calculated elements "on-read" are a pure convenience feature. Instead of having to


write the same expression several times in queries, you can define a calculated
element once and then simply refer to it.

In the definition of a calculated element "on-read", you can use almost all expressions
that are allowed in queries. Some restrictions apply:

 Subqueries are not allowed.


 Nested projections (inline/expand) are not allowed.
 A calculated element can't be key.

A calculated element can be used in every location where an expression can occur. A
calculated element can't be used in the following cases:

 in the ON condition of an unmanaged association


 as the foreign key of a managed association
 in a query together with nested projections (inline/expand)

Temporary Restriction in the [Link] Runtime

Currently, an OData request or a custom query can't directly access a calculated element
in the entity where it is defined. It must always be accessed using a view/projection.

On-write (beta)

Calculated elements "on-write" (also referred to as "stored" calculated elements) are


defined by adding the keyword stored. A type specification is mandatory.

cds
entity Employees {
firstName : String;
lastName : String;
name : String = (firstName || ' ' || lastName) stored;
}

For a calculated element "on-write", the expression is already evaluated when an


entry is written into the database. The resulting value is then stored/persisted like a
regular field, and when reading from the entity, it behaves like a regular field as well.
Using a stored calculated element can improve performance, in particular when it's
used for sorting or filtering. This is paid for by higher memory consumption.
While calculated elements "on-read" are handled entirely by CAP, the "on-write"
variant is implemented by using the corresponding feature for database tables. The
previous entity definition results in the following table definition:

sql
-- SAP HANA syntax --
CREATE TABLE Employees (
firstName NVARCHAR,
lastName NVARCHAR,
name NVARCHAR GENERATED ALWAYS AS (firstName || ' ' || lastName)
);

For the definition of calculated elements on-write, all the on-read variant's
restrictions apply and referencing localized elements isn't allowed. In addition, there
are restrictions that depend on the particular database. Currently all databases
supported by CAP have a common restriction: The calculation expression may only
refer to fields of the same table row. Therefore, such an expression must not contain
subqueries, aggregate functions, or paths with associations.

No restrictons apply for reading a calculated element on-write.

Default Values

As in SQL you can specify default values to fill in upon INSERTs if no value is specified
for a given element.

cds
entity Foo {
bar : String default 'bar';
boo : Integer default 1;
}

Default values can also be specified in custom type definitions:

cds
type CreatedAt : Timestamp default $now;
type Complex {
real : Decimal default 0.0;
imag : Decimal default 0.0;
}

Type References

If you want to base an element's type on another element of the same structure, you
can use the type of operator.
cds
entity Author {
firstname : String(100);
lastname : type of firstname; // has type "String(100)"
}

For referencing elements of other artifacts, you can use the element access through :.
Element references with : don't require type of in front of them.

cds
entity Employees {
firstname: Author:firstname;
lastname: Author:lastname;
}

Constraints

Element definitions can be augmented with constraint not null as known from SQL.

cds
entity Employees {
name : String(111) not null;
}

Enums

You can specify enumeration values for a type as a semicolon-delimited list of


symbols. For string types, declaration of actual values is optional; if omitted, the
actual values are the string counterparts of the symbols.

cds
type Gender : String enum { male; female; non_binary = 'non-binary'; }
entity Order {
status : Integer enum {
submitted = 1;
fulfilled = 2;
shipped = 3;
canceled = -1;
};
}

To enforce your enum values during runtime, use the @[Link] annotation. For


localization of enum values, model them as code list.
Views and Projections

Use as select from or as projection on to derive new entities from existing ones by
projections, very much like views in SQL. When mapped to relational databases, such
entities are in fact translated to SQL views but they're frequently also used to declare
projections without any SQL views involved.

The entity signature is inferred from the projection.

 The as select from Variant


 The as projection on Variant
 Views with Inferred Signatures

 Views with Parameters

The as select from Variant

Use the as select from variant to use all possible features an underlying relational
database would support using any valid CQL query including all query clauses.

cds
entity Foo1 as SELECT from Bar; //> implicit {*}
entity Foo2 as SELECT from Employees { * };
entity Foo3 as SELECT from Employees LEFT JOIN Bar on [Link]=[Link] {
foo, bar as car, sum(boo) as moo
} where exists (
SELECT 1 as anyXY from SomeOtherEntity as soe where soe.x = y
)
group by foo, bar
order by moo asc;

The as projection on Variant

Use the as projection on variant instead of as select from to indicate that you don't use
the full power of SQL in your query. For example, having a restricted query in an
entity allows us to serve such an entity from external OData services.

cds
entity Foo as projection on Bar {...}

Currently the restrictions of as projection on compared to as select from are:


 no explicit, manual JOINs
 no explicit, manual UNIONs
 no sub selects in from clauses

Over time, we can add additional checks depending on specific outbound protocols.

Views with Inferred Signatures

By default views inherit all properties and annotations from their primary underlying
base entity. Their elements signature is inferred from the projection on base elements.
Each element inherits all properties from the respective base element, except
the key property. The key property is only inherited if all of the following applies:

 No explicit key is set in the query.


 All key elements of the primary base entity are selected (for example, by
using *).
 No path expression with a to-many association is used.
 No union, join or similar query construct is used.

For example, the following definition:

cds
entity SomeView as SELECT from Employees {
ID,
name,
[Link] as jobTitle
};

Might result in this inferred signature:

cds
entity SomeView {
key ID: Integer;
name: String;
jobTitle: String;
};

Note: CAP does not enforce uniqueness for key elements of a view or projection.

Use a CDL cast to set an element's type, if one of the following conditions apply:

 You don't want to use the inferred type.


 The query column is an expression (no inferred type is computed).

cds
entity SomeView as SELECT from Employees {
ID : Integer64,
name : LargeString,
'SAP SE' as company : String
};

TIP

By using a cast, annotations and other properties are inherited from the provided type
and not the base element, see Annotation Propagation

Views with Parameters

You can equip views with parameters that are passed in whenever that view is
queried. Default values can be specified. Refer to these parameters in the view's
query using the prefix :.

cds
entity SomeView ( foo: Integer, bar: Boolean )
as SELECT * from Employees where ID=:foo;

Learn more about how to expose views with parameters in  Services - Exposed
[Link] more about views with parameters for existing HANA artifacts
in Native SAP HANA Artifacts.

Associations & Compositions

Associations capture relationships between entities. They are like forward-declared


joins added to a table definition in SQL.

 Unmanaged Associations
 Managed Associations
 To-many Associations
 Many-to-many Associations

 Compositions
 Managed Compositions

Unmanaged Associations
Unmanaged associations specify arbitrary join conditions in their on clause, which
refer to available foreign key elements. The association's name ( address in the
following example) is used as the alias for the to-be-joined target entity.

You might also like