velocious 1.0.568 → 1.0.569
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/README.md +20 -0
- package/build/configuration.js +36 -0
- package/build/database/drivers/base.js +167 -54
- package/build/database/drivers/mssql/index.js +10 -7
- package/build/database/drivers/mysql/index.js +10 -5
- package/build/database/drivers/pgsql/index.js +4 -4
- package/build/database/drivers/sqlite/base.js +2 -2
- package/build/database/drivers/sqlite/connection-sql-js.js +62 -2
- package/build/database/drivers/sqlite/index.web.js +74 -0
- package/build/database/operation-connection.js +110 -0
- package/build/database/operation-lease.js +47 -0
- package/build/database/operation.js +140 -0
- package/build/database/pool/base.js +26 -1
- package/build/database/pool/single-multi-use.js +49 -0
- package/build/database/query/model-class-query.js +38 -7
- package/build/database/query/preloader/belongs-to.js +3 -2
- package/build/database/query/preloader/has-many.js +4 -3
- package/build/database/query/preloader/has-one.js +2 -1
- package/build/database/query/preloader/query-for-model.js +17 -0
- package/build/database/query/query-data.js +12 -3
- package/build/database/query/with-count.js +5 -3
- package/build/database/record/acts-as-list.js +11 -8
- package/build/database/record/attachments/store.js +15 -11
- package/build/database/record/auditing.js +12 -9
- package/build/database/record/counter-cache-magnitude.js +5 -3
- package/build/database/record/index.js +95 -14
- package/build/database/record/instance-relationships/belongs-to.js +4 -2
- package/build/database/record/instance-relationships/has-many.js +7 -5
- package/build/database/record/instance-relationships/has-one.js +4 -2
- package/build/database/record/validators/uniqueness.js +3 -2
- package/build/frontend-models/websocket-publishers.js +2 -2
- package/build/src/configuration.d.ts +12 -0
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +35 -1
- package/build/src/database/drivers/base.d.ts +66 -20
- package/build/src/database/drivers/base.d.ts.map +1 -1
- package/build/src/database/drivers/base.js +158 -54
- package/build/src/database/drivers/mssql/index.d.ts +4 -1
- package/build/src/database/drivers/mssql/index.d.ts.map +1 -1
- package/build/src/database/drivers/mssql/index.js +11 -8
- package/build/src/database/drivers/mysql/index.d.ts +2 -1
- package/build/src/database/drivers/mysql/index.d.ts.map +1 -1
- package/build/src/database/drivers/mysql/index.js +10 -6
- package/build/src/database/drivers/pgsql/index.d.ts +2 -1
- package/build/src/database/drivers/pgsql/index.d.ts.map +1 -1
- package/build/src/database/drivers/pgsql/index.js +5 -5
- package/build/src/database/drivers/sqlite/base.d.ts +1 -1
- package/build/src/database/drivers/sqlite/base.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/base.js +3 -3
- package/build/src/database/drivers/sqlite/connection-sql-js.d.ts +20 -0
- package/build/src/database/drivers/sqlite/connection-sql-js.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/connection-sql-js.js +56 -3
- package/build/src/database/drivers/sqlite/index.web.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/index.web.js +64 -1
- package/build/src/database/operation-connection.d.ts +61 -0
- package/build/src/database/operation-connection.d.ts.map +1 -0
- package/build/src/database/operation-connection.js +93 -0
- package/build/src/database/operation-lease.d.ts +27 -0
- package/build/src/database/operation-lease.d.ts.map +1 -0
- package/build/src/database/operation-lease.js +44 -0
- package/build/src/database/operation.d.ts +77 -0
- package/build/src/database/operation.d.ts.map +1 -0
- package/build/src/database/operation.js +123 -0
- package/build/src/database/pool/base.d.ts +14 -0
- package/build/src/database/pool/base.d.ts.map +1 -1
- package/build/src/database/pool/base.js +24 -2
- package/build/src/database/pool/single-multi-use.d.ts +1 -0
- package/build/src/database/pool/single-multi-use.d.ts.map +1 -1
- package/build/src/database/pool/single-multi-use.js +49 -1
- package/build/src/database/query/model-class-query.d.ts +14 -0
- package/build/src/database/query/model-class-query.d.ts.map +1 -1
- package/build/src/database/query/model-class-query.js +32 -8
- package/build/src/database/query/preloader/belongs-to.d.ts.map +1 -1
- package/build/src/database/query/preloader/belongs-to.js +4 -3
- package/build/src/database/query/preloader/has-many.d.ts.map +1 -1
- package/build/src/database/query/preloader/has-many.js +5 -4
- package/build/src/database/query/preloader/has-one.d.ts.map +1 -1
- package/build/src/database/query/preloader/has-one.js +3 -2
- package/build/src/database/query/preloader/query-for-model.d.ts +10 -0
- package/build/src/database/query/preloader/query-for-model.d.ts.map +1 -0
- package/build/src/database/query/preloader/query-for-model.js +16 -0
- package/build/src/database/query/query-data.d.ts.map +1 -1
- package/build/src/database/query/query-data.js +13 -4
- package/build/src/database/query/with-count.d.ts.map +1 -1
- package/build/src/database/query/with-count.js +6 -4
- package/build/src/database/record/acts-as-list.js +12 -9
- package/build/src/database/record/attachments/attachment-record.d.ts +9 -0
- package/build/src/database/record/attachments/attachment-record.d.ts.map +1 -1
- package/build/src/database/record/attachments/store.d.ts +4 -2
- package/build/src/database/record/attachments/store.d.ts.map +1 -1
- package/build/src/database/record/attachments/store.js +16 -12
- package/build/src/database/record/auditing.d.ts.map +1 -1
- package/build/src/database/record/auditing.js +13 -10
- package/build/src/database/record/counter-cache-magnitude.js +6 -4
- package/build/src/database/record/index.d.ts +42 -2
- package/build/src/database/record/index.d.ts.map +1 -1
- package/build/src/database/record/index.js +87 -15
- package/build/src/database/record/instance-relationships/belongs-to.d.ts.map +1 -1
- package/build/src/database/record/instance-relationships/belongs-to.js +4 -3
- package/build/src/database/record/instance-relationships/has-many.d.ts.map +1 -1
- package/build/src/database/record/instance-relationships/has-many.js +7 -5
- package/build/src/database/record/instance-relationships/has-one.d.ts.map +1 -1
- package/build/src/database/record/instance-relationships/has-one.js +4 -3
- package/build/src/database/record/validators/uniqueness.d.ts.map +1 -1
- package/build/src/database/record/validators/uniqueness.js +4 -3
- package/build/src/frontend-models/websocket-publishers.js +3 -3
- package/build/src/sync/server-sequence-allocator.d.ts +16 -4
- package/build/src/sync/server-sequence-allocator.d.ts.map +1 -1
- package/build/src/sync/server-sequence-allocator.js +37 -11
- package/build/src/sync/sync-client.d.ts.map +1 -1
- package/build/src/sync/sync-client.js +7 -3
- package/build/src/sync/sync-publisher.d.ts +2 -1
- package/build/src/sync/sync-publisher.d.ts.map +1 -1
- package/build/src/sync/sync-publisher.js +11 -6
- package/build/sync/server-sequence-allocator.js +43 -10
- package/build/sync/sync-client.js +6 -2
- package/build/sync/sync-publisher.js +10 -5
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/configuration.js +36 -0
- package/src/database/drivers/base.js +167 -54
- package/src/database/drivers/mssql/index.js +10 -7
- package/src/database/drivers/mysql/index.js +10 -5
- package/src/database/drivers/pgsql/index.js +4 -4
- package/src/database/drivers/sqlite/base.js +2 -2
- package/src/database/drivers/sqlite/connection-sql-js.js +62 -2
- package/src/database/drivers/sqlite/index.web.js +74 -0
- package/src/database/operation-connection.js +110 -0
- package/src/database/operation-lease.js +47 -0
- package/src/database/operation.js +140 -0
- package/src/database/pool/base.js +26 -1
- package/src/database/pool/single-multi-use.js +49 -0
- package/src/database/query/model-class-query.js +38 -7
- package/src/database/query/preloader/belongs-to.js +3 -2
- package/src/database/query/preloader/has-many.js +4 -3
- package/src/database/query/preloader/has-one.js +2 -1
- package/src/database/query/preloader/query-for-model.js +17 -0
- package/src/database/query/query-data.js +12 -3
- package/src/database/query/with-count.js +5 -3
- package/src/database/record/acts-as-list.js +11 -8
- package/src/database/record/attachments/store.js +15 -11
- package/src/database/record/auditing.js +12 -9
- package/src/database/record/counter-cache-magnitude.js +5 -3
- package/src/database/record/index.js +95 -14
- package/src/database/record/instance-relationships/belongs-to.js +4 -2
- package/src/database/record/instance-relationships/has-many.js +7 -5
- package/src/database/record/instance-relationships/has-one.js +4 -2
- package/src/database/record/validators/uniqueness.js +3 -2
- package/src/frontend-models/websocket-publishers.js +2 -2
- package/src/sync/server-sequence-allocator.js +43 -10
- package/src/sync/sync-client.js +6 -2
- package/src/sync/sync-publisher.js +10 -5
package/README.md
CHANGED
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
* In-process driver schema metadata caching (see [docs/schema-metadata-cache.md](docs/schema-metadata-cache.md))
|
|
35
35
|
* Planned local-first shared-resource sync architecture (see [docs/offline-sync.md](docs/offline-sync.md))
|
|
36
36
|
* Selective named database connection checkouts, bounded pool waits, and debugging held connections (see [docs/database-connections.md](docs/database-connections.md))
|
|
37
|
+
* Explicit singular-database operation transactions whose model scopes preserve ownership through records, relationships, lifecycle work, nested savepoints, and commit callbacks (see [docs/operation-scoped-transactions.md](docs/operation-scoped-transactions.md))
|
|
37
38
|
* AbortSignal-driven MySQL/MariaDB query cancellation for raw, model, and cross-tenant aggregate queries (see [docs/database-query-cancellation.md](docs/database-query-cancellation.md))
|
|
38
39
|
* Optional built-in debug endpoint for inspecting server and database connection state (see [docs/debug-endpoint.md](docs/debug-endpoint.md))
|
|
39
40
|
* Optional built-in API manifest endpoint describing every registered frontend-model resource as human- and machine-readable JSON (see [docs/api-manifest-endpoint.md](docs/api-manifest-endpoint.md))
|
|
@@ -51,6 +52,25 @@ npx velocious init
|
|
|
51
52
|
|
|
52
53
|
By default, Velocious looks for your configuration in `src/config/configuration.js`. If you keep the configuration elsewhere, make sure your app imports it early and calls `configuration.setCurrent()`.
|
|
53
54
|
|
|
55
|
+
# Operation-scoped transactions
|
|
56
|
+
|
|
57
|
+
Use `configuration.withTransaction` for an atomic unit of model work on one database:
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
await configuration.withTransaction({databaseIdentifier: "default", name: "accept ticket"}, async (operation) => {
|
|
61
|
+
const ticket = await operation.forModel(Ticket).find(ticketId)
|
|
62
|
+
|
|
63
|
+
ticket.setAccepted(true)
|
|
64
|
+
await ticket.save()
|
|
65
|
+
|
|
66
|
+
await operation.afterCommit(async () => {
|
|
67
|
+
await publishAcceptedTicket(ticket.id())
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Use operation-bound model scopes and their loaded records throughout the callback. `operation.transaction` adds a nested savepoint, and `operation.connection()` is the deliberate escape hatch for owned raw SQL. Cross-database models, same-identifier tenant switches to another physical database, and operation handles used after the callback are rejected. On shared SQLite/SQL.js pools, unrelated work waits for the operation lease, while admission during an already-open ordinary transaction is rejected. See [operation-scoped transactions](docs/operation-scoped-transactions.md) for pool behavior, after-commit failure semantics, and migration guidance.
|
|
73
|
+
|
|
54
74
|
# Development
|
|
55
75
|
|
|
56
76
|
When working on Velocious itself, npm scripts are cross-platform (Windows `cmd`/PowerShell and POSIX shells):
|
package/build/configuration.js
CHANGED
|
@@ -16,6 +16,7 @@ import {digg} from "diggerize"
|
|
|
16
16
|
import gettextConfig from "gettext-universal/build/src/config.js"
|
|
17
17
|
import translate from "gettext-universal/build/src/translate.js"
|
|
18
18
|
import Ability from "./authorization/ability.js"
|
|
19
|
+
import DatabaseOperation from "./database/operation.js"
|
|
19
20
|
import {initializeAuditedModelRelationships} from "./database/record/auditing.js"
|
|
20
21
|
import EventEmitter from "./utils/event-emitter.js"
|
|
21
22
|
import VelociousWebsocketChannelSubscribers from "./http-server/websocket-channel-subscribers.js"
|
|
@@ -2896,6 +2897,41 @@ export default class VelociousConfiguration {
|
|
|
2896
2897
|
})
|
|
2897
2898
|
}
|
|
2898
2899
|
|
|
2900
|
+
/**
|
|
2901
|
+
* Runs explicit model work in a transaction pinned to one database connection.
|
|
2902
|
+
* @template T
|
|
2903
|
+
* @param {{databaseIdentifier: string, name?: string}} options - Operation options.
|
|
2904
|
+
* @param {(operation: DatabaseOperation) => Promise<T>} callback - Operation callback.
|
|
2905
|
+
* @returns {Promise<T>} - Resolves with the callback result.
|
|
2906
|
+
*/
|
|
2907
|
+
async withTransaction({databaseIdentifier, name = "Configuration.withTransaction", ...restArgs}, callback) {
|
|
2908
|
+
restArgsError(restArgs)
|
|
2909
|
+
|
|
2910
|
+
if (!databaseIdentifier) throw new Error("Configuration.withTransaction requires a databaseIdentifier")
|
|
2911
|
+
if (typeof callback != "function") throw new Error("Configuration.withTransaction requires a callback")
|
|
2912
|
+
if (!this.getDatabaseIdentifiers().includes(databaseIdentifier)) {
|
|
2913
|
+
throw new Error(`Unknown or inactive database identifier: ${databaseIdentifier}`)
|
|
2914
|
+
}
|
|
2915
|
+
|
|
2916
|
+
const pool = this.getDatabasePool(databaseIdentifier)
|
|
2917
|
+
|
|
2918
|
+
return await pool.withOperationConnection({name}, async (connection, owner) => {
|
|
2919
|
+
const operation = new DatabaseOperation({
|
|
2920
|
+
configuration: this,
|
|
2921
|
+
configurationReuseKey: pool.getConnectionConfigurationReuseKey(connection),
|
|
2922
|
+
connection,
|
|
2923
|
+
databaseIdentifier,
|
|
2924
|
+
owner
|
|
2925
|
+
})
|
|
2926
|
+
|
|
2927
|
+
try {
|
|
2928
|
+
return await operation.transaction(async () => await callback(operation))
|
|
2929
|
+
} finally {
|
|
2930
|
+
operation.complete()
|
|
2931
|
+
}
|
|
2932
|
+
})
|
|
2933
|
+
}
|
|
2934
|
+
|
|
2899
2935
|
/**
|
|
2900
2936
|
* Runs callback with database connections for the requested identifiers.
|
|
2901
2937
|
* @template T
|
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
* @property {boolean} [sessionTimeZone] - Whether to ensure the configured database session time zone before the query.
|
|
62
62
|
* @property {AbortSignal} [signal] - Aborts the in-flight query (destroying its connection) when it fires.
|
|
63
63
|
* @property {string} [sourceStack] - Stack captured at the caller boundary.
|
|
64
|
+
* @property {symbol} [operationOwner] - Opaque owner for an operation-leased connection.
|
|
64
65
|
*/
|
|
65
66
|
|
|
66
67
|
/**
|
|
@@ -127,6 +128,21 @@ import TableForeignKey from "../table-data/table-foreign-key.js"
|
|
|
127
128
|
import wait from "awaitery/build/wait.js"
|
|
128
129
|
import {optionalPositiveInteger} from "typanic"
|
|
129
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Marks a callback failure that happened after the owning transaction was durably committed.
|
|
133
|
+
* The public transaction boundary unwraps it before deadlock classification.
|
|
134
|
+
*/
|
|
135
|
+
class VelociousDatabaseAfterCommitCallbackError extends Error {
|
|
136
|
+
/**
|
|
137
|
+
* Runs constructor.
|
|
138
|
+
* @param {?} callbackError - Original callback failure.
|
|
139
|
+
*/
|
|
140
|
+
constructor(callbackError) {
|
|
141
|
+
super("Database afterCommit callback failed")
|
|
142
|
+
this.callbackError = callbackError
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
130
146
|
/**
|
|
131
147
|
* Runs now ms.
|
|
132
148
|
* @returns {number} - Current high-resolution-ish timestamp in milliseconds.
|
|
@@ -175,6 +191,11 @@ export default class VelociousDatabaseDriversBase {
|
|
|
175
191
|
_activeQuery = null
|
|
176
192
|
/** @type {Map<string, number>} */
|
|
177
193
|
_heldAdvisoryLocks = new Map()
|
|
194
|
+
/**
|
|
195
|
+
* Exclusive operation lease installed by a single-multi-use pool.
|
|
196
|
+
* @type {import("../operation-lease.js").default | undefined}
|
|
197
|
+
*/
|
|
198
|
+
_operationLease = undefined
|
|
178
199
|
|
|
179
200
|
/**
|
|
180
201
|
* Runs constructor.
|
|
@@ -488,6 +509,46 @@ export default class VelociousDatabaseDriversBase {
|
|
|
488
509
|
return this.configuration
|
|
489
510
|
}
|
|
490
511
|
|
|
512
|
+
/**
|
|
513
|
+
* Installs an operation lease atomically with ordinary transaction admission.
|
|
514
|
+
* @param {import("../operation-lease.js").default} operationLease - Active lease.
|
|
515
|
+
* @returns {Promise<void>} - Resolves once the lease owns transaction admission.
|
|
516
|
+
*/
|
|
517
|
+
async setOperationLease(operationLease) {
|
|
518
|
+
await this._transactionsActionsMutex.sync(async () => {
|
|
519
|
+
if (this._operationLease) throw new Error("A database operation lease is already active")
|
|
520
|
+
if (this._transactionsCount > 0) {
|
|
521
|
+
throw new Error("Cannot start a database operation while an unrelated ordinary transaction is already active")
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
this._operationLease = operationLease
|
|
525
|
+
})
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Clears the matching operation lease.
|
|
530
|
+
* @param {import("../operation-lease.js").default} operationLease - Lease to clear.
|
|
531
|
+
* @returns {void}
|
|
532
|
+
*/
|
|
533
|
+
clearOperationLease(operationLease) {
|
|
534
|
+
if (this._operationLease !== operationLease) {
|
|
535
|
+
throw new Error("Cannot clear a database operation lease owned by another operation")
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
this._operationLease = undefined
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Waits for an unrelated operation lease to release.
|
|
543
|
+
* @param {symbol | undefined} operationOwner - Candidate operation owner.
|
|
544
|
+
* @returns {Promise<void>}
|
|
545
|
+
*/
|
|
546
|
+
async _waitForOperationLease(operationOwner) {
|
|
547
|
+
const operationLease = this._operationLease
|
|
548
|
+
|
|
549
|
+
if (operationLease) await operationLease.wait(operationOwner)
|
|
550
|
+
}
|
|
551
|
+
|
|
491
552
|
/**
|
|
492
553
|
* Runs get id seq.
|
|
493
554
|
* @returns {number | undefined} - The id seq.
|
|
@@ -739,9 +800,10 @@ export default class VelociousDatabaseDriversBase {
|
|
|
739
800
|
/**
|
|
740
801
|
* Runs last insert id.
|
|
741
802
|
* @abstract
|
|
803
|
+
* @param {QueryOptions} [_options] - Query ownership options.
|
|
742
804
|
* @returns {Promise<number>} - Resolves with the last insert id.
|
|
743
805
|
*/
|
|
744
|
-
lastInsertID() {
|
|
806
|
+
lastInsertID(_options = {}) {
|
|
745
807
|
throw new Error(`${this.constructor.name}#lastInsertID not implemented`)
|
|
746
808
|
}
|
|
747
809
|
|
|
@@ -932,12 +994,16 @@ export default class VelociousDatabaseDriversBase {
|
|
|
932
994
|
* The outermost transaction retries the whole callback on a deadlock / lock-wait-timeout,
|
|
933
995
|
* because such errors roll the entire transaction back and the standard recovery is to
|
|
934
996
|
* restart it. Nested savepoints let the deadlock bubble up to this outer retry.
|
|
935
|
-
* @
|
|
936
|
-
* @
|
|
997
|
+
* @template T
|
|
998
|
+
* @param {() => Promise<T>} callback - Callback function.
|
|
999
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1000
|
+
* @returns {Promise<T>} - Resolves with the transaction result.
|
|
937
1001
|
*/
|
|
938
|
-
async transaction(callback) {
|
|
1002
|
+
async transaction(callback, options = {}) {
|
|
1003
|
+
await this._waitForOperationLease(options.operationOwner)
|
|
1004
|
+
|
|
939
1005
|
if (this._transactionsCount > 0) {
|
|
940
|
-
return await this._runTransactionAttempt(callback)
|
|
1006
|
+
return await this._runTransactionAttempt(callback, options)
|
|
941
1007
|
}
|
|
942
1008
|
|
|
943
1009
|
const args = this.getArgs()
|
|
@@ -950,8 +1016,10 @@ export default class VelociousDatabaseDriversBase {
|
|
|
950
1016
|
attempt++
|
|
951
1017
|
|
|
952
1018
|
try {
|
|
953
|
-
return await this._runTransactionAttempt(callback)
|
|
1019
|
+
return await this._runTransactionAttempt(callback, options)
|
|
954
1020
|
} catch (error) {
|
|
1021
|
+
if (error instanceof VelociousDatabaseAfterCommitCallbackError) throw error.callbackError
|
|
1022
|
+
|
|
955
1023
|
const retryInfo = error instanceof Error ? this.retryableDatabaseError(error) : {retry: false, reconnect: false}
|
|
956
1024
|
|
|
957
1025
|
if (retryInfo.deadlock && attempt < maxAttempts && this._transactionsCount == 0) {
|
|
@@ -993,10 +1061,12 @@ export default class VelociousDatabaseDriversBase {
|
|
|
993
1061
|
* Runs a single transaction attempt: starts a transaction (or a savepoint when nested), runs
|
|
994
1062
|
* `callback`, and commits — rolling back on error. {@link transaction} wraps this with deadlock
|
|
995
1063
|
* retry at the outermost level.
|
|
996
|
-
* @
|
|
1064
|
+
* @template T
|
|
1065
|
+
* @param {() => Promise<T>} callback - Callback function.
|
|
1066
|
+
* @param {Pick<QueryOptions, "operationOwner">} options - Transaction ownership.
|
|
997
1067
|
* @returns {Promise<?>} - Resolves with the transaction result.
|
|
998
1068
|
*/
|
|
999
|
-
async _runTransactionAttempt(callback) {
|
|
1069
|
+
async _runTransactionAttempt(callback, options) {
|
|
1000
1070
|
const savePointName = this.generateSavePointName()
|
|
1001
1071
|
/**
|
|
1002
1072
|
* Callback frame.
|
|
@@ -1007,14 +1077,19 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1007
1077
|
|
|
1008
1078
|
this._afterCommitCallbackFrames.push(callbackFrame)
|
|
1009
1079
|
|
|
1010
|
-
|
|
1011
|
-
this.
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1080
|
+
try {
|
|
1081
|
+
if (this._transactionsCount == 0) {
|
|
1082
|
+
this.logger.debug("Start transaction")
|
|
1083
|
+
await this.startTransaction(options)
|
|
1084
|
+
transactionStarted = true
|
|
1085
|
+
} else {
|
|
1086
|
+
this.logger.debug("Start savepoint", savePointName)
|
|
1087
|
+
await this.startSavePoint(savePointName, options)
|
|
1088
|
+
savePointStarted = true
|
|
1089
|
+
}
|
|
1090
|
+
} catch (error) {
|
|
1091
|
+
this._afterCommitCallbackFrames.pop()
|
|
1092
|
+
throw error
|
|
1018
1093
|
}
|
|
1019
1094
|
|
|
1020
1095
|
let result
|
|
@@ -1024,15 +1099,13 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1024
1099
|
|
|
1025
1100
|
if (savePointStarted) {
|
|
1026
1101
|
this.logger.debug("Release savepoint", savePointName)
|
|
1027
|
-
await this.releaseSavePoint(savePointName)
|
|
1102
|
+
await this.releaseSavePoint(savePointName, options)
|
|
1028
1103
|
}
|
|
1029
1104
|
|
|
1030
1105
|
if (transactionStarted) {
|
|
1031
1106
|
this.logger.debug("Commit transaction")
|
|
1032
|
-
await this.commitTransaction()
|
|
1107
|
+
await this.commitTransaction(options)
|
|
1033
1108
|
}
|
|
1034
|
-
|
|
1035
|
-
await this._commitAfterCommitCallbackFrame()
|
|
1036
1109
|
} catch (error) {
|
|
1037
1110
|
if (error instanceof Error) {
|
|
1038
1111
|
this.logger.debug("Transaction error", error.message)
|
|
@@ -1045,14 +1118,14 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1045
1118
|
if (savePointStarted) {
|
|
1046
1119
|
this.logger.debug("Rollback savepoint", savePointName)
|
|
1047
1120
|
try {
|
|
1048
|
-
await this.rollbackSavePoint(savePointName)
|
|
1121
|
+
await this.rollbackSavePoint(savePointName, options)
|
|
1049
1122
|
} catch (savePointError) {
|
|
1050
1123
|
const message = savePointError instanceof Error ? savePointError.message : `${savePointError}`
|
|
1051
1124
|
|
|
1052
1125
|
// MySQL sometimes drops savepoints unexpectedly; fall back to rolling back the full transaction
|
|
1053
1126
|
if (message.includes("SAVEPOINT") || message.includes("ER_SP_DOES_NOT_EXIST")) {
|
|
1054
1127
|
this.logger.debug("Savepoint rollback failed; rolling back entire transaction instead")
|
|
1055
|
-
await this.rollbackTransaction()
|
|
1128
|
+
await this.rollbackTransaction(options)
|
|
1056
1129
|
transactionRolledBack = true
|
|
1057
1130
|
} else {
|
|
1058
1131
|
throw savePointError
|
|
@@ -1066,7 +1139,7 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1066
1139
|
// `_transactionsCount` below zero, which would then defeat the outermost deadlock-retry guard.
|
|
1067
1140
|
if (transactionStarted && !transactionRolledBack && this._transactionsCount > 0) {
|
|
1068
1141
|
this.logger.debug("Rollback transaction")
|
|
1069
|
-
await this.rollbackTransaction()
|
|
1142
|
+
await this.rollbackTransaction(options)
|
|
1070
1143
|
}
|
|
1071
1144
|
|
|
1072
1145
|
this._afterCommitCallbackFrames.pop()
|
|
@@ -1074,6 +1147,12 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1074
1147
|
throw error
|
|
1075
1148
|
}
|
|
1076
1149
|
|
|
1150
|
+
try {
|
|
1151
|
+
await this._commitAfterCommitCallbackFrame()
|
|
1152
|
+
} catch (error) {
|
|
1153
|
+
throw new VelociousDatabaseAfterCommitCallbackError(error)
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1077
1156
|
return result
|
|
1078
1157
|
}
|
|
1079
1158
|
|
|
@@ -1081,9 +1160,12 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1081
1160
|
* Runs a callback after the surrounding transaction commits.
|
|
1082
1161
|
* If no transaction is active, the callback runs immediately.
|
|
1083
1162
|
* @param {() => void | Promise<void>} callback - Callback.
|
|
1163
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Callback ownership.
|
|
1084
1164
|
* @returns {Promise<void>} - Resolves when the callback has been registered or run.
|
|
1085
1165
|
*/
|
|
1086
|
-
async afterCommit(callback) {
|
|
1166
|
+
async afterCommit(callback, options = {}) {
|
|
1167
|
+
await this._waitForOperationLease(options.operationOwner)
|
|
1168
|
+
|
|
1087
1169
|
const currentFrame = this._afterCommitCallbackFrames[this._afterCommitCallbackFrames.length - 1]
|
|
1088
1170
|
|
|
1089
1171
|
if (!currentFrame) {
|
|
@@ -1102,40 +1184,60 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1102
1184
|
|
|
1103
1185
|
/**
|
|
1104
1186
|
* Runs start transaction.
|
|
1187
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1105
1188
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1106
1189
|
*/
|
|
1107
|
-
async startTransaction() {
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1190
|
+
async startTransaction(options = {}) {
|
|
1191
|
+
while (true) {
|
|
1192
|
+
/** @type {import("../operation-lease.js").default | undefined} */
|
|
1193
|
+
let blockingOperationLease
|
|
1194
|
+
|
|
1195
|
+
await this._transactionsActionsMutex.sync(async () => {
|
|
1196
|
+
const operationLease = this._operationLease
|
|
1197
|
+
|
|
1198
|
+
if (operationLease && options.operationOwner !== operationLease.owner) {
|
|
1199
|
+
blockingOperationLease = operationLease
|
|
1200
|
+
return
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
await this._startTransactionAction(options)
|
|
1204
|
+
this._transactionsCount++
|
|
1205
|
+
})
|
|
1206
|
+
|
|
1207
|
+
if (!blockingOperationLease) return
|
|
1208
|
+
|
|
1209
|
+
await blockingOperationLease.wait(options.operationOwner)
|
|
1210
|
+
}
|
|
1112
1211
|
}
|
|
1113
1212
|
|
|
1114
1213
|
/**
|
|
1115
1214
|
* Runs start transaction action.
|
|
1215
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1116
1216
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1117
1217
|
*/
|
|
1118
|
-
async _startTransactionAction() {
|
|
1119
|
-
await this.query("BEGIN TRANSACTION")
|
|
1218
|
+
async _startTransactionAction(options = {}) {
|
|
1219
|
+
await this.query("BEGIN TRANSACTION", options)
|
|
1120
1220
|
}
|
|
1121
1221
|
|
|
1122
1222
|
/**
|
|
1123
1223
|
* Runs commit transaction.
|
|
1224
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1124
1225
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1125
1226
|
*/
|
|
1126
|
-
async commitTransaction() {
|
|
1227
|
+
async commitTransaction(options = {}) {
|
|
1127
1228
|
await this._transactionsActionsMutex.sync(async () => {
|
|
1128
|
-
await this._commitTransactionAction()
|
|
1229
|
+
await this._commitTransactionAction(options)
|
|
1129
1230
|
this._transactionsCount--
|
|
1130
1231
|
})
|
|
1131
1232
|
}
|
|
1132
1233
|
|
|
1133
1234
|
/**
|
|
1134
1235
|
* Runs commit transaction action.
|
|
1236
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1135
1237
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1136
1238
|
*/
|
|
1137
|
-
async _commitTransactionAction() {
|
|
1138
|
-
await this.query("COMMIT")
|
|
1239
|
+
async _commitTransactionAction(options = {}) {
|
|
1240
|
+
await this.query("COMMIT", options)
|
|
1139
1241
|
}
|
|
1140
1242
|
|
|
1141
1243
|
/**
|
|
@@ -1183,6 +1285,7 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1183
1285
|
* @returns {Promise<QueryResultType>} - Resolves with the query.
|
|
1184
1286
|
*/
|
|
1185
1287
|
async query(sql, options = {}) {
|
|
1288
|
+
await this._waitForOperationLease(options.operationOwner)
|
|
1186
1289
|
this._assertWritableQuery(sql)
|
|
1187
1290
|
|
|
1188
1291
|
let tries = 0
|
|
@@ -1232,16 +1335,18 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1232
1335
|
/**
|
|
1233
1336
|
* Executes a mutation and returns the number of rows changed by that statement.
|
|
1234
1337
|
* @param {string} sql - Mutation SQL string.
|
|
1338
|
+
* @param {QueryOptions} [options] - Query ownership options.
|
|
1235
1339
|
* @returns {Promise<number>} - Affected row count.
|
|
1236
1340
|
*/
|
|
1237
|
-
async affectedRows(sql) {
|
|
1341
|
+
async affectedRows(sql, options = {}) {
|
|
1342
|
+
await this._waitForOperationLease(options.operationOwner)
|
|
1238
1343
|
this._assertWritableQuery(sql)
|
|
1239
|
-
await this.beforeQuery(sql,
|
|
1344
|
+
await this.beforeQuery(sql, options)
|
|
1240
1345
|
|
|
1241
1346
|
try {
|
|
1242
1347
|
return await this._affectedRowsActual(sql)
|
|
1243
1348
|
} finally {
|
|
1244
|
-
await this.afterQuery(sql,
|
|
1349
|
+
await this.afterQuery(sql, options)
|
|
1245
1350
|
}
|
|
1246
1351
|
}
|
|
1247
1352
|
|
|
@@ -1609,12 +1714,13 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1609
1714
|
|
|
1610
1715
|
/**
|
|
1611
1716
|
* Runs rollback transaction.
|
|
1717
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1612
1718
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1613
1719
|
*/
|
|
1614
|
-
async rollbackTransaction() {
|
|
1720
|
+
async rollbackTransaction(options = {}) {
|
|
1615
1721
|
await this._transactionsActionsMutex.sync(async () => {
|
|
1616
1722
|
try {
|
|
1617
|
-
await this._rollbackTransactionAction()
|
|
1723
|
+
await this._rollbackTransactionAction(options)
|
|
1618
1724
|
} finally {
|
|
1619
1725
|
this._transactionsCount--
|
|
1620
1726
|
|
|
@@ -1630,10 +1736,11 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1630
1736
|
|
|
1631
1737
|
/**
|
|
1632
1738
|
* Runs rollback transaction action.
|
|
1739
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1633
1740
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1634
1741
|
*/
|
|
1635
|
-
async _rollbackTransactionAction() {
|
|
1636
|
-
await this.query("ROLLBACK")
|
|
1742
|
+
async _rollbackTransactionAction(options = {}) {
|
|
1743
|
+
await this.query("ROLLBACK", options)
|
|
1637
1744
|
}
|
|
1638
1745
|
|
|
1639
1746
|
/**
|
|
@@ -1647,21 +1754,23 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1647
1754
|
/**
|
|
1648
1755
|
* Runs start save point.
|
|
1649
1756
|
* @param {string} savePointName - Save point name.
|
|
1757
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1650
1758
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1651
1759
|
*/
|
|
1652
|
-
async startSavePoint(savePointName) {
|
|
1760
|
+
async startSavePoint(savePointName, options = {}) {
|
|
1653
1761
|
await this._transactionsActionsMutex.sync(async () => {
|
|
1654
|
-
await this._startSavePointAction(savePointName)
|
|
1762
|
+
await this._startSavePointAction(savePointName, options)
|
|
1655
1763
|
})
|
|
1656
1764
|
}
|
|
1657
1765
|
|
|
1658
1766
|
/**
|
|
1659
1767
|
* Runs start save point action.
|
|
1660
1768
|
* @param {string} savePointName - Save point name.
|
|
1769
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1661
1770
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1662
1771
|
*/
|
|
1663
|
-
async _startSavePointAction(savePointName) {
|
|
1664
|
-
await this.query(`SAVEPOINT ${savePointName}
|
|
1772
|
+
async _startSavePointAction(savePointName, options = {}) {
|
|
1773
|
+
await this.query(`SAVEPOINT ${savePointName}`, options)
|
|
1665
1774
|
}
|
|
1666
1775
|
|
|
1667
1776
|
/**
|
|
@@ -1691,22 +1800,24 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1691
1800
|
/**
|
|
1692
1801
|
* Runs release save point.
|
|
1693
1802
|
* @param {string} savePointName - Save point name.
|
|
1803
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1694
1804
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1695
1805
|
*/
|
|
1696
|
-
async releaseSavePoint(savePointName) {
|
|
1806
|
+
async releaseSavePoint(savePointName, options = {}) {
|
|
1697
1807
|
await this._transactionsActionsMutex.sync(async () => {
|
|
1698
|
-
await this._releaseSavePointAction(savePointName)
|
|
1808
|
+
await this._releaseSavePointAction(savePointName, options)
|
|
1699
1809
|
})
|
|
1700
1810
|
}
|
|
1701
1811
|
|
|
1702
1812
|
/**
|
|
1703
1813
|
* Runs release save point action.
|
|
1704
1814
|
* @param {string} savePointName - Save point name.
|
|
1815
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1705
1816
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1706
1817
|
*/
|
|
1707
|
-
async _releaseSavePointAction(savePointName) {
|
|
1818
|
+
async _releaseSavePointAction(savePointName, options = {}) {
|
|
1708
1819
|
try {
|
|
1709
|
-
await this.query(`RELEASE SAVEPOINT ${savePointName}
|
|
1820
|
+
await this.query(`RELEASE SAVEPOINT ${savePointName}`, options)
|
|
1710
1821
|
} catch (error) {
|
|
1711
1822
|
const message = error instanceof Error ? error.message : `${error}`
|
|
1712
1823
|
|
|
@@ -1723,21 +1834,23 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1723
1834
|
/**
|
|
1724
1835
|
* Runs rollback save point.
|
|
1725
1836
|
* @param {string} savePointName - Save point name.
|
|
1837
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1726
1838
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1727
1839
|
*/
|
|
1728
|
-
async rollbackSavePoint(savePointName) {
|
|
1840
|
+
async rollbackSavePoint(savePointName, options = {}) {
|
|
1729
1841
|
await this._transactionsActionsMutex.sync(async () => {
|
|
1730
|
-
await this._rollbackSavePointAction(savePointName)
|
|
1842
|
+
await this._rollbackSavePointAction(savePointName, options)
|
|
1731
1843
|
})
|
|
1732
1844
|
}
|
|
1733
1845
|
|
|
1734
1846
|
/**
|
|
1735
1847
|
* Runs rollback save point action.
|
|
1736
1848
|
* @param {string} savePointName - Save point name.
|
|
1849
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1737
1850
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1738
1851
|
*/
|
|
1739
|
-
async _rollbackSavePointAction(savePointName) {
|
|
1740
|
-
await this.query(`ROLLBACK TO SAVEPOINT ${savePointName}
|
|
1852
|
+
async _rollbackSavePointAction(savePointName, options = {}) {
|
|
1853
|
+
await this.query(`ROLLBACK TO SAVEPOINT ${savePointName}`, options)
|
|
1741
1854
|
}
|
|
1742
1855
|
|
|
1743
1856
|
/**
|
|
@@ -463,8 +463,8 @@ export default class VelociousDatabaseDriversMssql extends Base{
|
|
|
463
463
|
})
|
|
464
464
|
}
|
|
465
465
|
|
|
466
|
-
async lastInsertID() {
|
|
467
|
-
const result = await this.query("SELECT SCOPE_IDENTITY() AS last_insert_id")
|
|
466
|
+
async lastInsertID(options = {}) {
|
|
467
|
+
const result = await this.query("SELECT SCOPE_IDENTITY() AS last_insert_id", options)
|
|
468
468
|
const lastInsertID = digg(result, 0, "last_insert_id")
|
|
469
469
|
|
|
470
470
|
if (lastInsertID === null) throw new Error("Couldn't get the last inserted ID")
|
|
@@ -534,29 +534,32 @@ export default class VelociousDatabaseDriversMssql extends Base{
|
|
|
534
534
|
/**
|
|
535
535
|
* Runs start save point action.
|
|
536
536
|
* @param {string} savePointName - Save point name.
|
|
537
|
+
* @param {Pick<import("../base.js").QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
537
538
|
* @returns {Promise<void>} - Resolves when complete.
|
|
538
539
|
*/
|
|
539
|
-
async _startSavePointAction(savePointName) {
|
|
540
|
-
await this.query(`SAVE TRANSACTION [${savePointName}]
|
|
540
|
+
async _startSavePointAction(savePointName, options = {}) {
|
|
541
|
+
await this.query(`SAVE TRANSACTION [${savePointName}]`, options)
|
|
541
542
|
}
|
|
542
543
|
|
|
543
544
|
/**
|
|
544
545
|
* Runs release save point action.
|
|
545
546
|
* @param {string} savePointName - Save point name.
|
|
547
|
+
* @param {Pick<import("../base.js").QueryOptions, "operationOwner">} [_options] - Transaction ownership.
|
|
546
548
|
* @returns {Promise<void>} - Resolves when complete.
|
|
547
549
|
*/
|
|
548
|
-
async _releaseSavePointAction(savePointName
|
|
550
|
+
async _releaseSavePointAction(savePointName, _options = {}) {
|
|
549
551
|
// Do nothing in MS-SQL.
|
|
550
552
|
}
|
|
551
553
|
|
|
552
554
|
/**
|
|
553
555
|
* Runs rollback save point action.
|
|
554
556
|
* @param {string} savePointName - Save point name.
|
|
557
|
+
* @param {Pick<import("../base.js").QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
555
558
|
* @returns {Promise<void>} - Resolves when complete.
|
|
556
559
|
*/
|
|
557
|
-
async _rollbackSavePointAction(savePointName) {
|
|
560
|
+
async _rollbackSavePointAction(savePointName, options = {}) {
|
|
558
561
|
try {
|
|
559
|
-
await this.query(`ROLLBACK TRANSACTION [${savePointName}]
|
|
562
|
+
await this.query(`ROLLBACK TRANSACTION [${savePointName}]`, options)
|
|
560
563
|
} catch (error) {
|
|
561
564
|
const message = error instanceof Error ? error.message : `${error}`
|
|
562
565
|
|
|
@@ -403,9 +403,12 @@ export default class VelociousDatabaseDriversMysql extends Base{
|
|
|
403
403
|
* large result set is read incrementally instead of being buffered. Overrides the base
|
|
404
404
|
* buffered fallback with true server-side streaming.
|
|
405
405
|
* @param {string} sql - SQL string to stream.
|
|
406
|
+
* @param {import("../base.js").QueryOptions} [options] - Query ownership options.
|
|
406
407
|
* @yields {Record<string, unknown>} - The result rows, one at a time.
|
|
407
408
|
*/
|
|
408
|
-
async *queryStream(sql) {
|
|
409
|
+
async *queryStream(sql, options = {}) {
|
|
410
|
+
await this._waitForOperationLease(options.operationOwner)
|
|
411
|
+
|
|
409
412
|
if (!this.pool) await this.connect()
|
|
410
413
|
if (!this.pool) throw new Error("MySQL pool failed to initialize")
|
|
411
414
|
|
|
@@ -554,10 +557,11 @@ export default class VelociousDatabaseDriversMysql extends Base{
|
|
|
554
557
|
|
|
555
558
|
/**
|
|
556
559
|
* Runs last insert id.
|
|
560
|
+
* @param {import("../base.js").QueryOptions} [options] - Query ownership options.
|
|
557
561
|
* @returns {Promise<number>} - Resolves with the last insert id.
|
|
558
562
|
*/
|
|
559
|
-
async lastInsertID() {
|
|
560
|
-
const result = await this.query("SELECT LAST_INSERT_ID() AS last_insert_id")
|
|
563
|
+
async lastInsertID(options = {}) {
|
|
564
|
+
const result = await this.query("SELECT LAST_INSERT_ID() AS last_insert_id", options)
|
|
561
565
|
|
|
562
566
|
return digg(result, 0, "last_insert_id")
|
|
563
567
|
}
|
|
@@ -574,10 +578,11 @@ export default class VelociousDatabaseDriversMysql extends Base{
|
|
|
574
578
|
|
|
575
579
|
/**
|
|
576
580
|
* Runs start transaction action.
|
|
581
|
+
* @param {Pick<import("../base.js").QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
577
582
|
* @returns {Promise<void>} - Resolves when complete.
|
|
578
583
|
*/
|
|
579
|
-
async _startTransactionAction() {
|
|
580
|
-
await this.query("START TRANSACTION")
|
|
584
|
+
async _startTransactionAction(options = {}) {
|
|
585
|
+
await this.query("START TRANSACTION", options)
|
|
581
586
|
}
|
|
582
587
|
|
|
583
588
|
/**
|
|
@@ -326,8 +326,8 @@ export default class VelociousDatabaseDriversPgsql extends Base{
|
|
|
326
326
|
})
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
-
async lastInsertID() {
|
|
330
|
-
const result = await this.query("SELECT LASTVAL() AS last_insert_id")
|
|
329
|
+
async lastInsertID(options = {}) {
|
|
330
|
+
const result = await this.query("SELECT LASTVAL() AS last_insert_id", options)
|
|
331
331
|
|
|
332
332
|
return digg(result, 0, "last_insert_id")
|
|
333
333
|
}
|
|
@@ -338,8 +338,8 @@ export default class VelociousDatabaseDriversPgsql extends Base{
|
|
|
338
338
|
return this._options
|
|
339
339
|
}
|
|
340
340
|
|
|
341
|
-
async _startTransactionAction() {
|
|
342
|
-
await this.query("START TRANSACTION")
|
|
341
|
+
async _startTransactionAction(options = {}) {
|
|
342
|
+
await this.query("START TRANSACTION", options)
|
|
343
343
|
}
|
|
344
344
|
|
|
345
345
|
/**
|
|
@@ -262,8 +262,8 @@ export default class VelociousDatabaseDriversSqliteBase extends Base {
|
|
|
262
262
|
})
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
-
async lastInsertID() {
|
|
266
|
-
const result = await this.query("SELECT LAST_INSERT_ROWID() AS last_insert_id")
|
|
265
|
+
async lastInsertID(options = {}) {
|
|
266
|
+
const result = await this.query("SELECT LAST_INSERT_ROWID() AS last_insert_id", options)
|
|
267
267
|
|
|
268
268
|
return digg(result, 0, "last_insert_id")
|
|
269
269
|
}
|