From a8a52c0d963dc9f02f41164d9ab5f7a62f5e78e5 Mon Sep 17 00:00:00 2001 From: Bob den Os Date: Tue, 11 Jun 2024 15:53:00 +0200 Subject: [PATCH 1/5] Add Initial quoted mode support --- db-service/lib/cqn2sql.js | 6 ++++++ hana/lib/HANAService.js | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/db-service/lib/cqn2sql.js b/db-service/lib/cqn2sql.js index 1802bd8a9..d026de472 100644 --- a/db-service/lib/cqn2sql.js +++ b/db-service/lib/cqn2sql.js @@ -32,6 +32,12 @@ class CQN2SQLRenderer { this.class = new.target // for IntelliSense this.class._init() // is a noop for subsequent calls this.model = srv?.model + + // Overwrite smart quoting + if (cds.env.cdsc.sqlMapping === 'quoted') { + this.class.prototype.name = (name) => name.id || name + this.class.prototype.quote = (s) => `"${s.replace(/"/g, '""')}"` + } } static _add_mixins(aspect, mixins) { diff --git a/hana/lib/HANAService.js b/hana/lib/HANAService.js index 5fca68015..16c11e853 100644 --- a/hana/lib/HANAService.js +++ b/hana/lib/HANAService.js @@ -568,11 +568,11 @@ class HANAService extends SQLService { // Calculate final output columns once let outputColumns = '' - outputColumns = `_path_ as "_path_",${blobs} as "_blobs_",${expands} as "_expands_",${jsonColumn} as "_json_"` + outputColumns = `${this.quote('_path_')} as "_path_",${blobs} as "_blobs_",${expands} as "_expands_",${jsonColumn} as "_json_"` if (blobColumns.length) outputColumns = `${outputColumns},${blobColumns.map(b => `${this.quote(b)} as "${b.replace(/"/g, '""')}"`)}` this._outputColumns = outputColumns - sql = `*,${path} as _path_` + sql = `*,${path} as ${this.quote('_path_')}` } return sql } From 36245eae7e0987be0ec4a01fbded9b699d951e6b Mon Sep 17 00:00:00 2001 From: Bob den Os Date: Mon, 5 Aug 2024 15:57:30 +0200 Subject: [PATCH 2/5] Use official sql.names quoted API --- db-service/lib/cqn2sql.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db-service/lib/cqn2sql.js b/db-service/lib/cqn2sql.js index a15f918af..8ec3235e3 100644 --- a/db-service/lib/cqn2sql.js +++ b/db-service/lib/cqn2sql.js @@ -36,9 +36,9 @@ class CQN2SQLRenderer { this.model = srv?.model // Overwrite smart quoting - if (cds.env.cdsc.sqlMapping === 'quoted') { + if (cds.env.sql.names === 'quoted') { this.class.prototype.name = (name) => name.id || name - this.class.prototype.quote = (s) => `"${s.replace(/"/g, '""')}"` + this.class.prototype.quote = (s) => `"${(s + '').replace(/"/g, '""')}"` } } From 7194b2b54cbc84183403f4a13ebcf333bf2c7009 Mon Sep 17 00:00:00 2001 From: Bob den Os Date: Mon, 5 Aug 2024 15:58:34 +0200 Subject: [PATCH 3/5] Attempt to use @cds.persistence.name for _texts entities --- db-service/lib/cqn2sql.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/db-service/lib/cqn2sql.js b/db-service/lib/cqn2sql.js index 8ec3235e3..24e5b9838 100644 --- a/db-service/lib/cqn2sql.js +++ b/db-service/lib/cqn2sql.js @@ -342,7 +342,9 @@ class CQN2SQLRenderer { const { ref, as } = from const _aliased = as ? s => s + ` as ${this.quote(as)}` : s => s if (ref) { - const z = ref[0] + const { target } = SELECT.from(from) + // localized views don't have @cds.persistence.name so all resolve to non localized entities + const z = target?.['@cds.persistence.name'] || ref[0] if (z.args) { return _aliased(`${this.quote(this.name(z))}${this.from_args(z.args)}`) } From 3e7dc2473e8298512f18dc07cb1d2402d7e8e3b8 Mon Sep 17 00:00:00 2001 From: Bob den Os <108393871+BobdenOs@users.noreply.github.com> Date: Tue, 1 Oct 2024 12:18:28 +0200 Subject: [PATCH 4/5] Update db-service/lib/cqn2sql.js Co-authored-by: Daniel Hutzel --- db-service/lib/cqn2sql.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db-service/lib/cqn2sql.js b/db-service/lib/cqn2sql.js index b391f0e06..dc9db6d52 100644 --- a/db-service/lib/cqn2sql.js +++ b/db-service/lib/cqn2sql.js @@ -38,7 +38,7 @@ class CQN2SQLRenderer { // Overwrite smart quoting if (cds.env.sql.names === 'quoted') { this.class.prototype.name = (name) => name.id || name - this.class.prototype.quote = (s) => `"${(s + '').replace(/"/g, '""')}"` + this.class.prototype.quote = (s) => `"${String(s).replace(/"/g, '""')}"` } } From 5c61737b966033d7d5a9491002660b073f828cd1 Mon Sep 17 00:00:00 2001 From: Johannes Vogel <31311694+johannes-vogel@users.noreply.github.com> Date: Tue, 1 Oct 2024 14:19:12 +0200 Subject: [PATCH 5/5] only infer in quoted mode --- db-service/lib/cqn2sql.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/db-service/lib/cqn2sql.js b/db-service/lib/cqn2sql.js index dc9db6d52..454458575 100644 --- a/db-service/lib/cqn2sql.js +++ b/db-service/lib/cqn2sql.js @@ -342,9 +342,12 @@ class CQN2SQLRenderer { const { ref, as } = from const _aliased = as ? s => s + ` as ${this.quote(as)}` : s => s if (ref) { - const { target } = SELECT.from(from) - // localized views don't have @cds.persistence.name so all resolve to non localized entities - const z = target?.['@cds.persistence.name'] || ref[0] + let z = ref[0] + if (cds.env.sql.names === 'quoted') { + // use SELECT.from to infer query, cds.infer also expects a query + const { target } = SELECT.from(from) + z = target?.['@cds.persistence.name'] || ref[0] + } if (z.args) { return _aliased(`${this.quote(this.name(z))}${this.from_args(z.args)}`) }