@cap-js/db-service 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@
4
4
  - The format is based on [Keep a Changelog](http://keepachangelog.com/).
5
5
  - This project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## Version 1.2.1 - 2023-09-08
8
+
9
+ ### Fixed
10
+
11
+ - Association expansion in infix filters. #213
12
+
7
13
  ## Version 1.2.0 - 2023-09-06
8
14
 
9
15
  ### Added
package/lib/cqn2sql.js CHANGED
@@ -235,19 +235,20 @@ class CQN2SQLRenderer {
235
235
  if (!elements) return sql // REVISIT: Above we say this is an error condition, but here we say it's ok?
236
236
  let cols = SELECT.columns.map(x => {
237
237
  const name = this.column_name(x)
238
- let col = `'$."${name}"',${this.output_converter4(x.element, this.quote(name))}`
238
+ let col = `'${name}',${this.output_converter4(x.element, this.quote(name))}`
239
239
  if (x.SELECT?.count) {
240
240
  // Return both the sub select and the count for @odata.count
241
241
  const qc = cds.ql.clone(x, { columns: [{ func: 'count' }], one: 1, limit: 0, orderBy: 0 })
242
- col += `, '$."${name}@odata.count"',${this.expr(qc)}`
242
+ return [col, `'${name}@odata.count',${this.expr(qc)}`]
243
243
  }
244
244
  return col
245
- })
245
+ }).flat()
246
246
 
247
247
  // Prevent SQLite from hitting function argument limit of 100
248
- let obj = "'{}'"
249
- for (let i = 0; i < cols.length; i += 48) {
250
- obj = `json_insert(${obj},${cols.slice(i, i + 48)})`
248
+ let obj = ''
249
+ for (let i = 0; i < cols.length; i += 50) {
250
+ const n = `json_object(${cols.slice(i, i + 50)})`
251
+ obj = obj ? `json_patch(${obj},${n})` : n
251
252
  }
252
253
  return `SELECT ${SELECT.one || SELECT.expand === 'root' ? obj : `json_group_array(${obj})`} as _json_ FROM (${sql})`
253
254
  }
package/lib/cqn4sql.js CHANGED
@@ -548,7 +548,10 @@ function cqn4sql(originalQuery, model = cds.context?.model || cds.model) {
548
548
  dollarSelfColumn.ref = [...referencedColumn.ref, ...dollarSelfColumn.ref.slice(2)]
549
549
  Object.defineProperties(dollarSelfColumn, {
550
550
  flatName: {
551
- value: referencedColumn.$refLinks[0].definition.kind === 'entity' ? dollarSelfColumn.ref.slice(1).join('_') : dollarSelfColumn.ref.join('_'),
551
+ value:
552
+ referencedColumn.$refLinks[0].definition.kind === 'entity'
553
+ ? dollarSelfColumn.ref.slice(1).join('_')
554
+ : dollarSelfColumn.ref.join('_'),
552
555
  },
553
556
  isJoinRelevant: {
554
557
  value: referencedColumn.isJoinRelevant,
@@ -1242,7 +1245,7 @@ function cqn4sql(originalQuery, model = cds.context?.model || cds.model) {
1242
1245
  ) {
1243
1246
  if (notSupportedOps.some(([firstOp]) => firstOp === next))
1244
1247
  cds.error(`The operator "${next}" is not supported for structure comparison`)
1245
- const newTokens = expandComparison(token, ops, rhs)
1248
+ const newTokens = expandComparison(token, ops, rhs, $baseLink)
1246
1249
  const needXpr = Boolean(tokenStream[i - 1] || tokenStream[indexRhs + 1])
1247
1250
  transformedTokenStream.push(...(needXpr ? [asXpr(newTokens)] : newTokens))
1248
1251
  i = indexRhs // jump to next relevant index
@@ -1301,9 +1304,14 @@ function cqn4sql(originalQuery, model = cds.context?.model || cds.model) {
1301
1304
  * @param {object} token with $refLinks
1302
1305
  * @param {string} operator one of allOps
1303
1306
  * @param {object} value either `null` or a column (with `ref` and `$refLinks`)
1307
+ * @param {object} $baseLink optional base `$refLink`, e.g. for infix filters of scoped queries.
1308
+ * In the following example, we must pass `bookshop:Reproduce` as $baseLink for `author`:
1309
+ *
1310
+ * `DELETE.from('bookshop.Reproduce[author = null]:accessGroup')`
1311
+ * ^^^^^^
1304
1312
  * @returns {array}
1305
1313
  */
1306
- function expandComparison(token, operator, value) {
1314
+ function expandComparison(token, operator, value, $baseLink = null) {
1307
1315
  const { definition } = token.$refLinks[token.$refLinks.length - 1]
1308
1316
  let flatRhs
1309
1317
  const result = []
@@ -1366,7 +1374,10 @@ function cqn4sql(originalQuery, model = cds.context?.model || cds.model) {
1366
1374
  if (!def.$refLinks) return def
1367
1375
  const leaf = def.$refLinks[def.$refLinks.length - 1]
1368
1376
  const first = def.$refLinks[0]
1369
- const tableAlias = getQuerySourceName(def, def.ref.length > 1 && first.definition.isAssociation ? first : null)
1377
+ const tableAlias = getQuerySourceName(
1378
+ def,
1379
+ def.ref.length > 1 && first.definition.isAssociation ? first : $baseLink,
1380
+ )
1370
1381
  if (leaf.definition.parent.kind !== 'entity')
1371
1382
  // we need the base name
1372
1383
  return getFlatColumnsFor(leaf.definition, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cap-js/db-service",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "CDS base database service",
5
5
  "homepage": "https://github.com/cap-js/cds-dbs/tree/main/db-service#cds-base-database-service",
6
6
  "repository": {