diff --git a/guides/databases-hana.md b/guides/databases-hana.md index e81a4a192..e48dfe98c 100644 --- a/guides/databases-hana.md +++ b/guides/databases-hana.md @@ -25,7 +25,7 @@ CAP isn't validated with other variants of SAP HANA, like "SAP HANA Database as Run this to use SAP HANA Cloud for production: ```sh -npm add @cap-js/hana +cds add hana ``` ::: details Using other SAP HANA drivers... @@ -34,9 +34,9 @@ Package `@cap-js/hana` uses the [`hdb`](https://www.npmjs.com/package/hdb) drive ::: -::: tip Prefer `cds add` +:::info prefer `cds add …` over `npm add …` -... as documented in the [deployment guide](deployment/to-cf#_1-sap-hana-database), which also does the equivalent of `npm add @cap-js/hana` but in addition cares for updating `mta.yaml` and other deployment resources. +It does the equivalent of e.g. `npm add @cap-js/hana` but in addition cares for updating `mta.yaml` and other deployment resources as documented in the [deployment guide](deployment/to-cf#_1-sap-hana-database). ::: diff --git a/guides/databases-postgres.md b/guides/databases-postgres.md index 1b31813aa..1fece2ac7 100644 --- a/guides/databases-postgres.md +++ b/guides/databases-postgres.md @@ -7,7 +7,9 @@ impl-variants: true
-This guide focuses on the new PostgreSQL Service provided through *[@cap-js/postgres](https://www.npmjs.com/package/@cap-js/postgres)*, which is based on the same new database services architecture as the new [SQLite Service](databases-sqlite). This architecture brings significantly enhanced feature sets and feature parity, as documented in the [*Features* section of the SQLite guide](databases-sqlite#features). +This guide focuses on the PostgreSQL Service delivered by [`@cap-js/postgres`](https://github.com/cap-js/cds-dbs/tree/main/packages/postgres). +It belongs to the unified `@cap-js` database-services architecture, the same foundation used by [`@cap-js/sqlite`](https://github.com/cap-js/cds-dbs/tree/main/packages/sqlite). +The shared architecture offers an aligned and expanded feature set across databases; its main capabilities are listed in the [*Features* section of the SQLite guide](databases-sqlite#features). *Learn about migrating from the former `cds-pg` in the [Migration](#migration) chapter.*{.learn-more} @@ -75,8 +77,10 @@ Output: ```js { impl: '@cap-js/postgres', + kind: 'postgres', dialect: 'postgres', - kind: 'postgres' + vcap: { label: 'postgresql-db' }, + schema_evolution: 'auto' } ``` @@ -477,7 +481,7 @@ You can use `cds deploy` with option `--dry` to simulate and inspect how things ``` ::: - + > **Note:** If you use SQLite, ALTER TYPE commands are not necessary and so, are not supported, as SQLite is essentially typeless. ### Generate Scripts @@ -618,7 +622,7 @@ If the changes in the model could lead to data loss, an error is raised. ## Migration { .node } -Thanks to CAP's database-agnostic cds.ql API, we're confident that the new PostgreSQL service comes without breaking changes. Nevertheless, please check the instructions in the [SQLite Migration guide](databases-sqlite#migration), with by and large applies also to the new PostgreSQL service. +Thanks to CAP's database-agnostic cds.ql API, we're confident that the `@cap-js/` PostgreSQL service comes without breaking changes. Nevertheless, please check the instructions in the [SQLite Migration guide](databases-sqlite#migration), which mostly applies also to the new PostgreSQL service. ### `cds deploy --model-only` diff --git a/guides/databases-sqlite.md b/guides/databases-sqlite.md index 185aced81..ce36eea33 100644 --- a/guides/databases-sqlite.md +++ b/guides/databases-sqlite.md @@ -9,8 +9,9 @@ CAP provides extensive support for [SQLite](https://www.sqlite.org/index.html),
-::: tip New SQLite Service -This guide focuses on the new SQLite Service provided through *[@cap-js/sqlite](https://www.npmjs.com/package/@cap-js/sqlite)*, which has many advantages over the former one, as documented in the [*Features*](#features) section. To migrate from the old service, find instructions in the [*Migration*](#migration) section. +::: tip This guide focuses on the SQLite Service provided by [`@cap-js/sqlite`](https://www.npmjs.com/package/@cap-js/sqlite). +Starting with CDS 9, this service is the **standard and required** runtime for SQLite in CAP projects. Its benefits are detailed in the [*Features*](#features) section. +If your project still relies on the previous SQLite service, follow the instructions in the [*Migration*](#migration) section to switch. :::
@@ -34,7 +35,7 @@ This guide focuses on the new SQLite Service provided through *[@cap-js/sqlite]( Run this to use SQLite for development: ```sh -npm add @cap-js/sqlite -D +cds add sqlite ``` ### Auto-Wired Configuration {.node} @@ -314,10 +315,19 @@ The following is an overview of advanced features supported by the new database > These apply to all new database services, including SQLiteService, HANAService, and PostgresService. + ### Path Expressions & Filters {.node} -The new database service provides **full support** for all kinds of [path expressions](../cds/cql#path-expressions), including [infix filters](../cds/cql#with-infix-filters) and [exists predicates](../cds/cql#exists-predicate). For example, you can try this out with *[cap/samples](https://github.com/sap-samples/cloud-cap-samples)* as follows: +All `@cap-js` database services — [`@cap-js/sqlite`](https://github.com/cap-js/cds-dbs/tree/main/packages/sqlite), +[`@cap-js/postgres`](https://github.com/cap-js/cds-dbs/tree/main/packages/postgres), and +[`@cap-js/hana`](https://github.com/cap-js/cds-dbs/tree/main/packages/hana) — provide **full support** for all kinds of [path expressions](../cds/cql#path-expressions), including [infix filters](../cds/cql#with-infix-filters) and [exists predicates](../cds/cql#exists-predicate). + +You can try this out with *[cap/samples](https://github.com/sap-samples/cloud-cap-samples)* as follows: + ```js // $ cds repl --profile better-sqlite @@ -347,7 +357,7 @@ await SELECT `from ${Authors} { books.genre.name }` ### Optimized Expands {.node} -The old database service implementation(s) used to translate deep reads, that is, SELECTs with expands, into several database queries and collect the individual results into deep result structures. The new service uses `json_object` and other similar functions to instead do that in one single query, with sub selects, which greatly improves performance. +The legacy database service implementation(s) used to translate deep reads, that is, `SELECT`s with expands, into several database queries and collect the individual results into deep result structures. The new service uses `json_object` and other similar functions to instead do that in one single query, with sub selects, which greatly improves performance. For example: @@ -386,13 +396,13 @@ SELECT.one.localized(Books) ### Using Lean Draft {.node} -The old implementation was overly polluted with draft handling. But as draft is actually a Fiori UI concept, none of that should show up in database layers. Hence, we eliminated all draft handling from the new database service implementations, and implemented draft in a modular, non-intrusive way — called *'Lean Draft'*. The most important change is that we don't do expensive UNIONs anymore but work with single (cheap) selects. +The legacy implementation was overly polluted with draft handling. But as draft is actually a Fiori UI concept, none of that should show up in database layers. Hence, we eliminated all draft handling from the `@cap-js` database services, and implemented draft in a modular, non-intrusive way — called *'Lean Draft'*. The most important change is that we don't do expensive UNIONs anymore but work with single (cheap) selects. ### Consistent Timestamps {.node} -Values for elements of type `DateTime` and `Timestamp` are handled in a consistent way across all new database services along these lines: +Values for elements of type `DateTime` and `Timestamp` are handled in a consistent way across all `@cap-js` database services along these lines: :::tip *Timestamps* = `Timestamp` as well as `DateTime` @@ -404,7 +414,7 @@ When we say *Timestamps*, we mean elements of type `Timestamp` as well as `DateT #### Writing Timestamps -When writing data using INSERT, UPSERT or UPDATE, you can provide values for `DateTime` and `Timestamp` elements as JavaScript `Date` objects or ISO 8601 Strings. All input is normalized to ensure `DateTime` and `Timestamp` values can be safely compared. In case of SAP HANA and PostgreSQL, they're converted to native types. In case of SQLite, they're stored as ISO 8601 Strings in Zulu timezone as returned by JavaScript's `Date.toISOString()`. +When writing data using `INSERT`, `UPSERT` or `UPDATE`, you can provide values for `DateTime` and `Timestamp` elements as JavaScript `Date` objects or ISO 8601 Strings. All input is normalized to ensure `DateTime` and `Timestamp` values can be safely compared. In case of SAP HANA and PostgreSQL, they're converted to native types. In case of SQLite, they're stored as ISO 8601 Strings in Zulu timezone as returned by JavaScript's `Date.toISOString()`. For example: @@ -473,7 +483,7 @@ SELECT.from(Foo).where `createdAt = ${'2022-11-11T11:11:11+02:00'}` // non-Zulu SELECT.from(Foo).where `createdAt = ${'2022-11-11T11:11:11Z'}` // missing 3-digit fractions ``` -> This is because we can never reliably infer the types of input to `where` clause expressions. Therefore, that input will not receive any normalisation, but be passed down as is as plain string. +> This is because we can never reliably infer the types of input to `where` clause expressions. Therefore, that input will not receive any normalisation, but is passed down as is as plain string. :::tip Always ensure proper input in `where` clauses @@ -492,7 +502,7 @@ The rules regarding Timestamps apply to all comparison operators: `=`, `<`, `>`, ### Improved Performance {.node} -The combination of the above-mentioned improvements commonly leads to significant performance improvements. For example, displaying the list page of Travels in [cap/sflight](https://github.com/SAP-samples/cap-sflight) took **>250ms** in the past, and **~15ms** now. +The combination of the above-mentioned improvements commonly leads to significant performance improvements. For example, displaying the list page of Travels in [cap/sflight](https://github.com/SAP-samples/cap-sflight) took **>250ms** with the legacy database services, and **~15ms** with the `@cap-js` database services. @@ -502,15 +512,22 @@ The combination of the above-mentioned improvements commonly leads to significan -While we were able to keep all public APIs stable, we had to apply changes and fixes to some **undocumented behaviours and internal APIs** in the new implementation. While not formally breaking changes, you may have used or relied on these undocumented APIs and behaviours. In that case, you can find instructions about how to resolve this in the following sections. +While we were able to keep all public APIs stable, we had to apply changes and fixes to some **undocumented behaviours and internal APIs** in the `@cap-js` database service implementation. While not formally breaking changes, you may have used or relied on these undocumented APIs and behaviours. In that case, you can find instructions about how to resolve this in the following sections. > These apply to all new database services: SQLiteService, HANAService, and PostgresService. -### Use Old and New in Parallel {.node} +### Use Legacy and `@cap-js` database services in Parallel {.node} + +::: danger This is not possible with CDS 9 + +The legacy database services have been removed with CDS 9. +Running your app with both services at the same time is only supported with CDS 8 + +::: -During migration, you may want to occasionally run and test your app with both the new SQLite service and the old one. You can accomplish this as follows: +During migration, you may want to occasionally run and test your app with both the `@cap-js` SQLite service and the legacy one. You can accomplish this as follows: 1. Add the new service with `--no-save`: ```sh @@ -542,9 +559,9 @@ During migration, you may want to occasionally run and test your app with both t ``` -### Avoid UNIONs and JOINs {.node} +### Avoid `UNION`s and `JOIN`s {.node} -Many advanced features supported by the new database services, like path expressions or deep expands, rely on the ability to infer queries from CDS models. This task gets extremely complex when adding UNIONs and JOINs to the equation — at least the effort and overhead is hardly matched by generated value. Therefore, we dropped support of UNIONs and JOINs in CQN queries. +Many advanced features supported by the `@cap-js` database services, like path expressions or deep expands, rely on the ability to infer queries from CDS models. This task gets extremely complex when adding `UNION`s and `JOIN`s to the equation — at least the effort and overhead is hardly matched by generated value. Therefore, we dropped support of `UNION`s and `JOIN`s in CQN queries. For example, this means queries like these are deprecated / not supported any longer: @@ -570,7 +587,7 @@ Mitigations: ### Fixed Localized Data {.node} -Formerly, when reading data using `cds.ql`, this *always* returned localized data. For example: +In the legacy database services, when reading data using `cds.ql`, this *always* returned localized data. For example: ```js SELECT.from(Books) // always read from localized.Books instead @@ -583,19 +600,19 @@ SELECT.localized(Books) // reads localized data SELECT.from(Books) // reads plain data ``` -::: details No changes to app services behaviour +::: details No changes to app services behavior -Generic application service handlers use *SELECT.localized* to request localized data from the database. Hence, CAP services automatically serve localized data as before. +Generic application service handlers use `SELECT.localized` to request localized data from the database. Hence, CAP services automatically serve localized data as before. ::: ### Skipped Virtuals {.node} -In contrast to their former behaviour, new database services ignore all virtual elements and hence don't add them to result set entries. Selecting only virtual elements in a query leads to an error. +In contrast to their former behaviour, `@cap-js` database services ignore all virtual elements and hence don't add them to result set entries. Selecting only virtual elements in a query leads to an error. ::: details Reasoning -Virtual elements are meant to be calculated and filled in by custom handlers of your application services. Nevertheless, the old database services always returned `null`, or specified `default` values for virtual elements. This behavior was removed, as it provides very little value, if at all. +Virtual elements are meant to be calculated and filled in by custom handlers of your application services. Nevertheless, the legacy database services always returned `null`, or specified `default` values for virtual elements. This behavior was removed, as it provides very little value, if at all. ::: @@ -608,7 +625,7 @@ entity Foo { } ``` -The behaviour has changed to: +The behavior has changed to: ```js [dev] cds repl @@ -625,7 +642,7 @@ Before, both `<>` and `!=` were translated to `name <> 'John' OR name is null`. ::: warning -This is a breaking change in regard to the previous implementation. +This is a breaking change in regard to the legacy implementation. ::: ### Miscellaneous {.node} diff --git a/guides/databases.md b/guides/databases.md index ab2325c95..ab2b45c09 100644 --- a/guides/databases.md +++ b/guides/databases.md @@ -24,7 +24,11 @@ impl-variants: true ### Migrating to the `@cap-js/` Database Services? {.node} -With CDS 8, the [`@cap-js`](https://github.com/cap-js/cds-dbs) database services for SQLite, PostgreSQL, and SAP HANA are generally available. It's highly recommended to migrate. You can find instructions in the [migration guide](databases-sqlite#migration). Although the guide is written in the context of the SQLite Service, the same hints apply to PostgreSQL and SAP HANA. +Since CDS 8, the [`@cap-js`](https://github.com/cap-js/cds-dbs) database services for SQLite, PostgreSQL, and SAP HANA have been generally available. You can find instructions in the [migration guide](databases-sqlite#migration). Although the guide is written in the context of the SQLite Service, the same hints apply to PostgreSQL and SAP HANA. + +:::info Migration Required +Starting with CDS 9, the [`@cap-js`](https://github.com/cap-js/cds-dbs) database services are the default and **only** supported CAP database runtime. If you haven’t migrated yet, we strongly recommend doing so. +::: ### Adding Database Packages {.node} @@ -36,27 +40,26 @@ Following are cds-plugin packages for CAP Node.js runtime that support the respe | **[SQLite](databases-sqlite)** | [`@cap-js/sqlite`](https://www.npmjs.com/package/@cap-js/sqlite) | recommended for development | | **[PostgreSQL](databases-postgres)** | [`@cap-js/postgres`](https://www.npmjs.com/package/@cap-js/postgres) | maintained by community + CAP team | - -> Follow the preceding links to find specific information for each. In general, all you need to do is to install one of the database packages, as follows: Using SQLite for development: ```sh -npm add @cap-js/sqlite -D +cds add sqlite ``` Using SAP HANA for production: ```sh -npm add @cap-js/hana +cds add hana ``` - -::: details Prefer `cds add hana` ... +After that, run `npm install` to install the packages. + +:::info prefer `cds add …` over `npm add …` -... which also does the equivalent of `npm add @cap-js/hana` but in addition cares for updating `mta.yaml` and other deployment resources as documented in the [deployment guide](deployment/to-cf#_1-sap-hana-database). +It does the equivalent of e.g. `npm add @cap-js/hana` but in addition cares for updating `mta.yaml` and other deployment resources as documented in the [deployment guide](deployment/to-cf#_1-sap-hana-database). ::: @@ -64,19 +67,18 @@ npm add @cap-js/hana The afore-mentioned packages use `cds-plugin` techniques to automatically configure the primary database with `cds.env`. For example, if you added SQLite and SAP HANA, this effectively results in this auto-wired configuration: - ```json {"cds":{ "requires": { "db": { "[development]": { "kind": "sqlite", "impl": "@cap-js/sqlite", "credentials": { "url": "memory" } }, - "[production]": { "kind": "hana", "impl": "@cap-js/hana", "deploy-format": "hdbtable" } + "[production]": { "kind": "hana", "impl": "@cap-js/hana" } } } }} ``` -::: details In contrast to pre-CDS 7 setups this means... +::: warning In contrast to pre-CDS 7 setups this means... 1. You don't need to — and should not — add direct dependencies to driver packages, like [`hdb`](https://www.npmjs.com/package/hdb) or [`sqlite3`](https://www.npmjs.com/package/sqlite3) anymore in your *package.json* files. 2. You don't need to configure `cds.requires.db` anymore, unless you want to override defaults brought with the new packages. @@ -114,7 +116,7 @@ The auto-wired configuration uses configuration presets, which are automatically The config options are as follows: -- `kind` — a name of a preset, like `sql`, `sqlite`, `postgres`, or `hana` +- `kind` — a name of a preset, like `sqlite`, `postgres`, or `hana` - `impl` — the module name of a CAP database service implementation - `credentials` — an object with db-specific configurations, most commonly `url` @@ -345,6 +347,8 @@ Select.from(AUTHOR) ### Standard Operators {.node} + + The database services guarantee the identical behavior of these operators: * `==`, `=` — with `=` null being translated to `is null` @@ -360,7 +364,7 @@ The operator mappings are available for runtime queries only, but not in CDS fil ### Session Variables {.node} -The API shown after this, which includes the function `session_context()` and specific pseudo variable names, is supported by **all** new database services, that is, *SQLite*, *PostgreSQL* and *SAP HANA*. +The API shown after this, which includes the function `session_context()` and specific pseudo variable names, is supported by **all** [`@cap-js`](https://github.com/cap-js/cds-dbs) database services. This allows you to write the respective code once and run it on all these databases: ```sql @@ -397,7 +401,9 @@ db.queryForList("SELECT from sqlite_schema where name like ?", name); ### Reading `LargeBinary` / BLOB {.node} -Formerly, `LargeBinary` elements (or BLOBs) were always returned as any other data type. Now, they're skipped from `SELECT *` queries. Yet, you can still enforce reading BLOBs by explicitly selecting them. Then the BLOB properties are returned as readable streams. +Formerly, `LargeBinary` elements (or BLOBs) were always returned as any other data type. +With the [`@cap-js`](https://github.com/cap-js/cds-dbs) database services, they're skipped from `SELECT *` queries. +Yet, you can still enforce reading BLOBs by explicitly selecting them. The selected BLOB properties are returned as readable streams. ```js SELECT.from(Books) //> [{ ID, title, ..., image1, image2 }] // [!code --] @@ -470,7 +476,7 @@ service CatalogService { ::: -Generate an SQL DDL script by running this in the root directory containing both *.cds* files: +Generate the SQL DDL script by running the following command in the root directory that contains your *.cds* files:
@@ -651,24 +657,26 @@ In addition, you can use the following annotations to fine-tune generated SQL. ### @cds.persistence.skip -Add `@cds.persistence.skip` to an entity to indicate that this entity should be skipped from generated DDL scripts, and also no SQL views to be generated on top of it: +Use `@cds.persistence.skip` on an entity to exclude it from all generated DDL artifacts. +When this annotation is present, the CDS compiler creates **neither** a table for the entity **nor** any SQL views based on it: ```cds @cds.persistence.skip -entity Foo {...} //> No SQL table will be generated -entity Bar as select from Foo; //> No SQL view will be generated +entity Foo {...} // → no SQL table is generated +entity Bar as select from Foo; // → no SQL view is generated ``` ### @cds.persistence.exists -Add `@cds.persistence.exists` to an entity to indicate that this entity should be skipped from generated DDL scripts. In contrast to `@cds.persistence.skip` a database relation is expected to exist, so we can generate SQL views on top. +Use `@cds.persistence.exists` on an entity when the underlying table already exists in the database. +The CDS compiler therefore **skips** table creation but **still** generates SQL views that reference the entity: ```cds @cds.persistence.exists -entity Foo {...} //> No SQL table will be generated -entity Bar as select from Foo; //> The SQL view will be generated +entity Foo {...} // → no SQL table is generated (assumed to exist) +entity Bar as select from Foo; // → SQL view is generated ``` ::: details On SAP HANA ... @@ -735,9 +743,8 @@ The following rules apply: a potential name mapping yourself, for example, for structured elements. - Annotation `@sql.prepend` is only supported for entities translating to tables. It can't be used with views or with elements. -- For SAP HANA tables, there's an implicit `@sql.prepend: 'COLUMN'` that is overwritten by an explicitly provided `@sql.prepend`. -* Both `@sql.prepend` and `@sql.append` are disallowed in SaaS extension projects. +- Both `@sql.prepend` and `@sql.append` are disallowed in SaaS extension projects. If you use native database clauses in combination with `@cds.persistence.journal`, see [Schema Evolution Support of Native Database Clauses](databases-hana#schema-evolution-native-db-clauses). @@ -745,7 +752,10 @@ If you use native database clauses in combination with `@cds.persistence.journal #### Creating a Row Table on SAP HANA -By using `@sql.prepend: 'ROW'`, you can create a row table: +For SAP HANA tables, CDS creates **column** tables by default via an implicit `@sql.prepend: 'COLUMN'`. +You can override this default with your own `@sql.prepend`. + +Use `@sql.prepend: 'ROW'` to generate a **row** table instead: ```cds @sql.prepend: 'ROW' @@ -754,7 +764,7 @@ entity E { } ``` -Run `cds compile - 2 hdbtable` on the previous sample and this is the result: +Run `cds compile -2 hdbtable` on the previous sample and this is the result: ```sql [E.hdbtable] ROW TABLE E ( @@ -764,6 +774,7 @@ ROW TABLE E ( ``` [Learn more about Columnar and Row-Based Data Storage](https://help.sap.com/docs/hana-cloud-database/sap-hana-cloud-sap-hana-database-administration-guide/columnar-and-row-based-data-storage){.learn-more} + ### Reserved Words The CDS compiler and CAP runtimes provide smart quoting for reserved words in SQLite and in SAP HANA so that they can still be used in most situations. But in general reserved words can't be used as identifiers. The list of reserved words varies per database. @@ -847,7 +858,7 @@ entity Genres { } ``` -As a special case, a referential constraint with `delete cascade` is also generated +As a special case, a referential constraint with `ON DELETE CASCADE` is also generated for the text table of a [localized entity](../guides/localized-data#localized-data), although no managed association is present in the `texts` entity. @@ -894,7 +905,7 @@ To switch on the same mappings for your CDL files, you have to set: cds.cdsc.standardDatabaseFunctions = true ::: tip -this will be the default starting with `@sap/cds-compiler >= 9` and hence is only needed for earlier versions. +this will be the default starting with `@sap/cds-compiler >= 6` and hence is only needed for earlier versions. :::