velocious 1.0.567 → 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 +49 -1
- package/build/configuration.js +36 -0
- package/build/database/drivers/base-table.js +4 -3
- package/build/database/drivers/base.js +195 -54
- package/build/database/drivers/index-metadata.js +28 -0
- package/build/database/drivers/mssql/column.js +2 -34
- package/build/database/drivers/mssql/columns-index.js +37 -0
- package/build/database/drivers/mssql/index.js +10 -7
- package/build/database/drivers/mssql/table.js +55 -11
- package/build/database/drivers/mysql/index.js +10 -5
- package/build/database/drivers/mysql/sql/alter-table.js +13 -0
- package/build/database/drivers/pgsql/column.js +2 -27
- package/build/database/drivers/pgsql/columns-index.js +37 -0
- package/build/database/drivers/pgsql/index.js +4 -4
- package/build/database/drivers/pgsql/table.js +61 -10
- 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/drivers/sqlite/sql/alter-table.js +18 -0
- package/build/database/migration/index.js +92 -3
- 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/alter-table-base.js +20 -1
- 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/normalize-input.js +38 -10
- package/build/database/record/attachments/storage-drivers/filesystem.js +33 -2
- package/build/database/record/attachments/storage-drivers/native.js +17 -2
- package/build/database/record/attachments/storage-drivers/s3.js +27 -7
- package/build/database/record/attachments/store.js +173 -53
- 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/database/table-data/table-foreign-key.js +9 -1
- package/build/environment-handlers/base.js +1 -1
- package/build/environment-handlers/node/attachment-path-source.js +144 -0
- package/build/environment-handlers/node.js +28 -3
- 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-table.d.ts.map +1 -1
- package/build/src/database/drivers/base-table.js +4 -3
- package/build/src/database/drivers/base.d.ts +73 -20
- package/build/src/database/drivers/base.d.ts.map +1 -1
- package/build/src/database/drivers/base.js +181 -54
- package/build/src/database/drivers/index-metadata.d.ts +41 -0
- package/build/src/database/drivers/index-metadata.d.ts.map +1 -0
- package/build/src/database/drivers/index-metadata.js +26 -0
- package/build/src/database/drivers/mssql/column.d.ts.map +1 -1
- package/build/src/database/drivers/mssql/column.js +3 -31
- package/build/src/database/drivers/mssql/columns-index.d.ts +41 -0
- package/build/src/database/drivers/mssql/columns-index.d.ts.map +1 -1
- package/build/src/database/drivers/mssql/columns-index.js +35 -1
- 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/mssql/table.d.ts +42 -0
- package/build/src/database/drivers/mssql/table.d.ts.map +1 -1
- package/build/src/database/drivers/mssql/table.js +49 -12
- 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/mysql/sql/alter-table.d.ts.map +1 -1
- package/build/src/database/drivers/mysql/sql/alter-table.js +12 -1
- package/build/src/database/drivers/pgsql/column.d.ts.map +1 -1
- package/build/src/database/drivers/pgsql/column.js +3 -24
- package/build/src/database/drivers/pgsql/columns-index.d.ts +41 -0
- package/build/src/database/drivers/pgsql/columns-index.d.ts.map +1 -1
- package/build/src/database/drivers/pgsql/columns-index.js +35 -1
- 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/pgsql/table.d.ts +42 -0
- package/build/src/database/drivers/pgsql/table.d.ts.map +1 -1
- package/build/src/database/drivers/pgsql/table.js +54 -11
- 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/drivers/sqlite/sql/alter-table.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/sql/alter-table.js +15 -1
- package/build/src/database/migration/index.d.ts +35 -1
- package/build/src/database/migration/index.d.ts.map +1 -1
- package/build/src/database/migration/index.js +78 -4
- 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/alter-table-base.d.ts +6 -0
- package/build/src/database/query/alter-table-base.d.ts.map +1 -1
- package/build/src/database/query/alter-table-base.js +18 -2
- 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/normalize-input.d.ts +33 -4
- package/build/src/database/record/attachments/normalize-input.d.ts.map +1 -1
- package/build/src/database/record/attachments/normalize-input.js +39 -11
- package/build/src/database/record/attachments/storage-drivers/filesystem.d.ts +2 -5
- package/build/src/database/record/attachments/storage-drivers/filesystem.d.ts.map +1 -1
- package/build/src/database/record/attachments/storage-drivers/filesystem.js +28 -3
- package/build/src/database/record/attachments/storage-drivers/native.d.ts +2 -6
- package/build/src/database/record/attachments/storage-drivers/native.d.ts.map +1 -1
- package/build/src/database/record/attachments/storage-drivers/native.js +14 -3
- package/build/src/database/record/attachments/storage-drivers/s3.d.ts +2 -6
- package/build/src/database/record/attachments/storage-drivers/s3.d.ts.map +1 -1
- package/build/src/database/record/attachments/storage-drivers/s3.js +29 -8
- package/build/src/database/record/attachments/store.d.ts +31 -2
- package/build/src/database/record/attachments/store.d.ts.map +1 -1
- package/build/src/database/record/attachments/store.js +158 -54
- 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/database/table-data/table-foreign-key.d.ts +9 -1
- package/build/src/database/table-data/table-foreign-key.d.ts.map +1 -1
- package/build/src/database/table-data/table-foreign-key.js +9 -2
- package/build/src/environment-handlers/base.d.ts +2 -5
- package/build/src/environment-handlers/base.d.ts.map +1 -1
- package/build/src/environment-handlers/base.js +2 -2
- package/build/src/environment-handlers/node/attachment-path-source.d.ts +64 -0
- package/build/src/environment-handlers/node/attachment-path-source.d.ts.map +1 -0
- package/build/src/environment-handlers/node/attachment-path-source.js +116 -0
- package/build/src/environment-handlers/node.d.ts +12 -0
- package/build/src/environment-handlers/node.d.ts.map +1 -1
- package/build/src/environment-handlers/node.js +24 -4
- 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-table.js +4 -3
- package/src/database/drivers/base.js +195 -54
- package/src/database/drivers/index-metadata.js +28 -0
- package/src/database/drivers/mssql/column.js +2 -34
- package/src/database/drivers/mssql/columns-index.js +37 -0
- package/src/database/drivers/mssql/index.js +10 -7
- package/src/database/drivers/mssql/table.js +55 -11
- package/src/database/drivers/mysql/index.js +10 -5
- package/src/database/drivers/mysql/sql/alter-table.js +13 -0
- package/src/database/drivers/pgsql/column.js +2 -27
- package/src/database/drivers/pgsql/columns-index.js +37 -0
- package/src/database/drivers/pgsql/index.js +4 -4
- package/src/database/drivers/pgsql/table.js +61 -10
- 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/drivers/sqlite/sql/alter-table.js +18 -0
- package/src/database/migration/index.js +92 -3
- 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/alter-table-base.js +20 -1
- 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/normalize-input.js +38 -10
- package/src/database/record/attachments/storage-drivers/filesystem.js +33 -2
- package/src/database/record/attachments/storage-drivers/native.js +17 -2
- package/src/database/record/attachments/storage-drivers/s3.js +27 -7
- package/src/database/record/attachments/store.js +173 -53
- 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/database/table-data/table-foreign-key.js +9 -1
- package/src/environment-handlers/base.js +1 -1
- package/src/environment-handlers/node/attachment-path-source.js +144 -0
- package/src/environment-handlers/node.js +28 -3
- 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,9 +34,11 @@
|
|
|
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))
|
|
41
|
+
* Backend record attachments with filesystem, S3, native callback, and bounded Node path-input persistence (see [docs/attachments.md](docs/attachments.md))
|
|
40
42
|
|
|
41
43
|
# Setup
|
|
42
44
|
|
|
@@ -50,6 +52,25 @@ npx velocious init
|
|
|
50
52
|
|
|
51
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()`.
|
|
52
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
|
+
|
|
53
74
|
# Development
|
|
54
75
|
|
|
55
76
|
When working on Velocious itself, npm scripts are cross-platform (Windows `cmd`/PowerShell and POSIX shells):
|
|
@@ -521,6 +542,9 @@ Task.hasOneAttachment("descriptionFile")
|
|
|
521
542
|
Task.hasOneAttachment("archivedPdf", {driver: "s3"})
|
|
522
543
|
```
|
|
523
544
|
|
|
545
|
+
See [Backend record attachments](docs/attachments.md) for the complete input,
|
|
546
|
+
storage-driver, lifecycle, and path-security contracts.
|
|
547
|
+
|
|
524
548
|
You can also pass a driver class or instance directly on the attachment:
|
|
525
549
|
|
|
526
550
|
```js
|
|
@@ -538,6 +562,10 @@ await task.descriptionFile().attach({
|
|
|
538
562
|
content: "my file content",
|
|
539
563
|
filename: "file.doc"
|
|
540
564
|
})
|
|
565
|
+
await task.archivedPdf().attach({
|
|
566
|
+
path: "/var/app/uploads/archive.pdf",
|
|
567
|
+
contentType: "application/pdf"
|
|
568
|
+
})
|
|
541
569
|
const descriptionFileUrl = await task.descriptionFile().url()
|
|
542
570
|
await task.update({
|
|
543
571
|
descriptionFile: {
|
|
@@ -605,7 +633,25 @@ new Configuration({
|
|
|
605
633
|
```
|
|
606
634
|
|
|
607
635
|
Then `{path: "..."}`
|
|
608
|
-
inputs are only accepted when the
|
|
636
|
+
inputs are only accepted when the path resolves inside one of the allowed
|
|
637
|
+
prefixes and the once-opened handle identifies a regular file. Its exact byte
|
|
638
|
+
size comes from that handle's stat snapshot. The filesystem driver copies it
|
|
639
|
+
with a bounded, backpressured stream and the S3 driver sends a Node `Readable`;
|
|
640
|
+
on current nullable schemas neither driver first materializes the whole file as
|
|
641
|
+
a Buffer or Base64 value. Legacy schemas with a non-null `content_base64`
|
|
642
|
+
column instead materialize the opened snapshot once before driver persistence
|
|
643
|
+
and reuse those exact bytes for storage and the database Base64. Path
|
|
644
|
+
replacement cannot switch the opened source, truncation is rejected, later
|
|
645
|
+
appends are ignored, and the source is closed after persistence.
|
|
646
|
+
|
|
647
|
+
The native driver's documented `write({contentBase64, ...})` callback remains
|
|
648
|
+
source-compatible. For path input only, that driver reads and Base64-encodes the
|
|
649
|
+
opened source after driver selection on current schemas; legacy path input
|
|
650
|
+
arrives pre-materialized with the same Base64 written to the database. Existing
|
|
651
|
+
Buffer, string, browser, and `UploadedFile` inputs keep their in-memory
|
|
652
|
+
behavior. See
|
|
653
|
+
[docs/attachments.md](docs/attachments.md#normalized-storage-driver-input) for
|
|
654
|
+
the normalized input passed to custom drivers.
|
|
609
655
|
|
|
610
656
|
For frontend models, configure `resourceConfig().attachments` and use:
|
|
611
657
|
|
|
@@ -1148,6 +1194,8 @@ export default class CreateEvents extends Migration {
|
|
|
1148
1194
|
}
|
|
1149
1195
|
```
|
|
1150
1196
|
|
|
1197
|
+
To reverse an `addReference("tasks", "project", {foreignKey: true, type: "uuid"})` migration, use `await this.removeReference("tasks", "project")` in `down()`. It removes the generated foreign key, index, and column; see [removing references and foreign keys](docs/database-migrations.md#removing-references-and-foreign-keys) for custom-column and foreign-key-only cases.
|
|
1198
|
+
|
|
1151
1199
|
Migrations that must be rerunnable can guard changes with `tableExists(...)`, `columnExists(table, column)` and `indexExists(table, index)` — a missing table yields `false` rather than throwing. See [docs/database-migrations.md](docs/database-migrations.md#guarding-schema-changes-in-rerunnable-migrations).
|
|
1152
1200
|
|
|
1153
1201
|
## Run migrations from the command line
|
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
|
|
@@ -104,13 +104,15 @@ export default class VelociousDatabaseDriversBaseTable {
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
for (const foreignKey of await this.getForeignKeys()) {
|
|
107
|
-
|
|
107
|
+
const tableDataForeignKey = foreignKey.getTableDataForeignKey()
|
|
108
|
+
|
|
109
|
+
tableData.addForeignKey(tableDataForeignKey)
|
|
108
110
|
|
|
109
111
|
const tableDataColumn = tableDataColumns.find((tableDataColumn) => tableDataColumn.getName() == foreignKey.getColumnName())
|
|
110
112
|
|
|
111
113
|
if (!tableDataColumn) throw new Error(`Couldn't find table data column for foreign key: ${foreignKey.getColumnName()}`)
|
|
112
114
|
|
|
113
|
-
tableDataColumn.setForeignKey(
|
|
115
|
+
tableDataColumn.setForeignKey(tableDataForeignKey)
|
|
114
116
|
}
|
|
115
117
|
|
|
116
118
|
for (const index of await this.getIndexes()) {
|
|
@@ -153,4 +155,3 @@ export default class VelociousDatabaseDriversBaseTable {
|
|
|
153
155
|
return await this.getDriver().query(sql)
|
|
154
156
|
}
|
|
155
157
|
}
|
|
156
|
-
|
|
@@ -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.
|
|
@@ -224,6 +245,34 @@ export default class VelociousDatabaseDriversBase {
|
|
|
224
245
|
}
|
|
225
246
|
}
|
|
226
247
|
|
|
248
|
+
/**
|
|
249
|
+
* Runs remove foreign key.
|
|
250
|
+
* @param {string} tableName - Table name.
|
|
251
|
+
* @param {import("./base-foreign-key.js").default} foreignKeyMetadata - Foreign key metadata.
|
|
252
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
253
|
+
*/
|
|
254
|
+
async removeForeignKey(tableName, foreignKeyMetadata) {
|
|
255
|
+
this._assertNotReadOnly()
|
|
256
|
+
|
|
257
|
+
const tableForeignKey = new TableForeignKey({
|
|
258
|
+
columnName: foreignKeyMetadata.getColumnName(),
|
|
259
|
+
dropForeignKey: true,
|
|
260
|
+
name: foreignKeyMetadata.getName(),
|
|
261
|
+
referencedColumnName: foreignKeyMetadata.getReferencedColumnName(),
|
|
262
|
+
referencedTableName: foreignKeyMetadata.getReferencedTableName(),
|
|
263
|
+
tableName
|
|
264
|
+
})
|
|
265
|
+
const tableData = new TableData(tableName)
|
|
266
|
+
|
|
267
|
+
tableData.addForeignKey(tableForeignKey)
|
|
268
|
+
|
|
269
|
+
const alterTableSQLs = await this.alterTableSQLs(tableData)
|
|
270
|
+
|
|
271
|
+
for (const alterTableSQL of alterTableSQLs) {
|
|
272
|
+
await this.query(alterTableSQL)
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
227
276
|
/**
|
|
228
277
|
* Runs alter table sqls.
|
|
229
278
|
* @abstract
|
|
@@ -460,6 +509,46 @@ export default class VelociousDatabaseDriversBase {
|
|
|
460
509
|
return this.configuration
|
|
461
510
|
}
|
|
462
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
|
+
|
|
463
552
|
/**
|
|
464
553
|
* Runs get id seq.
|
|
465
554
|
* @returns {number | undefined} - The id seq.
|
|
@@ -711,9 +800,10 @@ export default class VelociousDatabaseDriversBase {
|
|
|
711
800
|
/**
|
|
712
801
|
* Runs last insert id.
|
|
713
802
|
* @abstract
|
|
803
|
+
* @param {QueryOptions} [_options] - Query ownership options.
|
|
714
804
|
* @returns {Promise<number>} - Resolves with the last insert id.
|
|
715
805
|
*/
|
|
716
|
-
lastInsertID() {
|
|
806
|
+
lastInsertID(_options = {}) {
|
|
717
807
|
throw new Error(`${this.constructor.name}#lastInsertID not implemented`)
|
|
718
808
|
}
|
|
719
809
|
|
|
@@ -904,12 +994,16 @@ export default class VelociousDatabaseDriversBase {
|
|
|
904
994
|
* The outermost transaction retries the whole callback on a deadlock / lock-wait-timeout,
|
|
905
995
|
* because such errors roll the entire transaction back and the standard recovery is to
|
|
906
996
|
* restart it. Nested savepoints let the deadlock bubble up to this outer retry.
|
|
907
|
-
* @
|
|
908
|
-
* @
|
|
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.
|
|
909
1001
|
*/
|
|
910
|
-
async transaction(callback) {
|
|
1002
|
+
async transaction(callback, options = {}) {
|
|
1003
|
+
await this._waitForOperationLease(options.operationOwner)
|
|
1004
|
+
|
|
911
1005
|
if (this._transactionsCount > 0) {
|
|
912
|
-
return await this._runTransactionAttempt(callback)
|
|
1006
|
+
return await this._runTransactionAttempt(callback, options)
|
|
913
1007
|
}
|
|
914
1008
|
|
|
915
1009
|
const args = this.getArgs()
|
|
@@ -922,8 +1016,10 @@ export default class VelociousDatabaseDriversBase {
|
|
|
922
1016
|
attempt++
|
|
923
1017
|
|
|
924
1018
|
try {
|
|
925
|
-
return await this._runTransactionAttempt(callback)
|
|
1019
|
+
return await this._runTransactionAttempt(callback, options)
|
|
926
1020
|
} catch (error) {
|
|
1021
|
+
if (error instanceof VelociousDatabaseAfterCommitCallbackError) throw error.callbackError
|
|
1022
|
+
|
|
927
1023
|
const retryInfo = error instanceof Error ? this.retryableDatabaseError(error) : {retry: false, reconnect: false}
|
|
928
1024
|
|
|
929
1025
|
if (retryInfo.deadlock && attempt < maxAttempts && this._transactionsCount == 0) {
|
|
@@ -965,10 +1061,12 @@ export default class VelociousDatabaseDriversBase {
|
|
|
965
1061
|
* Runs a single transaction attempt: starts a transaction (or a savepoint when nested), runs
|
|
966
1062
|
* `callback`, and commits — rolling back on error. {@link transaction} wraps this with deadlock
|
|
967
1063
|
* retry at the outermost level.
|
|
968
|
-
* @
|
|
1064
|
+
* @template T
|
|
1065
|
+
* @param {() => Promise<T>} callback - Callback function.
|
|
1066
|
+
* @param {Pick<QueryOptions, "operationOwner">} options - Transaction ownership.
|
|
969
1067
|
* @returns {Promise<?>} - Resolves with the transaction result.
|
|
970
1068
|
*/
|
|
971
|
-
async _runTransactionAttempt(callback) {
|
|
1069
|
+
async _runTransactionAttempt(callback, options) {
|
|
972
1070
|
const savePointName = this.generateSavePointName()
|
|
973
1071
|
/**
|
|
974
1072
|
* Callback frame.
|
|
@@ -979,14 +1077,19 @@ export default class VelociousDatabaseDriversBase {
|
|
|
979
1077
|
|
|
980
1078
|
this._afterCommitCallbackFrames.push(callbackFrame)
|
|
981
1079
|
|
|
982
|
-
|
|
983
|
-
this.
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
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
|
|
990
1093
|
}
|
|
991
1094
|
|
|
992
1095
|
let result
|
|
@@ -996,15 +1099,13 @@ export default class VelociousDatabaseDriversBase {
|
|
|
996
1099
|
|
|
997
1100
|
if (savePointStarted) {
|
|
998
1101
|
this.logger.debug("Release savepoint", savePointName)
|
|
999
|
-
await this.releaseSavePoint(savePointName)
|
|
1102
|
+
await this.releaseSavePoint(savePointName, options)
|
|
1000
1103
|
}
|
|
1001
1104
|
|
|
1002
1105
|
if (transactionStarted) {
|
|
1003
1106
|
this.logger.debug("Commit transaction")
|
|
1004
|
-
await this.commitTransaction()
|
|
1107
|
+
await this.commitTransaction(options)
|
|
1005
1108
|
}
|
|
1006
|
-
|
|
1007
|
-
await this._commitAfterCommitCallbackFrame()
|
|
1008
1109
|
} catch (error) {
|
|
1009
1110
|
if (error instanceof Error) {
|
|
1010
1111
|
this.logger.debug("Transaction error", error.message)
|
|
@@ -1017,14 +1118,14 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1017
1118
|
if (savePointStarted) {
|
|
1018
1119
|
this.logger.debug("Rollback savepoint", savePointName)
|
|
1019
1120
|
try {
|
|
1020
|
-
await this.rollbackSavePoint(savePointName)
|
|
1121
|
+
await this.rollbackSavePoint(savePointName, options)
|
|
1021
1122
|
} catch (savePointError) {
|
|
1022
1123
|
const message = savePointError instanceof Error ? savePointError.message : `${savePointError}`
|
|
1023
1124
|
|
|
1024
1125
|
// MySQL sometimes drops savepoints unexpectedly; fall back to rolling back the full transaction
|
|
1025
1126
|
if (message.includes("SAVEPOINT") || message.includes("ER_SP_DOES_NOT_EXIST")) {
|
|
1026
1127
|
this.logger.debug("Savepoint rollback failed; rolling back entire transaction instead")
|
|
1027
|
-
await this.rollbackTransaction()
|
|
1128
|
+
await this.rollbackTransaction(options)
|
|
1028
1129
|
transactionRolledBack = true
|
|
1029
1130
|
} else {
|
|
1030
1131
|
throw savePointError
|
|
@@ -1038,7 +1139,7 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1038
1139
|
// `_transactionsCount` below zero, which would then defeat the outermost deadlock-retry guard.
|
|
1039
1140
|
if (transactionStarted && !transactionRolledBack && this._transactionsCount > 0) {
|
|
1040
1141
|
this.logger.debug("Rollback transaction")
|
|
1041
|
-
await this.rollbackTransaction()
|
|
1142
|
+
await this.rollbackTransaction(options)
|
|
1042
1143
|
}
|
|
1043
1144
|
|
|
1044
1145
|
this._afterCommitCallbackFrames.pop()
|
|
@@ -1046,6 +1147,12 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1046
1147
|
throw error
|
|
1047
1148
|
}
|
|
1048
1149
|
|
|
1150
|
+
try {
|
|
1151
|
+
await this._commitAfterCommitCallbackFrame()
|
|
1152
|
+
} catch (error) {
|
|
1153
|
+
throw new VelociousDatabaseAfterCommitCallbackError(error)
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1049
1156
|
return result
|
|
1050
1157
|
}
|
|
1051
1158
|
|
|
@@ -1053,9 +1160,12 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1053
1160
|
* Runs a callback after the surrounding transaction commits.
|
|
1054
1161
|
* If no transaction is active, the callback runs immediately.
|
|
1055
1162
|
* @param {() => void | Promise<void>} callback - Callback.
|
|
1163
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Callback ownership.
|
|
1056
1164
|
* @returns {Promise<void>} - Resolves when the callback has been registered or run.
|
|
1057
1165
|
*/
|
|
1058
|
-
async afterCommit(callback) {
|
|
1166
|
+
async afterCommit(callback, options = {}) {
|
|
1167
|
+
await this._waitForOperationLease(options.operationOwner)
|
|
1168
|
+
|
|
1059
1169
|
const currentFrame = this._afterCommitCallbackFrames[this._afterCommitCallbackFrames.length - 1]
|
|
1060
1170
|
|
|
1061
1171
|
if (!currentFrame) {
|
|
@@ -1074,40 +1184,60 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1074
1184
|
|
|
1075
1185
|
/**
|
|
1076
1186
|
* Runs start transaction.
|
|
1187
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1077
1188
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1078
1189
|
*/
|
|
1079
|
-
async startTransaction() {
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
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
|
+
}
|
|
1084
1211
|
}
|
|
1085
1212
|
|
|
1086
1213
|
/**
|
|
1087
1214
|
* Runs start transaction action.
|
|
1215
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1088
1216
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1089
1217
|
*/
|
|
1090
|
-
async _startTransactionAction() {
|
|
1091
|
-
await this.query("BEGIN TRANSACTION")
|
|
1218
|
+
async _startTransactionAction(options = {}) {
|
|
1219
|
+
await this.query("BEGIN TRANSACTION", options)
|
|
1092
1220
|
}
|
|
1093
1221
|
|
|
1094
1222
|
/**
|
|
1095
1223
|
* Runs commit transaction.
|
|
1224
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1096
1225
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1097
1226
|
*/
|
|
1098
|
-
async commitTransaction() {
|
|
1227
|
+
async commitTransaction(options = {}) {
|
|
1099
1228
|
await this._transactionsActionsMutex.sync(async () => {
|
|
1100
|
-
await this._commitTransactionAction()
|
|
1229
|
+
await this._commitTransactionAction(options)
|
|
1101
1230
|
this._transactionsCount--
|
|
1102
1231
|
})
|
|
1103
1232
|
}
|
|
1104
1233
|
|
|
1105
1234
|
/**
|
|
1106
1235
|
* Runs commit transaction action.
|
|
1236
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1107
1237
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1108
1238
|
*/
|
|
1109
|
-
async _commitTransactionAction() {
|
|
1110
|
-
await this.query("COMMIT")
|
|
1239
|
+
async _commitTransactionAction(options = {}) {
|
|
1240
|
+
await this.query("COMMIT", options)
|
|
1111
1241
|
}
|
|
1112
1242
|
|
|
1113
1243
|
/**
|
|
@@ -1155,6 +1285,7 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1155
1285
|
* @returns {Promise<QueryResultType>} - Resolves with the query.
|
|
1156
1286
|
*/
|
|
1157
1287
|
async query(sql, options = {}) {
|
|
1288
|
+
await this._waitForOperationLease(options.operationOwner)
|
|
1158
1289
|
this._assertWritableQuery(sql)
|
|
1159
1290
|
|
|
1160
1291
|
let tries = 0
|
|
@@ -1204,16 +1335,18 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1204
1335
|
/**
|
|
1205
1336
|
* Executes a mutation and returns the number of rows changed by that statement.
|
|
1206
1337
|
* @param {string} sql - Mutation SQL string.
|
|
1338
|
+
* @param {QueryOptions} [options] - Query ownership options.
|
|
1207
1339
|
* @returns {Promise<number>} - Affected row count.
|
|
1208
1340
|
*/
|
|
1209
|
-
async affectedRows(sql) {
|
|
1341
|
+
async affectedRows(sql, options = {}) {
|
|
1342
|
+
await this._waitForOperationLease(options.operationOwner)
|
|
1210
1343
|
this._assertWritableQuery(sql)
|
|
1211
|
-
await this.beforeQuery(sql,
|
|
1344
|
+
await this.beforeQuery(sql, options)
|
|
1212
1345
|
|
|
1213
1346
|
try {
|
|
1214
1347
|
return await this._affectedRowsActual(sql)
|
|
1215
1348
|
} finally {
|
|
1216
|
-
await this.afterQuery(sql,
|
|
1349
|
+
await this.afterQuery(sql, options)
|
|
1217
1350
|
}
|
|
1218
1351
|
}
|
|
1219
1352
|
|
|
@@ -1581,12 +1714,13 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1581
1714
|
|
|
1582
1715
|
/**
|
|
1583
1716
|
* Runs rollback transaction.
|
|
1717
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1584
1718
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1585
1719
|
*/
|
|
1586
|
-
async rollbackTransaction() {
|
|
1720
|
+
async rollbackTransaction(options = {}) {
|
|
1587
1721
|
await this._transactionsActionsMutex.sync(async () => {
|
|
1588
1722
|
try {
|
|
1589
|
-
await this._rollbackTransactionAction()
|
|
1723
|
+
await this._rollbackTransactionAction(options)
|
|
1590
1724
|
} finally {
|
|
1591
1725
|
this._transactionsCount--
|
|
1592
1726
|
|
|
@@ -1602,10 +1736,11 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1602
1736
|
|
|
1603
1737
|
/**
|
|
1604
1738
|
* Runs rollback transaction action.
|
|
1739
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1605
1740
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1606
1741
|
*/
|
|
1607
|
-
async _rollbackTransactionAction() {
|
|
1608
|
-
await this.query("ROLLBACK")
|
|
1742
|
+
async _rollbackTransactionAction(options = {}) {
|
|
1743
|
+
await this.query("ROLLBACK", options)
|
|
1609
1744
|
}
|
|
1610
1745
|
|
|
1611
1746
|
/**
|
|
@@ -1619,21 +1754,23 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1619
1754
|
/**
|
|
1620
1755
|
* Runs start save point.
|
|
1621
1756
|
* @param {string} savePointName - Save point name.
|
|
1757
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1622
1758
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1623
1759
|
*/
|
|
1624
|
-
async startSavePoint(savePointName) {
|
|
1760
|
+
async startSavePoint(savePointName, options = {}) {
|
|
1625
1761
|
await this._transactionsActionsMutex.sync(async () => {
|
|
1626
|
-
await this._startSavePointAction(savePointName)
|
|
1762
|
+
await this._startSavePointAction(savePointName, options)
|
|
1627
1763
|
})
|
|
1628
1764
|
}
|
|
1629
1765
|
|
|
1630
1766
|
/**
|
|
1631
1767
|
* Runs start save point action.
|
|
1632
1768
|
* @param {string} savePointName - Save point name.
|
|
1769
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1633
1770
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1634
1771
|
*/
|
|
1635
|
-
async _startSavePointAction(savePointName) {
|
|
1636
|
-
await this.query(`SAVEPOINT ${savePointName}
|
|
1772
|
+
async _startSavePointAction(savePointName, options = {}) {
|
|
1773
|
+
await this.query(`SAVEPOINT ${savePointName}`, options)
|
|
1637
1774
|
}
|
|
1638
1775
|
|
|
1639
1776
|
/**
|
|
@@ -1663,22 +1800,24 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1663
1800
|
/**
|
|
1664
1801
|
* Runs release save point.
|
|
1665
1802
|
* @param {string} savePointName - Save point name.
|
|
1803
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1666
1804
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1667
1805
|
*/
|
|
1668
|
-
async releaseSavePoint(savePointName) {
|
|
1806
|
+
async releaseSavePoint(savePointName, options = {}) {
|
|
1669
1807
|
await this._transactionsActionsMutex.sync(async () => {
|
|
1670
|
-
await this._releaseSavePointAction(savePointName)
|
|
1808
|
+
await this._releaseSavePointAction(savePointName, options)
|
|
1671
1809
|
})
|
|
1672
1810
|
}
|
|
1673
1811
|
|
|
1674
1812
|
/**
|
|
1675
1813
|
* Runs release save point action.
|
|
1676
1814
|
* @param {string} savePointName - Save point name.
|
|
1815
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1677
1816
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1678
1817
|
*/
|
|
1679
|
-
async _releaseSavePointAction(savePointName) {
|
|
1818
|
+
async _releaseSavePointAction(savePointName, options = {}) {
|
|
1680
1819
|
try {
|
|
1681
|
-
await this.query(`RELEASE SAVEPOINT ${savePointName}
|
|
1820
|
+
await this.query(`RELEASE SAVEPOINT ${savePointName}`, options)
|
|
1682
1821
|
} catch (error) {
|
|
1683
1822
|
const message = error instanceof Error ? error.message : `${error}`
|
|
1684
1823
|
|
|
@@ -1695,21 +1834,23 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1695
1834
|
/**
|
|
1696
1835
|
* Runs rollback save point.
|
|
1697
1836
|
* @param {string} savePointName - Save point name.
|
|
1837
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1698
1838
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1699
1839
|
*/
|
|
1700
|
-
async rollbackSavePoint(savePointName) {
|
|
1840
|
+
async rollbackSavePoint(savePointName, options = {}) {
|
|
1701
1841
|
await this._transactionsActionsMutex.sync(async () => {
|
|
1702
|
-
await this._rollbackSavePointAction(savePointName)
|
|
1842
|
+
await this._rollbackSavePointAction(savePointName, options)
|
|
1703
1843
|
})
|
|
1704
1844
|
}
|
|
1705
1845
|
|
|
1706
1846
|
/**
|
|
1707
1847
|
* Runs rollback save point action.
|
|
1708
1848
|
* @param {string} savePointName - Save point name.
|
|
1849
|
+
* @param {Pick<QueryOptions, "operationOwner">} [options] - Transaction ownership.
|
|
1709
1850
|
* @returns {Promise<void>} - Resolves when complete.
|
|
1710
1851
|
*/
|
|
1711
|
-
async _rollbackSavePointAction(savePointName) {
|
|
1712
|
-
await this.query(`ROLLBACK TO SAVEPOINT ${savePointName}
|
|
1852
|
+
async _rollbackSavePointAction(savePointName, options = {}) {
|
|
1853
|
+
await this.query(`ROLLBACK TO SAVEPOINT ${savePointName}`, options)
|
|
1713
1854
|
}
|
|
1714
1855
|
|
|
1715
1856
|
/**
|