@cap-js/postgres 1.12.0 → 1.14.0
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 +21 -0
- package/cds-plugin.js +17 -5
- package/lib/PostgresService.js +34 -20
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,27 @@
|
|
|
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.0](https://github.com/cap-js/cds-dbs/compare/postgres-v1.13.0...postgres-v1.14.0) (2025-04-17)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
* Result set streaming ([#702](https://github.com/cap-js/cds-dbs/issues/702)) ([2fe02ea](https://github.com/cap-js/cds-dbs/commit/2fe02eafd02993e5697efbdab90ad997fb2c9e00))
|
|
13
|
+
|
|
14
|
+
## [1.13.0](https://github.com/cap-js/cds-dbs/compare/postgres-v1.12.0...postgres-v1.13.0) (2025-03-31)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
* **collate:** only collate if locale is provided ([#1060](https://github.com/cap-js/cds-dbs/issues/1060)) ([dedd768](https://github.com/cap-js/cds-dbs/commit/dedd768c085aa29be0e38db11f11678ff55d5b7b))
|
|
20
|
+
* **forUpdate:** ignore locked ([#1074](https://github.com/cap-js/cds-dbs/issues/1074)) ([163480b](https://github.com/cap-js/cds-dbs/commit/163480b245b18a2829cd871c2f053c82bcc1abef))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
* consider `nulls first | last` on `orderBy` ([#1064](https://github.com/cap-js/cds-dbs/issues/1064)) ([c6bed60](https://github.com/cap-js/cds-dbs/commit/c6bed60f0d93b9f4a73c976727f30172707c60d9)), closes [#1062](https://github.com/cap-js/cds-dbs/issues/1062)
|
|
26
|
+
* Persist assert_integrity feature ([#1032](https://github.com/cap-js/cds-dbs/issues/1032)) ([2956279](https://github.com/cap-js/cds-dbs/commit/2956279777ac94330c98373d8bca32cf0f8e967e))
|
|
27
|
+
|
|
7
28
|
## [1.12.0](https://github.com/cap-js/cds-dbs/compare/postgres-v1.11.1...postgres-v1.12.0) (2025-03-04)
|
|
8
29
|
|
|
9
30
|
|
package/cds-plugin.js
CHANGED
|
@@ -25,11 +25,23 @@ cds.build?.register?.('postgres', class PostgresBuildPlugin extends cds.build.Pl
|
|
|
25
25
|
if (fs.existsSync(path.join(this.task.src, 'package.json'))) {
|
|
26
26
|
promises.push(this.copy(path.join(this.task.src, 'package.json')).to('package.json'))
|
|
27
27
|
} else {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
28
|
+
const packageJson = {
|
|
29
|
+
dependencies: {
|
|
30
|
+
'@sap/cds': '^8',
|
|
31
|
+
'@cap-js/postgres': '^1'
|
|
32
|
+
},
|
|
33
|
+
scripts: {
|
|
34
|
+
start: 'cds-deploy'
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const assertIntegrity = cds.env?.features?.assert_integrity
|
|
38
|
+
if (assertIntegrity) {
|
|
39
|
+
packageJson.cds ??= {}
|
|
40
|
+
packageJson.cds.features ??= {}
|
|
41
|
+
packageJson.cds.features.assert_integrity = assertIntegrity
|
|
42
|
+
}
|
|
43
|
+
promises.push(
|
|
44
|
+
this.write(packageJson).to('package.json')
|
|
33
45
|
)
|
|
34
46
|
}
|
|
35
47
|
promises.push(this.write(cds.compile.to.json(model)).to(path.join('db', 'csn.json')))
|
package/lib/PostgresService.js
CHANGED
|
@@ -178,9 +178,9 @@ GROUP BY k
|
|
|
178
178
|
throw enhanceError(e, sql)
|
|
179
179
|
}
|
|
180
180
|
},
|
|
181
|
-
stream: async (values, one) => {
|
|
181
|
+
stream: async (values, one, objectMode) => {
|
|
182
182
|
try {
|
|
183
|
-
const streamQuery = new QueryStream({ ...query, values: this._getValues(values) }, one)
|
|
183
|
+
const streamQuery = new QueryStream({ ...query, values: this._getValues(values) }, one, objectMode)
|
|
184
184
|
return await this.dbc.query(streamQuery)
|
|
185
185
|
} catch (e) {
|
|
186
186
|
throw enhanceError(e, sql)
|
|
@@ -305,7 +305,8 @@ GROUP BY k
|
|
|
305
305
|
}
|
|
306
306
|
}
|
|
307
307
|
|
|
308
|
-
async onSELECT(
|
|
308
|
+
async onSELECT(req) {
|
|
309
|
+
const { query, data } = req
|
|
309
310
|
// workaround for chunking odata streaming
|
|
310
311
|
if (query.SELECT?.columns?.find(col => col.as === '$mediaContentType')) {
|
|
311
312
|
const columns = query.SELECT.columns
|
|
@@ -323,7 +324,7 @@ GROUP BY k
|
|
|
323
324
|
res[this.class.CQN2SQL.prototype.column_name(binary[0])] = stream
|
|
324
325
|
return res
|
|
325
326
|
}
|
|
326
|
-
return super.onSELECT(
|
|
327
|
+
return super.onSELECT(req)
|
|
327
328
|
}
|
|
328
329
|
|
|
329
330
|
async onINSERT(req) {
|
|
@@ -344,14 +345,15 @@ GROUP BY k
|
|
|
344
345
|
|
|
345
346
|
static CQN2SQL = class CQN2Postgres extends SQLService.CQN2SQL {
|
|
346
347
|
_orderBy(orderBy, localized, locale) {
|
|
347
|
-
return orderBy.map(
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
(c.element?.[this.class._localized] ? ` COLLATE "${locale}"` : '') +
|
|
352
|
-
(c.sort?.toLowerCase() === 'desc' || c.sort === -1 ? ' DESC
|
|
353
|
-
:
|
|
354
|
-
|
|
348
|
+
return orderBy.map(c => {
|
|
349
|
+
const nulls = c.nulls || (c.sort?.toLowerCase() === 'desc' || c.sort === -1 ? 'LAST' : 'FIRST')
|
|
350
|
+
const o = localized
|
|
351
|
+
? this.expr(c) +
|
|
352
|
+
(c.element?.[this.class._localized] && locale ? ` COLLATE "${locale}"` : '') +
|
|
353
|
+
(c.sort?.toLowerCase() === 'desc' || c.sort === -1 ? ' DESC' : ' ASC')
|
|
354
|
+
: this.expr(c) + (c.sort?.toLowerCase() === 'desc' || c.sort === -1 ? ' DESC' : ' ASC')
|
|
355
|
+
return o + ' NULLS ' + (nulls.toLowerCase() === 'first' ? 'FIRST' : 'LAST')
|
|
356
|
+
})
|
|
355
357
|
}
|
|
356
358
|
|
|
357
359
|
orderBy(orderBy) {
|
|
@@ -465,9 +467,11 @@ GROUP BY k
|
|
|
465
467
|
// Postgres does not support locking columns only tables which makes of unapplicable
|
|
466
468
|
// Postgres does not support "wait n" it only supports "nowait"
|
|
467
469
|
forUpdate(update) {
|
|
468
|
-
const { wait } = update
|
|
469
|
-
|
|
470
|
-
|
|
470
|
+
const { wait, ignoreLocked } = update
|
|
471
|
+
let sql = 'FOR UPDATE'
|
|
472
|
+
if (wait === 0) sql += ' NOWAIT'
|
|
473
|
+
if (ignoreLocked) sql += ' SKIP LOCKED'
|
|
474
|
+
return sql
|
|
471
475
|
}
|
|
472
476
|
|
|
473
477
|
forShareLock(lock) {
|
|
@@ -571,7 +575,6 @@ GROUP BY k
|
|
|
571
575
|
|
|
572
576
|
// Convert ST types back to WKT format
|
|
573
577
|
'cds.hana.ST_POINT': expr => `ST_AsText(${expr})`,
|
|
574
|
-
'cds.hana.ST_POINT': expr => `ST_AsText(${expr})`,
|
|
575
578
|
}
|
|
576
579
|
}
|
|
577
580
|
|
|
@@ -664,7 +667,7 @@ GROUP BY k
|
|
|
664
667
|
}
|
|
665
668
|
|
|
666
669
|
class QueryStream extends Query {
|
|
667
|
-
constructor(config, one) {
|
|
670
|
+
constructor(config, one, objectMode) {
|
|
668
671
|
// REVISIT: currently when setting the row chunk size
|
|
669
672
|
// it results in an inconsistent connection state
|
|
670
673
|
// if (!one) config.rows = 1000
|
|
@@ -673,6 +676,7 @@ class QueryStream extends Query {
|
|
|
673
676
|
this._one = one || config.one
|
|
674
677
|
|
|
675
678
|
this.stream = new Readable({
|
|
679
|
+
objectMode,
|
|
676
680
|
read: this.rows
|
|
677
681
|
? () => {
|
|
678
682
|
this.stream.pause()
|
|
@@ -690,7 +694,7 @@ class QueryStream extends Query {
|
|
|
690
694
|
this._prom = new Promise((resolve, reject) => {
|
|
691
695
|
this.once('error', reject)
|
|
692
696
|
this.once('end', () => {
|
|
693
|
-
if (!this._one) this.push(this.constructor.close)
|
|
697
|
+
if (!objectMode && !this._one) this.push(this.constructor.close)
|
|
694
698
|
this.push(null)
|
|
695
699
|
if (this.stream.isPaused()) this.stream.resume()
|
|
696
700
|
resolve(null)
|
|
@@ -733,10 +737,15 @@ class QueryStream extends Query {
|
|
|
733
737
|
} else {
|
|
734
738
|
this.handleDataRow = msg => {
|
|
735
739
|
const val = msg.fields[0]
|
|
736
|
-
|
|
740
|
+
const objectMode = this.stream.readableObjectMode
|
|
741
|
+
if (!objectMode && !this._one && val !== null) this.push(this.constructor.open)
|
|
737
742
|
this.emit('row', val)
|
|
738
|
-
this.push(val)
|
|
743
|
+
this.push(objectMode ? JSON.parse(val) : val)
|
|
744
|
+
|
|
739
745
|
delete this.handleDataRow
|
|
746
|
+
if (objectMode) {
|
|
747
|
+
this.handleDataRow = this.handleDataRowObjectMode
|
|
748
|
+
}
|
|
740
749
|
}
|
|
741
750
|
}
|
|
742
751
|
return super.handleRowDescription(msg)
|
|
@@ -748,6 +757,11 @@ class QueryStream extends Query {
|
|
|
748
757
|
this.push(msg.fields[0])
|
|
749
758
|
}
|
|
750
759
|
|
|
760
|
+
// Called when a new row is received
|
|
761
|
+
handleDataRowObjectMode(msg) {
|
|
762
|
+
this.push(JSON.parse(msg.fields[0]))
|
|
763
|
+
}
|
|
764
|
+
|
|
751
765
|
// Called when a new binary row is received
|
|
752
766
|
handleBinaryRow(msg) {
|
|
753
767
|
const val = msg.fields[0] === null ? null : this._result._parsers[0](msg.fields[0])
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cap-js/postgres",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
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,7 +27,7 @@
|
|
|
27
27
|
"start": "docker compose -f pg-stack.yml up -d"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@cap-js/db-service": "^1.
|
|
30
|
+
"@cap-js/db-service": "^1.20.0",
|
|
31
31
|
"pg": "^8"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|