Skip to content

Commit

Permalink
fix: quoted mode (#937)
Browse files Browse the repository at this point in the history
  • Loading branch information
johannes-vogel authored Dec 12, 2024
1 parent ce24264 commit 9e62b22
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 21 deletions.
35 changes: 17 additions & 18 deletions db-service/lib/cqn2sql.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,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.sql.names === 'quoted') {
this.class.prototype.name = (name) => name.id || name
this.class.prototype.name = (name, query) => {
const e = name.id || name
return (query?.target || this.model?.definitions[e])?.['@cds.persistence.name'] || e
}
this.class.prototype.quote = (s) => `"${String(s).replace(/"/g, '""')}"`
}
}
Expand Down Expand Up @@ -124,7 +126,7 @@ class CQN2SQLRenderer {
target = typeof entity === 'string' ? { name: entity } : q.CREATE.entity
}

const name = this.name(target.name)
const name = this.name(target.name, q)
// Don't allow place holders inside views
delete this.values
this.sql =
Expand Down Expand Up @@ -213,7 +215,7 @@ class CQN2SQLRenderer {
const { target } = q
const isView = target?.query || target?.projection || q.DROP.view
const name = target?.name || q.DROP.table?.ref?.[0] || q.DROP.view?.ref?.[0]
return (this.sql = `DROP ${isView ? 'VIEW' : 'TABLE'} IF EXISTS ${this.quote(this.name(name))}`)
return (this.sql = `DROP ${isView ? 'VIEW' : 'TABLE'} IF EXISTS ${this.quote(this.name(name, q))}`)
}

// SELECT Statements ------------------------------------------------
Expand Down Expand Up @@ -352,15 +354,10 @@ class CQN2SQLRenderer {
const _aliased = as ? s => s + ` as ${this.quote(as)}` : s => s
if (ref) {
let z = ref[0]
if (cds.env.sql.names === 'quoted') {
// use SELECT.from to infer query, cds.infer also expects a query
const { target } = q || 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)}`)
return _aliased(`${this.quote(this.name(z, q))}${this.from_args(z.args)}`)
}
return _aliased(this.quote(this.name(z)))
return _aliased(this.quote(this.name(z, q)))
}
if (from.SELECT) return _aliased(`(${this.SELECT(from)})`)
if (from.join) return `${this.from(from.args[0])} ${from.join} JOIN ${this.from(from.args[1])}${from.on ? ` ON ${this.where(from.on)}` : ''}`
Expand Down Expand Up @@ -504,7 +501,7 @@ class CQN2SQLRenderer {
this.columns = columns

const alias = INSERT.into.as
const entity = this.name(q.target?.name || INSERT.into.ref[0])
const entity = this.name(q.target?.name || INSERT.into.ref[0], q)
if (!elements) {
this.entries = INSERT.entries.map(e => columns.map(c => e[c]))
const param = this.param.bind(this, { ref: ['?'] })
Expand Down Expand Up @@ -638,7 +635,7 @@ class CQN2SQLRenderer {
*/
INSERT_rows(q) {
const { INSERT } = q
const entity = this.name(q.target?.name || INSERT.into.ref[0])
const entity = this.name(q.target?.name || INSERT.into.ref[0], q)
const alias = INSERT.into.as
const elements = q.elements || q.target?.elements
const columns = this.columns = INSERT.columns || cds.error`Cannot insert rows without columns or elements`
Expand Down Expand Up @@ -684,7 +681,7 @@ class CQN2SQLRenderer {
*/
INSERT_select(q) {
const { INSERT } = q
const entity = this.name(q.target.name)
const entity = this.name(q.target.name, q)
const alias = INSERT.into.as
const elements = q.elements || q.target?.elements || {}
const columns = (this.columns = (INSERT.columns || ObjectKeys(elements)).filter(
Expand Down Expand Up @@ -752,7 +749,7 @@ class CQN2SQLRenderer {
.filter(c => keys.includes(c.name))
.map(c => `${c.onInsert || c.sql} as ${this.quote(c.name)}`)

const entity = this.name(q.target?.name || UPSERT.into.ref[0])
const entity = this.name(q.target?.name || UPSERT.into.ref[0], q)
sql = `SELECT ${managed.map(c => c.upsert)} FROM (SELECT value, ${extractkeys} from json_each(?)) as NEW LEFT JOIN ${this.quote(entity)} AS OLD ON ${keyCompare}`

const updateColumns = columns.filter(c => {
Expand All @@ -779,7 +776,7 @@ class CQN2SQLRenderer {
UPDATE(q) {
const { entity, with: _with, data, where } = q.UPDATE
const elements = q.target?.elements
let sql = `UPDATE ${this.quote(this.name(entity.ref?.[0] || entity))}`
let sql = `UPDATE ${this.quote(this.name(entity.ref?.[0] || entity, q))}`
if (entity.as) sql += ` AS ${this.quote(entity.as)}`

let columns = []
Expand Down Expand Up @@ -811,8 +808,9 @@ class CQN2SQLRenderer {
* @param {import('./infer/cqn').DELETE} param0
* @returns {string} SQL
*/
DELETE({ DELETE: { from, where } }) {
let sql = `DELETE FROM ${this.from(from)}`
DELETE(q) {
const { DELETE: { from, where } } = q
let sql = `DELETE FROM ${this.from(from, q)}`
if (where) sql += ` WHERE ${this.where(where)}`
return (this.sql = sql)
}
Expand Down Expand Up @@ -1028,6 +1026,7 @@ class CQN2SQLRenderer {
/**
* Calculates the Database name of the given name
* @param {string|import('./infer/cqn').ref} name
* @param {import('./infer/cqn').Query} query
* @returns {string} Database name
*/
name(name) {
Expand Down
6 changes: 3 additions & 3 deletions hana/lib/HANAService.js
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ class HANAService extends SQLService {

if (expand === 'root' && this._outputColumns) {
this.cqn = q
const fromSQL = this.from({ ref: [q.src.alias] })
const fromSQL = this.quote(this.name(q.src.alias))
this.withclause.unshift(`${fromSQL} as (${this.sql})`)
this.temporary.unshift({ blobs: this._blobs, select: `SELECT ${this._outputColumns} FROM ${fromSQL}` })
if (this.values) {
Expand Down Expand Up @@ -664,7 +664,7 @@ class HANAService extends SQLService {
this.values = undefined
const { INSERT } = q
// REVISIT: should @cds.persistence.name be considered ?
const entity = q.target?.['@cds.persistence.name'] || this.name(q.target?.name || INSERT.into.ref[0])
const entity = q.target?.['@cds.persistence.name'] || this.name(q.target?.name || INSERT.into.ref[0], q)

const elements = q.elements || q.target?.elements
if (!elements) {
Expand Down Expand Up @@ -761,7 +761,7 @@ class HANAService extends SQLService {
UPSERT(q) {
const { UPSERT } = q
// REVISIT: should @cds.persistence.name be considered ?
const entity = q.target?.['@cds.persistence.name'] || this.name(q.target?.name || UPSERT.into.ref[0])
const entity = q.target?.['@cds.persistence.name'] || this.name(q.target?.name || UPSERT.into.ref[0], q)
const elements = q.target?.elements || {}
const insert = this.INSERT({ __proto__: q, INSERT: UPSERT })

Expand Down

0 comments on commit 9e62b22

Please sign in to comment.