---
versions:
  cdsjs: 5.9.3
  cdsdk: 4.9.3
  cdsc: 2.13.8
  cdsmtx: 2.5.5
  java: 1.23.0

---

# March 2022

<ReleaseBadges />

[[toc]]

## Database Integrity Constraints

CDS can now automatically generate native database referential integrity constraints for managed to-one Associations and Compositions:

```cds
entity Books {
  ...
  author : Association to Authors;
}
entity Authors {
  key ID : Integer;
  ...
}
```

Association `author` triggers the generation of a constraint:

```sql
CONSTRAINT Books_author ON Books
  FOREIGN KEY(author_ID) REFERENCES Authors(ID)
  ON UPDATE RESTRICT
  ON DELETE RESTRICT
  VALIDATED
  ENFORCED
  INITIALLY DEFERRED
```

Database constraints are available for SQL dialects `hana` and `sqlite`.

Switch them on with the configuration `cds.env.features.assert_integrity`
that can have the values:

- `'db'`: Database constraints
- `'app'`: Runtime checks (default, only effective in Node.js runtime)
- `false`: No database constraints and no runtime checks

The Node.js runtime features integrity checks in the application. We intend to replace
these rather expensive checks in the application by database constraints with the next
major release in 2022. For the migration period until then you can choose what kind of
integrity checks are performed.

Generation of database constraints is of course also possible on the CAP Java stack,
where no runtime checks are available.

[Learn more about Database Constraints.](/@external/guides/databases/cdl-to-ddl#database-constraints){ .learn-more}

## Native Database Clauses

Using the annotations `@sql.prepend` and `@sql.append`, you can add arbitrary SQL snippets to the
DDL statements that are generated by the compiler. This allows you to use database features that
are not natively supported by CDS.

Model:

```cds
@sql.append: ```sql
             GROUP TYPE foo
             GROUP SUBTYPE bar
             ```
entity E {
  ...,
  @sql.append: 'FUZZY SEARCH INDEX ON'
  text: String(100);
}
```

Result:

```sql
create table E (
  ...,
  text nvarchar(100) FUZZY SEARCH INDEX ON
) GROUP TYPE foo
GROUP SUBTYPE bar
```

If you use native database clauses in entities where schema evolution has been enabled using annotation `@cds.persistence.journal`, see [Schema Evolution Support of Native Database Clauses](/@external/guides/databases/hana#schema-evolution-native-db-clauses).

::: warning _
The compiler doesn't check or process the provided SQL snippets in any way. You are responsible to ensure that the resulting statement is valid and doesn't negatively impact your database or your application. We don't provide support for problems caused by using this feature.
:::

[Learn more about Native Database Clauses.](/@external/guides/databases/hana#schema-evolution-native-db-clauses){ .learn-more}

## Native HANA Functions with non-standard syntax

CDS now supports SAP HANA aggregate functions with an additional `order by` clause in the argument list, like:

```sql
first_value(name order by price desc)
```


## CDS Language { #cds}

### Simplified Syntax for Extending or Annotating Elements

Until now, for annotating or extending elements of an entity, you had to "repeat" the relevant part of the entity definition:

```cds
annotate Foo with {
  nestedStructField {
    existingField @title:'Nested Field';
  }
}

extend Foo with {
  extend nestedStructField {
    newField : String;
  }
}
```

This is a bit cumbersome if you only want to annotate or extend single elements.
You can **now directly address the element** you want to annotate or extend:

```cds
annotate Foo:nestedStructField.existingField with @title:'Nested Field';

extend Foo:nestedStructField with { newField : String; }
```

[Learn more about **annotate**.](/@external/cds/cdl#annotate){ .learn-more} [Learn more about **extend**.](/@external/cds/cdl#extend){ .learn-more}

### Default in Type Definitions

A default value can now be specified also in scalar custom type definitions:

```cds
type CreatedAt : Timestamp default $now;
```

[Learn more about Defaults.](/@external/cds/cdl#default-values){ .learn-more}

## Node.js SDK { #cds-js}

### Important Changes ❗️ { #changes-in-node-js .important }

- **Fixed:** Keys of an entity were always fetched in addition. This does not happen anymore.
  Example:

  ```js
  let { CatalogService } = cds.services
  let books = await CatalogService.read('title').from('Books')
  ```

  &rarr; formerly this returned:

  ```js
  books = [{ ID:201, title:'Wuthering Heights' }, ...]
  ```

  &rarr; now it is:

  ```js
  books = [{ title:'Wuthering Heights' }, ...]
  ```

  If you need the keys in the result, make sure you request them explicitly in the query as well.

### Driver-Agnostic Results for Stored Procedures

We added a driver-agnostic way for SAP HANA procedure calls with table output data.

Example:

```js
// P1 -> table output, P2 -> primitive output, P3 -> input
> await cds.run(' CALL PROC(P1 => ?,P2 => ?,P3 => ?)', 42)
{
  P1: [...]
  P2: 4711
}
```

## Java SDK { #cds-java}

### Important Changes ❗️ { #important-changes-in-java .important }

Elements with type `UUID` that are annotated with `@odata.Type:'Edm.String'` are not normalized anymore. The comparison is case sensitive and arbitrary values can be stored ([example](#additional-values-for-managed-data)).

### Relaxed Deep Insert/Update

If the data of deep Insert or deep Update contains values of an associated entity but the (forward mapped) association does not cascade the Insert/Update operation, only the association itself is updated, but not the values of the associated entity.

Assumed you have the following model:

```cds
entity Orders {
  key id : UUID;
  book : Association to Books; // not cascading
}

entity Books {
  key id : Integer;
  title : String;
}
```

In addition, you run this code:

```java
Map<String, Object> order = Map.of("book",
    Map.of("id", 17, "title", "Capricorn"));
CqnInsert insert = Insert.into("Orders").entry(order);
db.run(insert);
```

This creates a new order and associates this order to the book with `id` 17. But it doesn't create the book.

### Collectors for AND and OR

New methods `CQL.withAnd()` and `CQL.withOr()` allow to use a `Collector` to connect a stream of CQN predicates with `AND` or `OR`:

```java
List<Map<String, Object>> values = ...
Stream<CqnPredicate> predicates = values.stream().map(CQL.matching);
CqnPredicate filter = predicates.collect(CQL.withOr());
```

[Learn more about Connecting Streams of Predicates](/@external/java/working-with-cql/query-api#connecting-streams-of-predicates)

### Additional Values for Managed Data

The annotations `@cds.on.insert` and `@cds.on.update` now support additional values. The special references `$user.locale` and `$user.tenant` allow to automatically set respective tenant or locale from the user info.

The value `$uuid` can be used to automatically set a generated UUID value.

The following snippets are equivalent:

```cds
entity Orders {
  @cds.on.insert : '$uuid'
  id : String;
}
```

```cds
entity Orders {
  @odata.Type : 'Edm.String'
  id : UUID;
}
```

### Security & Compliance

<span id="beforedefaultmockuser" />

#### Default Mock Users to Ease Testing

In case mock user security configuration is active, default mock users reflecting [pseudo roles](/@external/guides/security/cap-users#pseudo-roles) are available by default now. They are named `authenticated`, `system`, and `privileged` and can be used with an empty password. For instance, requests sent during a Spring MVC unit test with annotation `@WithMockUser("authenticated")` will pass authorization checks that require `authenticated-user`.

[Learn more mock user authentication.](/@external/java/security#mock-users){ .learn-more}

#### Improved Propagation of Authentication Information

The [AuthenticationInfo](https://www.javadoc.io/doc/com.sap.cds/cds-services-api/latest/com/sap/cds/services/authentication/AuthenticationInfo.html) (for example, storing a JWT) can now be accessed from the [RequestContext](https://www.javadoc.io/doc/com.sap.cds/cds-services-api/latest/com/sap/cds/services/request/RequestContext.html) and [EventContext](https://www.javadoc.io/doc/com.sap.cds/cds-services-api/latest/com/sap/cds/services/EventContext.html) and is provided as a Spring bean:

```java
@Autowired AuthenticationInfo authInfo;
...
JwtTokenAuthenticationInfo jwtTokenInfo = authInfo.as(JwtTokenAuthenticationInfo.class);
String jwtToken = jwtTokenInfo.getToken();
```

It is also propagated to child threads when propagating the `RequestContext`.

[Learn more in Reading Request Contexts.](/@external/java/event-handlers/request-contexts#reading-requestcontext){ .learn-more}

#### Fine-Grained Control of Outbox Usage

Added properties `cds.auditlog.outbox` and `cds.messaging.services.<key>.outbox` that control the usage of the Outbox for Auditlog/Messaging events.

[Learn more about CDS Properties.](/@external/java/developing-applications/properties){ .learn-more}

### Misc

- `@Core.ContentID` is now present on OData V4 error responses. For batch requests this allows to relate the error messages of an OData change set to the individual request that causes the error.

- When using SAP HANA Cloud, you can now enable a shared connection pool using property `cds.multiTenancy.dataSource.combinePools.enabled` without having to specify all database instances using property `cds.multiTenancy.dataSource.hanaDatabaseIds`.

- Added integration with Cloud SDK's RequestHeaderFacade ensuring HTTP headers are propagated to Cloud SDK.

- The goal install-cdsdk of the cds-maven-plugin provides the new parameter `arguments` to pass additional arguments to the command line.

## Preview on Save in VS Code { #preview-on-save}

The preview for a _.cds_ file is now automatically refreshed each time you save the corresponding _.cds_ file.

> You can disable this behavior with setting `Cds > Preview: Refresh On Save`.

## Simplified Deploy Guides { #deploy-guides}

We have reworked and simplified the [Deploy and Operate](/@external/guides/deploy/) guides.  Most notably,  the [Deploy to Cloud Foundry](/@external/guides/deploy/to-cf) and [Multitenancy](/@external/guides/multitenancy/) cookbooks are much simpler to execute, as they make use of the [project facets](#cds-add-improved)
below.

## Improved `cds add <facets>` { #cds-add-improved}

We've enhanced the CAP project facets to ease application setup for various configurations and deployment scenarios:

- `cds add xsuaa` prepares for JWT authentication via XSUAA.
- `cds add mtx` configures your application for SaaS deployments.
- `cds add approuter` allows for serving your application's UI using [SAP App Router](https://www.npmjs.com/package/@sap/approuter).
- `cds add kibana-logging` sets up your application for the BTP logging service and the Kibana dashboard.
- `cds add mta` creates the _mta.yaml_ deployment descriptor as before, but in addition, the other templates update _mta.yaml_ if needed.

The `--for <profile>` parameter allows to specify the [Node.js configuration profile](/@external/node.js/cds-env#profiles).  For example, `cds add mtx --for production` only adds multitenancy configuration to the `[production]` profile.

Take a look at the revised [deploy guides](/@external/guides/deploy/) to see the facets in context.

## Names Check in `cds lint` { #check-reserved-names}

A [new lint rule](/@external/tools/cds-lint/rules/no-dollar-prefixed-names/) warns about entities and elements that start with `$`.<br>
Such names may conflict with reserved variables that also start with `$` (like `$self`).

[Learn more about CDS Lint.](/@external/tools/cds-lint/){ .learn-more}

## Security in Multitenancy { #mtx}

Tokens downloaded to the command line client are now reduced in scope.
That means, they only contain those scopes necessary for client operation.
This follows the principle of least privileges and aims to reduce the risk of token misuse.

The optional `ExtendCDSdelete` scope is not part of the token unless the user is assigned that scope.
If the `ExtendCDSdelete` scope is not assigned when activating a new extension, requests to delete a previous version of an extension are rejected.

If the user's privileges change, for example, by assigning the `ExtendCDSdelete` scope via a role collection,
the user has to run `cds logout` and then `cds login`. This fetches a token containing the extended set of scopes.
