@cap-js/hana
Advanced tools
Comparing version 0.0.6 to 0.1.0
@@ -7,2 +7,26 @@ # Changelog | ||
## [0.1.0](https://github.com/cap-js/cds-dbs/compare/hana-v0.0.6...hana-v0.1.0) (2024-03-22) | ||
### Added | ||
* also support lowercase matchespattern function ([#528](https://github.com/cap-js/cds-dbs/issues/528)) ([6ea574e](https://github.com/cap-js/cds-dbs/commit/6ea574ee67ef5e42e4f8ccbe4fe91b46097de129)) | ||
* forUpdate and forShareLock ([#148](https://github.com/cap-js/cds-dbs/issues/148)) ([99a1170](https://github.com/cap-js/cds-dbs/commit/99a1170e61de4fd0c505834c25a9c03fc34da85b)) | ||
* **hana:** drop prepared statements after end of transaction ([#537](https://github.com/cap-js/cds-dbs/issues/537)) ([b1f864e](https://github.com/cap-js/cds-dbs/commit/b1f864e0a3a0e5efacd803d3709379cab76d61cc)) | ||
### Fixed | ||
* use keyword list from compiler ([#525](https://github.com/cap-js/cds-dbs/issues/525)) ([c6993d9](https://github.com/cap-js/cds-dbs/commit/c6993d9c0e823d403f49f55cfcfa8663971293c8)) | ||
* improve search inside where clause detection ([#538](https://github.com/cap-js/cds-dbs/issues/538)) ([51b8af3](https://github.com/cap-js/cds-dbs/commit/51b8af3b42fba3f7b509d00675997d6c711cacc4)) | ||
* reduce service manager calls for failing tenants ([#533](https://github.com/cap-js/cds-dbs/issues/533)) ([e95fd17](https://github.com/cap-js/cds-dbs/commit/e95fd176094ac8b1d95b3bc68538057bf28aadf1)) | ||
* Add views with parameters support ([#488](https://github.com/cap-js/cds-dbs/issues/488)) ([3790ec0](https://github.com/cap-js/cds-dbs/commit/3790ec0178aab2cdb429272bb3e813b13441785c)) | ||
* issue with reused select cqns ([#505](https://github.com/cap-js/cds-dbs/issues/505)) ([916d175](https://github.com/cap-js/cds-dbs/commit/916d1756422f0caf02c323052f2addafed39182a)) | ||
* joins without columns are rejected ([#535](https://github.com/cap-js/cds-dbs/issues/535)) ([eb9beda](https://github.com/cap-js/cds-dbs/commit/eb9beda728de60081d7afbfcd49305eeb241f3fb)) | ||
* mass insert for unknown entities ([#540](https://github.com/cap-js/cds-dbs/issues/540)) ([f2ea4af](https://github.com/cap-js/cds-dbs/commit/f2ea4affe65e76fa269766d3d02337ceb1138c65)) | ||
### Changed | ||
* this package now requires `@cap-js/db-service >= v1.7.0` ([#545](https://github.com/cap-js/cds-dbs/issues/545)) ([2cec27d](https://github.com/cap-js/cds-dbs/commit/2cec27d91402804c3b2da25cc7169f0d81a7406a)) | ||
## [0.0.6](https://github.com/cap-js/cds-dbs/compare/hana-v0.0.5...hana-v0.0.6) (2024-02-28) | ||
@@ -9,0 +33,0 @@ |
@@ -12,2 +12,4 @@ const isTime = /^\d{1,2}:\d{1,2}:\d{1,2}$/ | ||
endswith: (x, y) => `(CASE WHEN substring(${x},length(${x})+1 - length(${y})) = ${y} THEN TRUE ELSE FALSE END)`, | ||
matchesPattern: (x, y) => `(CASE WHEN ${x} LIKE_REGEXPR ${y} THEN TRUE ELSE FALSE END)`, | ||
matchespattern: (x, y) => `(CASE WHEN ${x} LIKE_REGEXPR ${y} THEN TRUE ELSE FALSE END)`, | ||
substring: (x, y, z) => | ||
@@ -14,0 +16,0 @@ z |
@@ -55,2 +55,6 @@ /** | ||
}, | ||
drop: async () => { | ||
const stmt = await prep | ||
return stmt.drop() | ||
} | ||
} | ||
@@ -57,0 +61,0 @@ } |
@@ -77,2 +77,3 @@ const { Readable, Stream } = require('stream') | ||
}) | ||
rsStreams.catch(() => {}) | ||
@@ -79,0 +80,0 @@ rs._rowPosition = -1 |
@@ -9,2 +9,8 @@ const fs = require('fs') | ||
const collations = require('./collations.json') | ||
const keywords = cds.compiler.to.hdi.keywords | ||
// keywords come as array | ||
const hanaKeywords = keywords.reduce((prev, curr) => { | ||
prev[curr] = 1 | ||
return prev | ||
}, {}) | ||
@@ -36,2 +42,3 @@ const DEBUG = cds.debug('sql|db') | ||
const service = this | ||
const acquireTimeoutMillis = this.options.pool?.acquireTimeoutMillis || cds.env.profiles.includes('production') ? 1000 : 10000 | ||
return { | ||
@@ -41,3 +48,3 @@ options: { | ||
max: 10, | ||
acquireTimeoutMillis: cds.env.profiles.includes('production') ? 1000 : 10000, | ||
acquireTimeoutMillis, | ||
idleTimeoutMillis: 60000, | ||
@@ -60,3 +67,10 @@ evictionRunIntervalMillis: 100000, | ||
} catch (err) { | ||
if (!isMultitenant || err.code !== 10) throw err | ||
if (isMultitenant) { | ||
// REVISIT: throw the error and break retry loop | ||
// Stop trying when the tenant does not exist or is rate limited | ||
if (err.status == 404 || err.status == 429) | ||
return new Promise(function (_, reject) { | ||
setTimeout(() => reject(err), acquireTimeoutMillis) | ||
}) | ||
} else if (err.code !== 10) throw err | ||
await require('@sap/cds-mtxs/lib').xt.serviceManager.get(tenant, { disableCache: true }) | ||
@@ -107,2 +121,3 @@ return this.create(tenant) | ||
const { query, data } = req | ||
if (!query.target) { | ||
@@ -115,11 +130,26 @@ try { this.infer(query) } catch (e) { /**/ } | ||
// REVISIT: disable this for queries like (SELECT 1) | ||
// Will return multiple rows with objects inside | ||
query.SELECT.expand = 'root' | ||
const { cqn, temporary, blobs, withclause, values } = this.cqn2sql(query, data) | ||
const isLockQuery = query.SELECT.forUpdate || query.SELECT.forShareLock | ||
if (!isLockQuery) { | ||
// REVISIT: disable this for queries like (SELECT 1) | ||
// Will return multiple rows with objects inside | ||
query.SELECT.expand = 'root' | ||
} | ||
const { cqn, sql, temporary, blobs, withclause, values } = this.cqn2sql(query, data) | ||
delete query.SELECT.expand | ||
// REVISIT: add prepare options when param:true is used | ||
const sqlScript = this.wrapTemporary(temporary, withclause, blobs) | ||
const sqlScript = isLockQuery ? sql : this.wrapTemporary(temporary, withclause, blobs) | ||
let rows = (values?.length || blobs.length > 0) | ||
? await (await this.prepare(sqlScript, blobs.length)).all(values || []) | ||
: await this.exec(sqlScript) | ||
if (isLockQuery) { | ||
// Fetch actual locked results | ||
const resultQuery = query.clone() | ||
resultQuery.SELECT.forUpdate = undefined | ||
resultQuery.SELECT.forShareLock = undefined | ||
return this.onSELECT({ query: resultQuery, __proto__: req }) | ||
} | ||
if (rows.length) { | ||
@@ -144,3 +174,3 @@ rows = this.parseRows(rows) | ||
? entries.reduce((l, c) => l.then(() => ps.run(c)), Promise.resolve(0)) | ||
: ps.run(entries[0]) | ||
: entries.length > 1 ? await ps.runBatch(entries) : await ps.run(entries[0]) | ||
: ps.run()) | ||
@@ -235,3 +265,6 @@ return new this.class.InsertResults(cqn, results) | ||
prepare(sql, hasBlobs) { | ||
return this.ensureDBC().prepare(sql, hasBlobs) | ||
const stmt = this.ensureDBC().prepare(sql, hasBlobs) | ||
// we store the statements, to release them on commit/rollback all at once | ||
this.dbc.statements.push(stmt) | ||
return stmt | ||
} | ||
@@ -280,2 +313,6 @@ | ||
if (q.SELECT.from?.join && !q.SELECT.columns) { | ||
throw new Error('CQN query using joins must specify the selected columns.') | ||
} | ||
const { limit, one, orderBy, expand, columns = ['*'], localized, count, parent } = q.SELECT | ||
@@ -661,5 +698,9 @@ | ||
const isView = target.query || target.projection | ||
return (this.sql = `DROP ${isView ? 'VIEW' : 'TABLE'} ${this.name(target.name)}`) | ||
return (this.sql = `DROP ${isView ? 'VIEW' : 'TABLE'} ${this.quote(this.name(target.name))}`) | ||
} | ||
from_args(args) { | ||
return `(${ObjectKeys(args).map(k => `${this.quote(k)} => ${this.expr(args[k])}`)})` | ||
} | ||
orderBy(orderBy, localized) { | ||
@@ -817,4 +858,7 @@ return orderBy.map( | ||
const up = cur.toUpperCase() | ||
// When a logic operator is found the expression is not a comparison | ||
// When it is a local check it cannot be compared outside of the xpr | ||
if (up in logicOperators) return !local | ||
// When a compare operator is found the expression is a comparison | ||
if (up in compareOperators || (!local && up in logicOperators)) return true | ||
if (up in compareOperators) return true | ||
// When a case operator is found it is the start of the expression | ||
@@ -929,3 +973,3 @@ if (up in caseOperators) break | ||
// Loads a static result from the query `SELECT * FROM RESERVED_KEYWORDS` | ||
static ReservedWords = { ...super.ReservedWords, ...require('./ReservedWords.json') } | ||
static ReservedWords = { ...super.ReservedWords, ...hanaKeywords } | ||
@@ -1028,2 +1072,3 @@ static Functions = require('./cql-functions') | ||
DEBUG?.('BEGIN') | ||
if (this.dbc) this.dbc.statements = [] | ||
return this.dbc?.begin() | ||
@@ -1034,2 +1079,6 @@ } | ||
DEBUG?.('COMMIT') | ||
this.dbc?.statements?.forEach(stmt => stmt | ||
.then(stmt => stmt.drop()) | ||
.catch(() => { }) | ||
) | ||
return this.dbc?.commit() | ||
@@ -1040,2 +1089,6 @@ } | ||
DEBUG?.('ROLLBACK') | ||
this.dbc?.statements?.forEach(stmt => stmt | ||
.then(stmt => stmt.drop()) | ||
.catch(() => { }) | ||
) | ||
return this.dbc?.rollback() | ||
@@ -1042,0 +1095,0 @@ } |
{ | ||
"name": "@cap-js/hana", | ||
"version": "0.0.6", | ||
"version": "0.1.0", | ||
"description": "CDS database service for SAP HANA", | ||
@@ -24,2 +24,3 @@ "homepage": "https://cap.cloud.sap/", | ||
"test": "npm start && jest --silent", | ||
"test:remote": "jest --silent", | ||
"start": "npm run start:hce || npm run start:hxe", | ||
@@ -31,3 +32,3 @@ "start:hce": "cd ./tools/docker/hce/ && ./start.sh", | ||
"hdb": "^0.19.5", | ||
"@cap-js/db-service": "^1.6.0" | ||
"@cap-js/db-service": "^1.7.0" | ||
}, | ||
@@ -54,2 +55,2 @@ "peerDependencies": { | ||
"license": "SEE LICENSE" | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
118770
17
2397
Updated@cap-js/db-service@^1.7.0