@cap-js/postgres 1.14.1 → 2.0.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,12 +4,46 @@
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
- ## [1.14.1](https://github.com/cap-js/cds-dbs/compare/postgres-v1.14.0...postgres-v1.14.1) (2025-05-28)
7
+ ## [2.0.1](https://github.com/cap-js/cds-dbs/compare/postgres-v2.0.0...postgres-v2.0.1) (2025-05-27)
8
+
9
+
10
+ ### ⚠ BREAKING CHANGES
11
+
12
+ * remove PG `?` placeholder replacement ([#1180](https://github.com/cap-js/cds-dbs/issues/1180))
8
13
 
9
14
 
10
15
  ### Fixed
11
16
 
12
- * close dependency ranges to cds^8 ([#1214](https://github.com/cap-js/cds-dbs/issues/1214)) ([a4156e8](https://github.com/cap-js/cds-dbs/commit/a4156e8db4bba8688457fe635d76aa0f1ac38d1e))
17
+ * Enable mixing stream and normal parameters in queries ([#1179](https://github.com/cap-js/cds-dbs/issues/1179)) ([7ee8083](https://github.com/cap-js/cds-dbs/commit/7ee808365426072250dd6de87abd11215f44561a))
18
+ * hierarchies in quoted mode ([3465cba](https://github.com/cap-js/cds-dbs/commit/3465cbab579d4560d12d3b230c55b746d4d3f5a5))
19
+ * only sort by locale if locale is set ([#1193](https://github.com/cap-js/cds-dbs/issues/1193)) ([3465cba](https://github.com/cap-js/cds-dbs/commit/3465cbab579d4560d12d3b230c55b746d4d3f5a5))
20
+
21
+
22
+ ### Changed
23
+
24
+ * remove PG `?` placeholder replacement ([#1180](https://github.com/cap-js/cds-dbs/issues/1180)) ([a1e0bd9](https://github.com/cap-js/cds-dbs/commit/a1e0bd9fe8501c284d8cbfc8d79d4dddda34c087))
25
+ * remove stream_compat ([#1139](https://github.com/cap-js/cds-dbs/issues/1139)) ([#1144](https://github.com/cap-js/cds-dbs/issues/1144)) ([1b8b2d9](https://github.com/cap-js/cds-dbs/commit/1b8b2d9539cd97be2cef088c98d88ef9ec7dd1bf))
26
+
27
+ ## [2.0.0](https://github.com/cap-js/cds-dbs/compare/postgres-v1.14.0...postgres-v2.0.0) (2025-05-07)
28
+
29
+
30
+ ### ⚠ BREAKING CHANGES
31
+
32
+ * update peer dependency to @sap/cds@9 ([#1178](https://github.com/cap-js/cds-dbs/issues/1178))
33
+ * update dependency to @cap-js/db-service@2 ([#1178](https://github.com/cap-js/cds-dbs/issues/1178))
34
+ * Unfiltered db constraint errors ([#1165](https://github.com/cap-js/cds-dbs/issues/1165))
35
+
36
+
37
+ ### Added
38
+
39
+ * Support for hierarchical queries ([#1093](https://github.com/cap-js/cds-dbs/issues/1093)) ([246e0b3](https://github.com/cap-js/cds-dbs/commit/246e0b38840f7e132ea49cae335b6be7a55354b3))
40
+
41
+
42
+ ### Changed
43
+
44
+ * Unfiltered db constraint errors ([#1165](https://github.com/cap-js/cds-dbs/issues/1165)) ([ff39e22](https://github.com/cap-js/cds-dbs/commit/ff39e22ac6cd3f20c98bc31c1a6bb828aa009796))
45
+ * update peer dependency to @sap/cds@9 ([#1178](https://github.com/cap-js/cds-dbs/issues/1178)) ([#1178](https://github.com/cap-js/cds-dbs/issues/1178)) ([0507edd](https://github.com/cap-js/cds-dbs/commit/0507edd4e1dcb98983b1fb65ade1344d978b7524))
46
+ * update dependency to @cap-js/db-service@2 ([#1178](https://github.com/cap-js/cds-dbs/issues/1178)) ([#1178](https://github.com/cap-js/cds-dbs/issues/1178)) ([0507edd](https://github.com/cap-js/cds-dbs/commit/0507edd4e1dcb98983b1fb65ade1344d978b7524))
13
47
 
14
48
  ## [1.14.0](https://github.com/cap-js/cds-dbs/compare/postgres-v1.13.0...postgres-v1.14.0) (2025-04-17)
15
49
 
@@ -4,7 +4,6 @@ const cds = require('@sap/cds')
4
4
  const crypto = require('crypto')
5
5
  const { Writable, Readable } = require('stream')
6
6
  const sessionVariableMap = require('./session.json')
7
- const SANITIZE_VALUES = process.env.NODE_ENV === 'production' && cds.env.log.sanitize_values !== false
8
7
 
9
8
  class PostgresService extends SQLService {
10
9
  init() {
@@ -213,7 +212,7 @@ GROUP BY k
213
212
  if (isBinary) value.setEncoding('base64')
214
213
  value.pipe(paramStream)
215
214
  value.on('error', err => paramStream.emit('error', err))
216
- streams[i] = paramStream
215
+ streams.push(paramStream)
217
216
  newValues[i] = streamID
218
217
  sql = sql.replace(
219
218
  new RegExp(`\\$${i + 1}`, 'g'),
@@ -284,12 +283,7 @@ GROUP BY k
284
283
  return target && this.run(cds.ql.CREATE(target))
285
284
  }
286
285
  }
287
- // Look for ? placeholders outside of string and replace them with $n
288
- if (/('|")(\1|[^\1]*?\1)|(\?)/.exec(query)?.[3]) {
289
- let i = 1
290
- // eslint-disable-next-line no-unused-vars
291
- req.query = query.replace(/('|")(\1|[^\1]*?\1)|(\?)/g, (a, _b, _c, d, _e, _f, _g) => (d ? '$' + i++ : a))
292
- }
286
+
293
287
  try {
294
288
  return await super.onPlainSQL(req, next)
295
289
  }
@@ -327,23 +321,47 @@ GROUP BY k
327
321
  return super.onSELECT(req)
328
322
  }
329
323
 
330
- async onINSERT(req) {
331
- try {
332
- return await super.onINSERT(req)
333
- } catch (err) {
334
- throw _not_unique(err, 'ENTITY_ALREADY_EXISTS', req.data)
335
- }
336
- }
337
324
 
338
- async onUPDATE(req) {
339
- try {
340
- return await super.onUPDATE(req)
341
- } catch (err) {
342
- throw _not_unique(err, 'UNIQUE_CONSTRAINT_VIOLATION', req.data)
325
+ static CQN2SQL = class CQN2Postgres extends SQLService.CQN2SQL {
326
+
327
+ render_with() {
328
+ const sql = this.sql
329
+ let recursive = false
330
+ const prefix = this._with.map(q => {
331
+ let sql
332
+ if ('SELECT' in q) sql = `${this.quote(q.as)} AS (${this.SELECT(q)})`
333
+ else if ('SET' in q) {
334
+ recursive = true
335
+ const { SET } = q
336
+ const isDepthFirst = SET.orderBy?.length && (SET.orderBy[0].sort?.toLowerCase() === 'desc' || SET.orderBy[0].sort === -1)
337
+ let alias = q.as
338
+ if (isDepthFirst) {
339
+ alias = alias + '_depth_first'
340
+ SET.args[1].SELECT.from.args.forEach(r => { if (r.ref[0] === q.as) r.ref[0] = alias })
341
+ }
342
+
343
+ sql = `${this.quote(alias)}(${SET.args[0].SELECT.columns?.map(c => this.quote(this.column_name(c))) || ''}) AS (${
344
+ // Root select
345
+ this.SELECT(SET.args[0])} ${
346
+ // Union clause
347
+ SET.op?.toUpperCase() || 'UNION'} ${SET.all ? 'ALL' : ''} ${
348
+ // Repeated join query
349
+ this.SELECT(SET.args[1])
350
+ })${
351
+ // Leverage Postgres specific depth first syntax
352
+ SET.orderBy?.length
353
+ ? ` SEARCH DEPTH FIRST BY ${SET.orderBy.map(r => this.ref(r))} SET "$DEPTH$"`
354
+ : ''
355
+ }`
356
+
357
+ // Enforce depth sorting for consuming queries
358
+ if (isDepthFirst) sql += `,${this.quote(q.as)} AS (SELECT * FROM ${this.quote(q.as + '_depth_first')} ORDER BY "$DEPTH$")`
359
+ }
360
+ return { sql }
361
+ })
362
+ this.sql = `WITH${recursive ? ' RECURSIVE' : ''} ${prefix.map(p => p.sql)} ${sql}`
343
363
  }
344
- }
345
364
 
346
- static CQN2SQL = class CQN2Postgres extends SQLService.CQN2SQL {
347
365
  _orderBy(orderBy, localized, locale) {
348
366
  return orderBy.map(c => {
349
367
  const nulls = c.nulls || (c.sort?.toLowerCase() === 'desc' || c.sort === -1 ? 'LAST' : 'FIRST')
@@ -361,7 +379,7 @@ GROUP BY k
361
379
  }
362
380
 
363
381
  orderByICU(orderBy, localized) {
364
- const locale = `${this.context.locale.replace('_', '-')}-x-icu`
382
+ const locale = this.context.locale ? `${this.context.locale.replace('_', '-')}-x-icu` : this.context.locale
365
383
  return this._orderBy(orderBy, localized, locale)
366
384
  }
367
385
 
@@ -877,15 +895,4 @@ class ParameterStream extends Writable {
877
895
  }
878
896
  }
879
897
 
880
- function _not_unique(err, code, data) {
881
- if (err.code === '23505')
882
- return Object.assign(err, {
883
- originalMessage: err.message, // FIXME: required because of next line
884
- message: code, // FIXME: misusing message as code
885
- code: 400, // FIXME: misusing code as (http) status
886
- })
887
- if (data) err.values = SANITIZE_VALUES ? ['***'] : data
888
- return err
889
- }
890
-
891
898
  module.exports = PostgresService
@@ -189,7 +189,7 @@ const HANAFunctions = {
189
189
  * @returns {string} - SQL statement
190
190
  */
191
191
  years_between(x, y) {
192
- return `TRUNC(${this.months_between(x, y)} / 12,0)`
192
+ return `TRUNC(${this.expr({ func: 'months_between', args: [x, y] })} / 12,0)`
193
193
  },
194
194
  }
195
195
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cap-js/postgres",
3
- "version": "1.14.1",
3
+ "version": "2.0.1",
4
4
  "description": "CDS database service for Postgres",
5
5
  "homepage": "https://github.com/cap-js/cds-dbs/tree/main/postgres#cds-database-service-for-postgres",
6
6
  "repository": {
@@ -27,12 +27,12 @@
27
27
  "start": "docker compose -f pg-stack.yml up -d"
28
28
  },
29
29
  "dependencies": {
30
- "@cap-js/db-service": "^1.20.0",
30
+ "@cap-js/db-service": "^2",
31
31
  "pg": "^8"
32
32
  },
33
33
  "peerDependencies": {
34
- "@sap/cds": ">=7.6 <9",
35
- "@sap/cds-dk": ">=7.5 <9"
34
+ "@sap/cds": ">=9",
35
+ "@sap/cds-dk": ">=9"
36
36
  },
37
37
  "peerDependenciesMeta": {
38
38
  "@sap/cds-dk": {
@@ -76,5 +76,5 @@
76
76
  }
77
77
  }
78
78
  },
79
- "license": "SEE LICENSE"
79
+ "license": "Apache-2.0"
80
80
  }