From 65c8c82f745e0097fab6ca8164a2ede8400da803 Mon Sep 17 00:00:00 2001 From: Christian Georgi Date: Wed, 24 Feb 2021 17:26:29 +0100 Subject: [PATCH 01/11] Showcase how to integrate DB-specific functions (#201) Augment `AdminService.Author` by 2 fields `age` and `lifetime` whose values are computed by SQLite and HANA-specific functions. Don't do this in bookshop directly, to keep it simple. Instead, use the fiori module, which also allows to integrate the fields in the UI. Co-authored-by: Daniel --- fiori/app/_i18n/i18n.properties | 1 + fiori/app/_i18n/i18n_de.properties | 1 + fiori/app/admin/fiori-service.cds | 23 ++++++++++++++++++++++- fiori/db/hana/index.cds | 10 ++++++++++ fiori/db/index.cds | 8 ++++++++ fiori/db/sqlite/index.cds | 10 ++++++++++ fiori/package.json | 12 +++++++++--- fiori/test/requests.http | 12 ++++++++++++ 8 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 fiori/db/hana/index.cds create mode 100644 fiori/db/index.cds create mode 100644 fiori/db/sqlite/index.cds diff --git a/fiori/app/_i18n/i18n.properties b/fiori/app/_i18n/i18n.properties index c1d0293f..83681bcf 100644 --- a/fiori/app/_i18n/i18n.properties +++ b/fiori/app/_i18n/i18n.properties @@ -11,6 +11,7 @@ DateOfBirth = Date of Birth DateOfDeath = Date of Death PlaceOfBirth = Place of Birth PlaceOfDeath = Place of Death +Age = Age Authors = Authors Order = Order Orders = Orders diff --git a/fiori/app/_i18n/i18n_de.properties b/fiori/app/_i18n/i18n_de.properties index 365b45df..7724f685 100644 --- a/fiori/app/_i18n/i18n_de.properties +++ b/fiori/app/_i18n/i18n_de.properties @@ -6,6 +6,7 @@ Authors = Autoren Author = Autor AuthorID = ID des Autors AuthorName = Name des Autors +Age = Alter Name = Name Stock = Bestand Order = Bestellung diff --git a/fiori/app/admin/fiori-service.cds b/fiori/app/admin/fiori-service.cds index 1aeddb9f..83ff758a 100644 --- a/fiori/app/admin/fiori-service.cds +++ b/fiori/app/admin/fiori-service.cds @@ -1,4 +1,4 @@ -using AdminService from '@capire/bookshop'; +using { AdminService } from '../../db'; //////////////////////////////////////////////////////////////////////////// // @@ -39,6 +39,27 @@ annotate AdminService.Books with @( } ); +annotate AdminService.Authors with @( + UI: { + HeaderInfo: { + Description: {Value: lifetime} + }, + Facets: [ + {$Type: 'UI.ReferenceFacet', Label: '{i18n>Details}', Target: '@UI.FieldGroup#Details'}, + {$Type: 'UI.ReferenceFacet', Label: '{i18n>Books}', Target: 'books/@UI.LineItem'}, + ], + FieldGroup#Details: { + Data: [ + {Value: placeOfBirth}, + {Value: placeOfDeath}, + {Value: dateOfBirth}, + {Value: dateOfDeath}, + {Value: age, Label: '{i18n>Age}'}, + ] + }, + } +); + //////////////////////////////////////////////////////////// diff --git a/fiori/db/hana/index.cds b/fiori/db/hana/index.cds new file mode 100644 index 00000000..db46e6d5 --- /dev/null +++ b/fiori/db/hana/index.cds @@ -0,0 +1,10 @@ +// +// Add Author.age and .lifetime with a DB-specific function +// + +using { AdminService } from '..'; + +extend projection AdminService.Authors with { + YEARS_BETWEEN(dateOfBirth, dateOfDeath) as age: Integer, + YEAR(dateOfBirth) || ' – ' || YEAR(dateOfDeath) as lifetime : String +} diff --git a/fiori/db/index.cds b/fiori/db/index.cds new file mode 100644 index 00000000..479fdbfb --- /dev/null +++ b/fiori/db/index.cds @@ -0,0 +1,8 @@ +using { sap.capire.bookshop } from '@capire/bookshop'; + +// Forward-declare calculated fields to be filled in database-specific ways +// TODO find a better way to have 'default' fields that still can be overwritten. +extend bookshop.Authors with { + virtual age: Integer; + virtual lifetime: String; +} diff --git a/fiori/db/sqlite/index.cds b/fiori/db/sqlite/index.cds new file mode 100644 index 00000000..9f2cc3b5 --- /dev/null +++ b/fiori/db/sqlite/index.cds @@ -0,0 +1,10 @@ +// +// Add Author.age and .lifetime with a DB-specific function +// + +using { AdminService } from '..'; + +extend projection AdminService.Authors with { + strftime('%Y',dateOfDeath)-strftime('%Y',dateOfBirth) as age: Integer, + strftime('%Y',dateOfBirth) || ' – ' || strftime('%Y',dateOfDeath) as lifetime : String +} diff --git a/fiori/package.json b/fiori/package.json index a4028d2e..7cbf5f3b 100644 --- a/fiori/package.json +++ b/fiori/package.json @@ -8,7 +8,7 @@ "@capire/common": "*", "@sap/cds": "^4", "express": "^4.17.1", - "passport": "0.4.1" + "passport": "^0.4.1" }, "scripts": { "start": "cds run --in-memory?", @@ -23,8 +23,14 @@ "kind": "odata", "model": "@capire/orders" }, "db": { - "kind": "sql" + "kind": "sql", + "[development]": { + "model": "db/sqlite" + }, + "[production]": { + "model": "db/hana" + } } } } -} \ No newline at end of file +} diff --git a/fiori/test/requests.http b/fiori/test/requests.http index 95076ce3..badacbfe 100644 --- a/fiori/test/requests.http +++ b/fiori/test/requests.http @@ -63,3 +63,15 @@ Content-Type: application/json ### Get active order GET {{bookshop}}/orders/Orders(ID={{newOrderID}},IsActiveEntity=true) + +### Create author +POST {{bookshop}}/admin/Authors +Content-Type: application/json +Authorization: Basic alice: + +{ + "ID": 200, + "name": "William Shakespeare", + "dateOfBirth": "1564-04-26", + "dateOfDeath": "1616-04-23" +} From 76540122929c5406c0b2db466dcbb02378e38bb9 Mon Sep 17 00:00:00 2001 From: Iwona Hahn Date: Thu, 25 Feb 2021 22:50:54 +0100 Subject: [PATCH 02/11] cosmetics codetour --- .tours/samples.tour | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.tours/samples.tour b/.tours/samples.tour index d3c5a22d..b3a15c28 100644 --- a/.tours/samples.tour +++ b/.tours/samples.tour @@ -5,7 +5,7 @@ { "title": "Welcome", "file": "README.md", - "description": "### Welcome to CAP Samples!\n\nThis tour leads you through a collection of samples for the [SAP Cloud Application Programming Model](https://cap.cloud.sap)\nYou will learn which features of the programming models are demonstrated in which sample.\n\nLet's start!", + "description": "### Welcome to CAP Samples!\n\nThis tour leads you through a collection of samples for the [SAP Cloud Application Programming Model (CAP)](https://cap.cloud.sap).\nYou will learn which features of the programming model are demonstrated in which sample.\n\nLet's start!", "line": 2, "selection": { "start": { @@ -133,4 +133,4 @@ ], "isPrimary": true, "description": "Overview of CAP Samples for Node.js" -} \ No newline at end of file +} From c46a82d0f89d136e38d1837d64c9820195846cdd Mon Sep 17 00:00:00 2001 From: Christian Georgi Date: Fri, 26 Feb 2021 16:34:21 +0100 Subject: [PATCH 03/11] Codetour for DB functions --- .tours/db-native.tour | 105 ++++++++++++++++++++++++++++++++++++++++++ fiori/package.json | 12 ++++- 2 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 .tours/db-native.tour diff --git a/.tours/db-native.tour b/.tours/db-native.tour new file mode 100644 index 00000000..f0b0e9a4 --- /dev/null +++ b/.tours/db-native.tour @@ -0,0 +1,105 @@ +{ + "$schema": "https://aka.ms/codetour-schema", + "title": "Database Functions", + "steps": [ + { + "title": "Introduction", + "description": "### Database Functions in CDS Models\n\nIn this tour, you will learn how to add database-specific funtions to CDS models in your application." + }, + { + "file": "bookshop/db/schema.cds", + "description": "#### Basic Schema\n\nWe want to add 2 fields to the `Authors` entity, one for the author's age and one for the span of years that she or he lived. These 2 fields can be computed out of the existing `dateOfBirth` and `dateOfDeath` fields.", + "selection": { + "start": { + "line": 19, + "character": 1 + }, + "end": { + "line": 21, + "character": 1 + } + }, + "title": "Base fields in Author" + }, + { + "file": "bookshop/srv/admin-service.cds", + "description": "This is how the `Authors` entity gets exposed in an OData or Rest service.\n\nIn the next step you will see how we extend this projection.", + "selection": { + "start": { + "line": 4, + "character": 1 + }, + "end": { + "line": 5, + "character": 1 + } + }, + "title": "Authors service" + }, + { + "file": "fiori/db/sqlite/index.cds", + "description": "#### SQLite implementation\n\nHere is the first implementation for SQLite. It computes the 2 fields `age` and `lifetime` through SQLite's [strftime](https://sqlite.org/lang_datefunc.html) function.\n\nThrough the [`extend projection`](https://cap.cloud.sap/docs/cds/cdl#extend-view) clause you can add additional fields to projection entities. These are deployed as database views, which is why we can integrate the database functions in the first place.", + "selection": { + "start": { + "line": 7, + "character": 1 + }, + "end": { + "line": 11, + "character": 1 + } + }, + "title": "SQLite implementation" + }, + { + "file": "fiori/db/hana/index.cds", + "description": "#### SAP HANA Implementation\n\nThis is the second implementation for SAP HANA. It computes the same 2 fields `age` and `lifetime` through the [YEARS_BETWEEN](https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/7c0d2c161ea34def86de3f5eadd6a0af.html) and [YEAR](https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/20f5fac6751910148dabd3c6821f907d.html) functions of SAP HANA.\n\n#### File Layout\n\nNote the path of the `.cds` file we are in: it's in a subfolder of `db`, so that it's _not_ automatically picked up when we start the application. The same is true for the SQLite implementation: it's in a separate `db/sqlite/`\nfolder as well. In the next step you will see how these files are loaded.", + "selection": { + "start": { + "line": 7, + "character": 1 + }, + "end": { + "line": 11, + "character": 1 + } + }, + "title": "SAP HANA implementation" + }, + { + "file": "fiori/package.json", + "description": "The `cds` section in `package.json` is a place to configure which of the `db/sqlite` and `db/hana` folders are used for which database.\nWe use [Node.js profiles](https://cap.cloud.sap/docs/node.js/cds-env#profiles) to separate the configuration.\nIn the `development` profile, you can see that `db/sqlite` is set as the model, while the `db/hana` folder is configured in the `production` profile.", + "line": 17, + "title": "Configuration" + }, + { + "file": "fiori/package.json", + "description": "To run with `development` and an in-memory SQLite database, you don'y need to do anything special, because it's activated by default. Just run\n\n>> cds watch fiori\n\nThen open http://localhost:4004/admin/Authors to see the 2 new fields.\n", + "line": 28, + "title": "Run with SQLite" + }, + { + "file": "fiori/package.json", + "description": "#### Deploy the CDS model to SAP HANA:\n\nTo 'activate' SAP HANA through the `production` profile, you can use the global `--production` flag:\n\n>> cd fiori; cds deploy --to hana --production\n\n[Learn more about SAP HANA deployment](https://cap.cloud.sap/docs/guides/databases#get-hana)\n\n#### Run the application\n\n>> cd fiori; cds watch --production\n\nThe service on http://localhost:4004/admin/Authors is the same as before, but this time the `Authors` entity is backed by a database view with an SAP HANA function.\n\n#### More\nIf you don't see data, you can add some in the next step.", + "line": 31, + "title": "Run with SAP HANA" + }, + { + "file": "fiori/test/requests.http", + "description": "### Add more data\n\nOptionally you may add some data by clicking on the _Send Request_ link (provided by the [Rest client](https://marketplace.visualstudio.com/items?itemName=humao.rest-client) extension).\n\n### Summary\n\nThat's it! You have seen \n- How to integrate database-specific functions in a CDS model\n- How to switch between the two implementations for SQLite and SAP HANA.", + "line": 68, + "selection": { + "start": { + "line": 67, + "character": 1 + }, + "end": { + "line": 73, + "character": 1 + } + }, + "title": "Wrap-up" + } + ], + "ref": "master" +} \ No newline at end of file diff --git a/fiori/package.json b/fiori/package.json index 7cbf5f3b..5da44c3c 100644 --- a/fiori/package.json +++ b/fiori/package.json @@ -15,12 +15,20 @@ "watch": "cds watch" }, "cds": { + "hana": { + "deploy-format": "hdbtable" + }, "requires": { + "auth": { + "strategy": "dummy" + }, "ReviewsService": { - "kind": "odata", "model": "@capire/reviews" + "kind": "odata", + "model": "@capire/reviews" }, "OrdersService": { - "kind": "odata", "model": "@capire/orders" + "kind": "odata", + "model": "@capire/orders" }, "db": { "kind": "sql", From d0d95f3c425bd94026f94a91868f81049ac48f2c Mon Sep 17 00:00:00 2001 From: Iwona Hahn Date: Fri, 26 Feb 2021 17:14:49 +0100 Subject: [PATCH 04/11] first review, minor edits --- .tours/db-native.tour | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.tours/db-native.tour b/.tours/db-native.tour index f0b0e9a4..7c63ac2f 100644 --- a/.tours/db-native.tour +++ b/.tours/db-native.tour @@ -8,7 +8,7 @@ }, { "file": "bookshop/db/schema.cds", - "description": "#### Basic Schema\n\nWe want to add 2 fields to the `Authors` entity, one for the author's age and one for the span of years that she or he lived. These 2 fields can be computed out of the existing `dateOfBirth` and `dateOfDeath` fields.", + "description": "#### Basic Schema\n\nWe want to add two fields to the `Authors` entity, one for the author's age and one for the span of years that she or he lived. These two fields can be computed out of the existing `dateOfBirth` and `dateOfDeath` fields.", "selection": { "start": { "line": 19, @@ -23,7 +23,7 @@ }, { "file": "bookshop/srv/admin-service.cds", - "description": "This is how the `Authors` entity gets exposed in an OData or Rest service.\n\nIn the next step you will see how we extend this projection.", + "description": "This is how the `Authors` entity gets exposed in an OData or REST service.\n\nIn the next step you will see how we extend this projection.", "selection": { "start": { "line": 4, @@ -38,7 +38,7 @@ }, { "file": "fiori/db/sqlite/index.cds", - "description": "#### SQLite implementation\n\nHere is the first implementation for SQLite. It computes the 2 fields `age` and `lifetime` through SQLite's [strftime](https://sqlite.org/lang_datefunc.html) function.\n\nThrough the [`extend projection`](https://cap.cloud.sap/docs/cds/cdl#extend-view) clause you can add additional fields to projection entities. These are deployed as database views, which is why we can integrate the database functions in the first place.", + "description": "#### SQLite implementation\n\nHere is the first implementation for SQLite. It computes the two fields `age` and `lifetime` through SQLite's [strftime](https://sqlite.org/lang_datefunc.html) function.\n\nThrough the [`extend projection`](https://cap.cloud.sap/docs/cds/cdl#extend-view) clause you can add additional fields to projection entities. These are deployed as database views, which is why we can integrate the database functions in the first place.", "selection": { "start": { "line": 7, @@ -53,7 +53,7 @@ }, { "file": "fiori/db/hana/index.cds", - "description": "#### SAP HANA Implementation\n\nThis is the second implementation for SAP HANA. It computes the same 2 fields `age` and `lifetime` through the [YEARS_BETWEEN](https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/7c0d2c161ea34def86de3f5eadd6a0af.html) and [YEAR](https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/20f5fac6751910148dabd3c6821f907d.html) functions of SAP HANA.\n\n#### File Layout\n\nNote the path of the `.cds` file we are in: it's in a subfolder of `db`, so that it's _not_ automatically picked up when we start the application. The same is true for the SQLite implementation: it's in a separate `db/sqlite/`\nfolder as well. In the next step you will see how these files are loaded.", + "description": "#### SAP HANA Implementation\n\nThis is the second implementation for SAP HANA. It computes the same two fields `age` and `lifetime` through the [YEARS_BETWEEN](https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/7c0d2c161ea34def86de3f5eadd6a0af.html) and [YEAR](https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/20f5fac6751910148dabd3c6821f907d.html) functions of SAP HANA.\n\n#### File Layout\n\nNote the path of the `.cds` file we are in: it's in a subfolder of `db`, so that it's _not_ automatically picked up when we start the application. The same is true for the SQLite implementation: it's in a separate `db/sqlite/`\nfolder as well. In the next step you will see how these files are loaded.", "selection": { "start": { "line": 7, @@ -74,19 +74,19 @@ }, { "file": "fiori/package.json", - "description": "To run with `development` and an in-memory SQLite database, you don'y need to do anything special, because it's activated by default. Just run\n\n>> cds watch fiori\n\nThen open http://localhost:4004/admin/Authors to see the 2 new fields.\n", + "description": "To run with `development` and an in-memory SQLite database, you don'y need to do anything special, because it's activated by default. Just run:\n\n>> cds watch fiori\n\nThen open http://localhost:4004/admin/Authors to see the two new fields.\n", "line": 28, "title": "Run with SQLite" }, { "file": "fiori/package.json", - "description": "#### Deploy the CDS model to SAP HANA:\n\nTo 'activate' SAP HANA through the `production` profile, you can use the global `--production` flag:\n\n>> cd fiori; cds deploy --to hana --production\n\n[Learn more about SAP HANA deployment](https://cap.cloud.sap/docs/guides/databases#get-hana)\n\n#### Run the application\n\n>> cd fiori; cds watch --production\n\nThe service on http://localhost:4004/admin/Authors is the same as before, but this time the `Authors` entity is backed by a database view with an SAP HANA function.\n\n#### More\nIf you don't see data, you can add some in the next step.", + "description": "#### Deploy the CDS Model to SAP HANA:\n\nTo 'activate' SAP HANA through the `production` profile, you can use the global `--production` flag:\n\n>> cd fiori; cds deploy --to hana --production\n\n[Learn more about SAP HANA deployment](https://cap.cloud.sap/docs/guides/databases#get-hana)\n\n#### Run the Application\n\n>> cd fiori; cds watch --production\n\nThe service on http://localhost:4004/admin/Authors is the same as before, but this time the `Authors` entity is backed by a database view with an SAP HANA function.\n\n#### More\nIf you don't see data, you can add some in the next step.", "line": 31, "title": "Run with SAP HANA" }, { "file": "fiori/test/requests.http", - "description": "### Add more data\n\nOptionally you may add some data by clicking on the _Send Request_ link (provided by the [Rest client](https://marketplace.visualstudio.com/items?itemName=humao.rest-client) extension).\n\n### Summary\n\nThat's it! You have seen \n- How to integrate database-specific functions in a CDS model\n- How to switch between the two implementations for SQLite and SAP HANA.", + "description": "### Add More Data\n\nOptionally you may add some data by clicking on the _Send Request_ link (provided by the [REST client](https://marketplace.visualstudio.com/items?itemName=humao.rest-client) extension).\n\n### Summary\n\nThat's it! You have seen: \n- How to integrate database-specific functions in a CDS model.\n- How to switch between the two implementations for SQLite and SAP HANA.", "line": 68, "selection": { "start": { From 85dd8558f43cdf40e29935bd2a25829cf1f96e36 Mon Sep 17 00:00:00 2001 From: Christian Georgi Date: Mon, 1 Mar 2021 14:37:57 +0100 Subject: [PATCH 05/11] Some more explanation around file structure --- .tours/db-native.tour | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.tours/db-native.tour b/.tours/db-native.tour index 7c63ac2f..fe4deaad 100644 --- a/.tours/db-native.tour +++ b/.tours/db-native.tour @@ -8,7 +8,7 @@ }, { "file": "bookshop/db/schema.cds", - "description": "#### Basic Schema\n\nWe want to add two fields to the `Authors` entity, one for the author's age and one for the span of years that she or he lived. These two fields can be computed out of the existing `dateOfBirth` and `dateOfDeath` fields.", + "description": "#### Basic Schema\n\nWe want to add two fields to the `Authors` entity, one for the author's age and one for the span of years that she or he lived.\n\nThese two fields can be computed out of the existing `dateOfBirth` and `dateOfDeath` fields.", "selection": { "start": { "line": 19, @@ -38,7 +38,7 @@ }, { "file": "fiori/db/sqlite/index.cds", - "description": "#### SQLite implementation\n\nHere is the first implementation for SQLite. It computes the two fields `age` and `lifetime` through SQLite's [strftime](https://sqlite.org/lang_datefunc.html) function.\n\nThrough the [`extend projection`](https://cap.cloud.sap/docs/cds/cdl#extend-view) clause you can add additional fields to projection entities. These are deployed as database views, which is why we can integrate the database functions in the first place.", + "description": "#### SQLite implementation\n\nHere is the first implementation for SQLite. It computes the two fields `age` and `lifetime` through SQLite's [strftime](https://sqlite.org/lang_datefunc.html) function.\n\nThrough the [`extend projection`](https://cap.cloud.sap/docs/cds/cdl#extend-view) clause you can add additional fields to projection entities. These are deployed as database views, which is why we can integrate the database functions in the first place.\n", "selection": { "start": { "line": 7, @@ -53,7 +53,7 @@ }, { "file": "fiori/db/hana/index.cds", - "description": "#### SAP HANA Implementation\n\nThis is the second implementation for SAP HANA. It computes the same two fields `age` and `lifetime` through the [YEARS_BETWEEN](https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/7c0d2c161ea34def86de3f5eadd6a0af.html) and [YEAR](https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/20f5fac6751910148dabd3c6821f907d.html) functions of SAP HANA.\n\n#### File Layout\n\nNote the path of the `.cds` file we are in: it's in a subfolder of `db`, so that it's _not_ automatically picked up when we start the application. The same is true for the SQLite implementation: it's in a separate `db/sqlite/`\nfolder as well. In the next step you will see how these files are loaded.", + "description": "#### SAP HANA Implementation\n\nThis is the second implementation for SAP HANA. It computes the same two fields `age` and `lifetime` through the [YEARS_BETWEEN](https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/7c0d2c161ea34def86de3f5eadd6a0af.html) and [YEAR](https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/20f5fac6751910148dabd3c6821f907d.html) functions of SAP HANA.\n\n#### File Layout and Code Structure\n\nNote the path of the `.cds` file we are in: it's in a subfolder of `db`, so that it's _not_ automatically picked up when we start the application. The same is true for the SQLite implementation: it's in a separate `db/sqlite/`\nfolder as well. In the next step you will see how these files are loaded.\n\nAlso, we choose to implement all of that as extension of the original bookshop here in the _fiori_ package. See the first [CAP Samples] code tour for more on the different packages of this reposiory.", "selection": { "start": { "line": 7, @@ -68,13 +68,13 @@ }, { "file": "fiori/package.json", - "description": "The `cds` section in `package.json` is a place to configure which of the `db/sqlite` and `db/hana` folders are used for which database.\nWe use [Node.js profiles](https://cap.cloud.sap/docs/node.js/cds-env#profiles) to separate the configuration.\nIn the `development` profile, you can see that `db/sqlite` is set as the model, while the `db/hana` folder is configured in the `production` profile.", + "description": "#### Configuration\n\nThe `cds` section in `package.json` is a place to configure which of the `db/sqlite` and `db/hana` folders are used for which database.\nWe use [Node.js profiles](https://cap.cloud.sap/docs/node.js/cds-env#profiles) to separate the configuration.\nIn the `development` profile, you can see that `db/sqlite` is set as the model, while the `db/hana` folder is configured in the `production` profile.", "line": 17, "title": "Configuration" }, { "file": "fiori/package.json", - "description": "To run with `development` and an in-memory SQLite database, you don'y need to do anything special, because it's activated by default. Just run:\n\n>> cds watch fiori\n\nThen open http://localhost:4004/admin/Authors to see the two new fields.\n", + "description": "#### Run with SQLite\n\nTo run with `development` and an in-memory SQLite database, you don'y need to do anything special, because it's activated by default. Just run:\n\n>> cds watch fiori\n\nThen open http://localhost:4004/admin/Authors to see the two new fields.\n", "line": 28, "title": "Run with SQLite" }, @@ -86,7 +86,7 @@ }, { "file": "fiori/test/requests.http", - "description": "### Add More Data\n\nOptionally you may add some data by clicking on the _Send Request_ link (provided by the [REST client](https://marketplace.visualstudio.com/items?itemName=humao.rest-client) extension).\n\n### Summary\n\nThat's it! You have seen: \n- How to integrate database-specific functions in a CDS model.\n- How to switch between the two implementations for SQLite and SAP HANA.", + "description": "### Add More Data\n\nOptionally you may add some `Authors` data by clicking on the _Send Request_ link (provided by the [REST client](https://marketplace.visualstudio.com/items?itemName=humao.rest-client) extension).", "line": 68, "selection": { "start": { @@ -98,7 +98,11 @@ "character": 1 } }, - "title": "Wrap-up" + "title": "Add Data" + }, + { + "title": "Wrap-up", + "description": "### Summary\n\nThat's it! You have seen: \n- How to integrate database-specific functions in a CDS model.\n- How to switch between the two implementations for SQLite and SAP HANA." } ], "ref": "master" From 76d1b1865bfbef8a3c027eb173f5be5b2597ad0a Mon Sep 17 00:00:00 2001 From: Iwona Hahn Date: Mon, 1 Mar 2021 17:24:53 +0100 Subject: [PATCH 06/11] minor edits --- .tours/db-native.tour | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.tours/db-native.tour b/.tours/db-native.tour index fe4deaad..035ef298 100644 --- a/.tours/db-native.tour +++ b/.tours/db-native.tour @@ -4,7 +4,7 @@ "steps": [ { "title": "Introduction", - "description": "### Database Functions in CDS Models\n\nIn this tour, you will learn how to add database-specific funtions to CDS models in your application." + "description": "### Database Functions in CDS Models\n\nIn this tour, you'll learn how to add database-specific functions to CDS models in your application." }, { "file": "bookshop/db/schema.cds", @@ -23,7 +23,7 @@ }, { "file": "bookshop/srv/admin-service.cds", - "description": "This is how the `Authors` entity gets exposed in an OData or REST service.\n\nIn the next step you will see how we extend this projection.", + "description": "This is how the `Authors` entity gets exposed in an OData or REST service.\n\nIn the next step, you'll see how we extend this projection.", "selection": { "start": { "line": 4, @@ -38,7 +38,7 @@ }, { "file": "fiori/db/sqlite/index.cds", - "description": "#### SQLite implementation\n\nHere is the first implementation for SQLite. It computes the two fields `age` and `lifetime` through SQLite's [strftime](https://sqlite.org/lang_datefunc.html) function.\n\nThrough the [`extend projection`](https://cap.cloud.sap/docs/cds/cdl#extend-view) clause you can add additional fields to projection entities. These are deployed as database views, which is why we can integrate the database functions in the first place.\n", + "description": "#### SQLite Implementation\n\nHere's the first implementation for SQLite. It computes the two fields `age` and `lifetime` through SQLite's [strftime](https://sqlite.org/lang_datefunc.html) function.\n\nThrough the [`extend projection`](https://cap.cloud.sap/docs/cds/cdl#extend-view) clause you can add additional fields to projection entities. These are deployed as database views, which is why we can integrate the database functions in the first place.\n", "selection": { "start": { "line": 7, @@ -53,7 +53,7 @@ }, { "file": "fiori/db/hana/index.cds", - "description": "#### SAP HANA Implementation\n\nThis is the second implementation for SAP HANA. It computes the same two fields `age` and `lifetime` through the [YEARS_BETWEEN](https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/7c0d2c161ea34def86de3f5eadd6a0af.html) and [YEAR](https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/20f5fac6751910148dabd3c6821f907d.html) functions of SAP HANA.\n\n#### File Layout and Code Structure\n\nNote the path of the `.cds` file we are in: it's in a subfolder of `db`, so that it's _not_ automatically picked up when we start the application. The same is true for the SQLite implementation: it's in a separate `db/sqlite/`\nfolder as well. In the next step you will see how these files are loaded.\n\nAlso, we choose to implement all of that as extension of the original bookshop here in the _fiori_ package. See the first [CAP Samples] code tour for more on the different packages of this reposiory.", + "description": "#### SAP HANA Implementation\n\nThis is the second implementation for SAP HANA. It computes the same two fields `age` and `lifetime` through the [YEARS_BETWEEN](https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/7c0d2c161ea34def86de3f5eadd6a0af.html) and [YEAR](https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/20f5fac6751910148dabd3c6821f907d.html) functions of SAP HANA.\n\n#### File Layout and Code Structure\n\nNote the path of the `.cds` file we are in: it's in a subfolder of `db`, so that it's _not_ automatically picked up when we start the application. The same is true for the SQLite implementation: it's in a separate `db/sqlite/` folder as well. In the next step, you'll see how these files are loaded.\n\nAlso, we choose to implement all of that as an extension of the original bookshop here in the _fiori_ package. See the first [CAP Samples] code tour for more details on the different packages of this repository.", "selection": { "start": { "line": 7, @@ -74,19 +74,19 @@ }, { "file": "fiori/package.json", - "description": "#### Run with SQLite\n\nTo run with `development` and an in-memory SQLite database, you don'y need to do anything special, because it's activated by default. Just run:\n\n>> cds watch fiori\n\nThen open http://localhost:4004/admin/Authors to see the two new fields.\n", + "description": "#### Run with SQLite\n\nTo run with `development` and an in-memory SQLite database, you don't need to do anything special, because it's activated by default. Just run:\n\n>> cds watch fiori\n\nThen open [http://localhost:4004/admin/Authors](http://localhost:4004/admin/Authors) to see the two new fields.\n", "line": 28, "title": "Run with SQLite" }, { "file": "fiori/package.json", - "description": "#### Deploy the CDS Model to SAP HANA:\n\nTo 'activate' SAP HANA through the `production` profile, you can use the global `--production` flag:\n\n>> cd fiori; cds deploy --to hana --production\n\n[Learn more about SAP HANA deployment](https://cap.cloud.sap/docs/guides/databases#get-hana)\n\n#### Run the Application\n\n>> cd fiori; cds watch --production\n\nThe service on http://localhost:4004/admin/Authors is the same as before, but this time the `Authors` entity is backed by a database view with an SAP HANA function.\n\n#### More\nIf you don't see data, you can add some in the next step.", + "description": "#### Deploy the CDS Model to SAP HANA\n\nTo 'activate' SAP HANA through the `production` profile, you can use the global `--production` flag:\n\n>> cd fiori; cds deploy --to hana --production\n\n[Learn more about SAP HANA deployment](https://cap.cloud.sap/docs/guides/databases#get-hana)\n\n#### Run the Application\n\n>> cd fiori; cds watch --production\n\nThe service on [http://localhost:4004/admin/Authors](http://localhost:4004/admin/Authors) is the same as before, but this time the `Authors` entity is backed by a database view with an SAP HANA function.\n\n#### More\n\nIf you don't see data, you can add some in the next step.", "line": 31, "title": "Run with SAP HANA" }, { "file": "fiori/test/requests.http", - "description": "### Add More Data\n\nOptionally you may add some `Authors` data by clicking on the _Send Request_ link (provided by the [REST client](https://marketplace.visualstudio.com/items?itemName=humao.rest-client) extension).", + "description": "### Add More Data\n\nOptionally you can add some `Authors` data by clicking on the _Send Request_ link (provided by the [REST client](https://marketplace.visualstudio.com/items?itemName=humao.rest-client) extension).", "line": 68, "selection": { "start": { From ebc7017ded7e864c095f9dad4cc4d51dd4c4513f Mon Sep 17 00:00:00 2001 From: Iwona Hahn Date: Mon, 1 Mar 2021 20:42:23 +0100 Subject: [PATCH 07/11] UA review --- reviews/readme.md | 9 ++++++--- samples.md | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/reviews/readme.md b/reviews/readme.md index 5574f752..29f8eff0 100644 --- a/reviews/readme.md +++ b/reviews/readme.md @@ -3,19 +3,22 @@ ## Run all-in-one Open a terminal window and run the bookshop in it: + ```sh npm run bookshop ``` -## Run as separate services +## Run as Separate Services + +Open two terminal windows. In the first one start the reviews service stand-alone: -Open two terminal windows, and in the first one start the reviews service stand-alone: ```sh npm run reviews-service ``` -In the the second one start the bookshop: +In the second one start the bookshop: + ```sh npm run bookshop ``` diff --git a/samples.md b/samples.md index bc5f7f81..0edc9e2e 100644 --- a/samples.md +++ b/samples.md @@ -57,7 +57,7 @@ Each sub directory essentially is an individual npm package arranged in an [all- - [@capire/reviews](reviews) - [@capire/orders](orders) - [@capire/common](common) -- [Adds a SAP Fiori elements application](https://cap.cloud.sap/docs/guides/fiori/) to bookshop, thereby introducing to: +- [Adds an SAP Fiori elements application](https://cap.cloud.sap/docs/guides/fiori/) to bookshop, thereby introducing to: - [OData Annotations](https://cap.cloud.sap/docs/guides/fiori#adding-odata-annotations) in `.cds` files - Support for [Fiori Draft](https://cap.cloud.sap/docs/guides/fiori#draft) - Support for [Value Helps](https://cap.cloud.sap/docs/guides/fiori#value-help) From ae788414f8644a9ab1bcb446796fd18d6c74f0ab Mon Sep 17 00:00:00 2001 From: Iwona Hahn Date: Mon, 1 Mar 2021 20:42:43 +0100 Subject: [PATCH 08/11] promote code tours --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 38e5cef7..21a8310b 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Find here a collection of samples for the [SAP Cloud Application Programming Mod ### Download -If you have [Git](https://git-scm.com/downloads) installed, clone this repo as shown below, otherwise [download as ZIP file](archive/master.zip). +If you've [Git](https://git-scm.com/downloads) installed, clone this repo as shown below, otherwise [download as ZIP file](archive/master.zip). ```sh git clone https://github.com/sap-samples/cloud-cap-samples samples @@ -72,10 +72,14 @@ npm add @capire/common @capire/bookshop ``` +## Code Tours + +Take one of the [guideded tours](.tours) in VS Code through our CAP samples and learn which CAP features are showcased by the different parts of the repository. Just install the [CodeTour extension](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour) for VS Code. We'll add more code tours in the future. Stay tuned! + ## Get Support Check out the documentation at [https://cap.cloud.sap](https://cap.cloud.sap).
-In case you have a question, find a bug, or otherwise need support, please use our [community](https://answers.sap.com/tags/9f13aee1-834c-4105-8e43-ee442775e5ce). +In case you've a question, find a bug, or otherwise need support, use our [community](https://answers.sap.com/tags/9f13aee1-834c-4105-8e43-ee442775e5ce) to get more visibility. ## License From 22ece2e586603f6beba5f39a5d3a6523e3abee9f Mon Sep 17 00:00:00 2001 From: Iwona Hahn Date: Mon, 1 Mar 2021 20:44:05 +0100 Subject: [PATCH 09/11] typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 21a8310b..7bc409bf 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ npm add @capire/common @capire/bookshop ## Code Tours -Take one of the [guideded tours](.tours) in VS Code through our CAP samples and learn which CAP features are showcased by the different parts of the repository. Just install the [CodeTour extension](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour) for VS Code. We'll add more code tours in the future. Stay tuned! +Take one of the [guided tours](.tours) in VS Code through our CAP samples and learn which CAP features are showcased by the different parts of the repository. Just install the [CodeTour extension](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour) for VS Code. We'll add more code tours in the future. Stay tuned! ## Get Support From 2368913612ac07533a4e78dc3aafa1b7f0799934 Mon Sep 17 00:00:00 2001 From: Christian Georgi Date: Tue, 2 Mar 2021 09:09:51 +0100 Subject: [PATCH 10/11] Dummy change --- samples.md | 1 - 1 file changed, 1 deletion(-) diff --git a/samples.md b/samples.md index 0edc9e2e..cf9a60b4 100644 --- a/samples.md +++ b/samples.md @@ -64,7 +64,6 @@ Each sub directory essentially is an individual npm package arranged in an [all- - Serving SAP Fiori apps locally - [The Vue.js app](bookshop/app/vue) imported from bookshop is served as well -
# All-in-one Monorepo From 647ac72588e1aff8cb6c27563063ca7b50294e53 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 2 Mar 2021 17:14:38 +0100 Subject: [PATCH 11/11] Prepare for compiler v2 --- test/cds.ql.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cds.ql.test.js b/test/cds.ql.test.js index a8bfa7be..dfade6b0 100644 --- a/test/cds.ql.test.js +++ b/test/cds.ql.test.js @@ -365,7 +365,7 @@ describe('cds.ql → cqn', () => { }, }) - expect( + if (!is_v2) expect( SELECT.from(Foo).where(`x=`, 1, `or y.z is null and (a>`, 2, `or b=`, 3, `)`) ).to.eql(CQL`SELECT from Foo where x=1 or y.z is null and (a>2 or b=3)`)