velocious 1.0.430 → 1.0.432
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/bin/velocious.js +48 -0
- package/build/application.js +229 -0
- package/build/authorization/ability.js +329 -0
- package/build/authorization/base-resource.js +143 -0
- package/build/background-jobs/client.js +50 -0
- package/build/background-jobs/cron-expression.js +277 -0
- package/build/background-jobs/forked-runner-child.js +86 -0
- package/build/background-jobs/job-record.js +13 -0
- package/build/background-jobs/job-registry.js +92 -0
- package/build/background-jobs/job-runner.js +107 -0
- package/build/background-jobs/job.js +77 -0
- package/build/background-jobs/json-socket.js +78 -0
- package/build/background-jobs/main.js +926 -0
- package/build/background-jobs/normalize-error.js +26 -0
- package/build/background-jobs/scheduler.js +274 -0
- package/build/background-jobs/socket-request.js +68 -0
- package/build/background-jobs/status-reporter.js +101 -0
- package/build/background-jobs/store.js +994 -0
- package/build/background-jobs/types.js +70 -0
- package/build/background-jobs/web/authorization.js +89 -0
- package/build/background-jobs/web/controller.js +280 -0
- package/build/background-jobs/web/index.js +57 -0
- package/build/background-jobs/web/path-matcher.js +74 -0
- package/build/background-jobs/web/registry.js +49 -0
- package/build/background-jobs/worker.js +683 -0
- package/build/beacon/client.js +330 -0
- package/build/beacon/in-process-broker.js +71 -0
- package/build/beacon/in-process-client.js +139 -0
- package/build/beacon/server.js +148 -0
- package/build/beacon/types.js +55 -0
- package/build/bin/velocious.js +39 -34
- package/build/cli/base-command.js +67 -0
- package/build/cli/browser-cli.js +45 -0
- package/build/cli/commands/background-jobs-main.js +7 -0
- package/build/cli/commands/background-jobs-runner.js +7 -0
- package/build/cli/commands/background-jobs-worker.js +7 -0
- package/build/cli/commands/beacon.js +7 -0
- package/build/cli/commands/console.js +12 -0
- package/build/cli/commands/db/base-command.js +82 -0
- package/build/cli/commands/db/create.js +64 -0
- package/build/cli/commands/db/drop.js +75 -0
- package/build/cli/commands/db/migrate.js +17 -0
- package/build/cli/commands/db/reset.js +22 -0
- package/build/cli/commands/db/rollback.js +15 -0
- package/build/cli/commands/db/schema/dump.js +12 -0
- package/build/cli/commands/db/schema/load.js +12 -0
- package/build/cli/commands/db/seed.js +12 -0
- package/build/cli/commands/db/tenants/check.js +38 -0
- package/build/cli/commands/db/tenants/create.js +33 -0
- package/build/cli/commands/db/tenants/migrate.js +49 -0
- package/build/cli/commands/destroy/migration.js +7 -0
- package/build/cli/commands/generate/base-models.js +7 -0
- package/build/cli/commands/generate/frontend-models.js +12 -0
- package/build/cli/commands/generate/migration.js +7 -0
- package/build/cli/commands/generate/model.js +7 -0
- package/build/cli/commands/init.js +11 -0
- package/build/cli/commands/routes.js +7 -0
- package/build/cli/commands/run-script.js +12 -0
- package/build/cli/commands/runner.js +12 -0
- package/build/cli/commands/server.js +7 -0
- package/build/cli/commands/test.js +9 -0
- package/build/cli/index.js +152 -0
- package/build/cli/tenant-database-command-helper.js +198 -0
- package/build/cli/use-browser-cli.js +30 -0
- package/build/configuration-resolver.js +65 -0
- package/build/configuration-types.js +429 -0
- package/build/configuration.js +2590 -0
- package/build/controller.js +421 -0
- package/build/current-configuration.js +31 -0
- package/build/current.js +80 -0
- package/build/database/annotations-async-hooks.js +47 -0
- package/build/database/annotations.js +40 -0
- package/build/database/drivers/base-column.js +182 -0
- package/build/database/drivers/base-columns-index.js +81 -0
- package/build/database/drivers/base-foreign-key.js +104 -0
- package/build/database/drivers/base-table.js +156 -0
- package/build/database/drivers/base.js +1609 -0
- package/build/database/drivers/mssql/column.js +74 -0
- package/build/database/drivers/mssql/columns-index.js +6 -0
- package/build/database/drivers/mssql/connect-connection.js +16 -0
- package/build/database/drivers/mssql/foreign-key.js +12 -0
- package/build/database/drivers/mssql/index.js +590 -0
- package/build/database/drivers/mssql/options.js +79 -0
- package/build/database/drivers/mssql/query-parser.js +6 -0
- package/build/database/drivers/mssql/sql/alter-table.js +4 -0
- package/build/database/drivers/mssql/sql/create-database.js +36 -0
- package/build/database/drivers/mssql/sql/create-index.js +4 -0
- package/build/database/drivers/mssql/sql/create-table.js +4 -0
- package/build/database/drivers/mssql/sql/delete.js +19 -0
- package/build/database/drivers/mssql/sql/drop-database.js +36 -0
- package/build/database/drivers/mssql/sql/drop-table.js +4 -0
- package/build/database/drivers/mssql/sql/insert.js +4 -0
- package/build/database/drivers/mssql/sql/update.js +31 -0
- package/build/database/drivers/mssql/sql/upsert.js +23 -0
- package/build/database/drivers/mssql/structure-sql.js +120 -0
- package/build/database/drivers/mssql/table.js +145 -0
- package/build/database/drivers/mysql/column.js +112 -0
- package/build/database/drivers/mysql/columns-index.js +22 -0
- package/build/database/drivers/mysql/foreign-key.js +12 -0
- package/build/database/drivers/mysql/index.js +473 -0
- package/build/database/drivers/mysql/options.js +34 -0
- package/build/database/drivers/mysql/query-parser.js +6 -0
- package/build/database/drivers/mysql/query.js +37 -0
- package/build/database/drivers/mysql/sql/alter-table.js +6 -0
- package/build/database/drivers/mysql/sql/create-database.js +39 -0
- package/build/database/drivers/mysql/sql/create-index.js +6 -0
- package/build/database/drivers/mysql/sql/create-table.js +6 -0
- package/build/database/drivers/mysql/sql/delete.js +21 -0
- package/build/database/drivers/mysql/sql/drop-database.js +6 -0
- package/build/database/drivers/mysql/sql/drop-table.js +6 -0
- package/build/database/drivers/mysql/sql/insert.js +6 -0
- package/build/database/drivers/mysql/sql/update.js +33 -0
- package/build/database/drivers/mysql/sql/upsert.js +13 -0
- package/build/database/drivers/mysql/structure-sql.js +93 -0
- package/build/database/drivers/mysql/table.js +121 -0
- package/build/database/drivers/pgsql/column.js +90 -0
- package/build/database/drivers/pgsql/columns-index.js +6 -0
- package/build/database/drivers/pgsql/foreign-key.js +12 -0
- package/build/database/drivers/pgsql/index.js +441 -0
- package/build/database/drivers/pgsql/options.js +32 -0
- package/build/database/drivers/pgsql/query-parser.js +6 -0
- package/build/database/drivers/pgsql/sql/alter-table.js +6 -0
- package/build/database/drivers/pgsql/sql/create-database.js +38 -0
- package/build/database/drivers/pgsql/sql/create-index.js +6 -0
- package/build/database/drivers/pgsql/sql/create-table.js +6 -0
- package/build/database/drivers/pgsql/sql/delete.js +21 -0
- package/build/database/drivers/pgsql/sql/drop-database.js +6 -0
- package/build/database/drivers/pgsql/sql/drop-table.js +6 -0
- package/build/database/drivers/pgsql/sql/insert.js +6 -0
- package/build/database/drivers/pgsql/sql/update.js +33 -0
- package/build/database/drivers/pgsql/sql/upsert.js +14 -0
- package/build/database/drivers/pgsql/structure-sql.js +126 -0
- package/build/database/drivers/pgsql/table.js +135 -0
- package/build/database/drivers/sqlite/base.js +509 -0
- package/build/database/drivers/sqlite/column.js +75 -0
- package/build/database/drivers/sqlite/columns-index.js +30 -0
- package/build/database/drivers/sqlite/connection-sql-js.js +46 -0
- package/build/database/drivers/sqlite/foreign-key.js +24 -0
- package/build/database/drivers/sqlite/index.js +394 -0
- package/build/database/drivers/sqlite/index.native.js +72 -0
- package/build/database/drivers/sqlite/index.web.js +99 -0
- package/build/database/drivers/sqlite/options.js +32 -0
- package/build/database/drivers/sqlite/query-parser.js +6 -0
- package/build/database/drivers/sqlite/query.js +35 -0
- package/build/database/drivers/sqlite/query.native.js +35 -0
- package/build/database/drivers/sqlite/query.web.js +49 -0
- package/build/database/drivers/sqlite/sql/alter-table.js +187 -0
- package/build/database/drivers/sqlite/sql/create-index.js +6 -0
- package/build/database/drivers/sqlite/sql/create-table.js +6 -0
- package/build/database/drivers/sqlite/sql/delete.js +26 -0
- package/build/database/drivers/sqlite/sql/drop-table.js +6 -0
- package/build/database/drivers/sqlite/sql/insert.js +6 -0
- package/build/database/drivers/sqlite/sql/update.js +33 -0
- package/build/database/drivers/sqlite/sql/upsert.js +14 -0
- package/build/database/drivers/sqlite/structure-sql.js +56 -0
- package/build/database/drivers/sqlite/table-rebuilder.js +96 -0
- package/build/database/drivers/sqlite/table.js +131 -0
- package/build/database/drivers/structure-sql/utils.js +35 -0
- package/build/database/handler.js +13 -0
- package/build/database/initializer-from-require-context.js +101 -0
- package/build/database/migration/index.js +438 -0
- package/build/database/migrator/files-finder.js +55 -0
- package/build/database/migrator/types.js +31 -0
- package/build/database/migrator.js +557 -0
- package/build/database/pool/async-tracked-multi-connection.js +1164 -0
- package/build/database/pool/base-methods-forward.js +52 -0
- package/build/database/pool/base.js +380 -0
- package/build/database/pool/single-multi-use.js +118 -0
- package/build/database/query/alter-table-base.js +104 -0
- package/build/database/query/base.js +49 -0
- package/build/database/query/create-database-base.js +42 -0
- package/build/database/query/create-index-base.js +117 -0
- package/build/database/query/create-table-base.js +205 -0
- package/build/database/query/delete-base.js +19 -0
- package/build/database/query/drop-database-base.js +38 -0
- package/build/database/query/drop-table-base.js +58 -0
- package/build/database/query/from-base.js +36 -0
- package/build/database/query/from-plain.js +16 -0
- package/build/database/query/from-table.js +18 -0
- package/build/database/query/index.js +533 -0
- package/build/database/query/insert-base.js +172 -0
- package/build/database/query/join-base.js +43 -0
- package/build/database/query/join-object.js +167 -0
- package/build/database/query/join-plain.js +18 -0
- package/build/database/query/join-tracker.js +93 -0
- package/build/database/query/model-class-query.js +1577 -0
- package/build/database/query/order-base.js +33 -0
- package/build/database/query/order-column.js +77 -0
- package/build/database/query/order-plain.js +28 -0
- package/build/database/query/preloader/belongs-to.js +267 -0
- package/build/database/query/preloader/ensure-model-class-initialized.js +18 -0
- package/build/database/query/preloader/has-many.js +316 -0
- package/build/database/query/preloader/has-one.js +123 -0
- package/build/database/query/preloader/selection.js +152 -0
- package/build/database/query/preloader.js +201 -0
- package/build/database/query/query-data.js +305 -0
- package/build/database/query/select-base.js +30 -0
- package/build/database/query/select-plain.js +18 -0
- package/build/database/query/select-table-and-column.js +28 -0
- package/build/database/query/update-base.js +41 -0
- package/build/database/query/upsert-base.js +103 -0
- package/build/database/query/where-base.js +38 -0
- package/build/database/query/where-combinator.js +31 -0
- package/build/database/query/where-hash.js +77 -0
- package/build/database/query/where-model-class-hash.js +505 -0
- package/build/database/query/where-not.js +23 -0
- package/build/database/query/where-plain.js +20 -0
- package/build/database/query/with-count.js +219 -0
- package/build/database/query-parser/base-query-parser.js +40 -0
- package/build/database/query-parser/from-parser.js +49 -0
- package/build/database/query-parser/group-parser.js +55 -0
- package/build/database/query-parser/joins-parser.js +37 -0
- package/build/database/query-parser/limit-parser.js +77 -0
- package/build/database/query-parser/options.js +94 -0
- package/build/database/query-parser/order-parser.js +45 -0
- package/build/database/query-parser/select-parser.js +67 -0
- package/build/database/query-parser/where-parser.js +46 -0
- package/build/database/record/acts-as-list.js +374 -0
- package/build/database/record/attachments/download.js +49 -0
- package/build/database/record/attachments/handle.js +188 -0
- package/build/database/record/attachments/normalize-input.js +213 -0
- package/build/database/record/attachments/storage-drivers/filesystem.js +114 -0
- package/build/database/record/attachments/storage-drivers/native.js +146 -0
- package/build/database/record/attachments/storage-drivers/s3.js +245 -0
- package/build/database/record/attachments/store.js +591 -0
- package/build/database/record/index.js +4094 -0
- package/build/database/record/instance-relationships/base.js +289 -0
- package/build/database/record/instance-relationships/belongs-to.js +84 -0
- package/build/database/record/instance-relationships/has-many.js +284 -0
- package/build/database/record/instance-relationships/has-one.js +117 -0
- package/build/database/record/record-not-found-error.js +3 -0
- package/build/database/record/relationships/base.js +195 -0
- package/build/database/record/relationships/belongs-to.js +57 -0
- package/build/database/record/relationships/has-many.js +46 -0
- package/build/database/record/relationships/has-one.js +46 -0
- package/build/database/record/state-machine.js +278 -0
- package/build/database/record/user-module.js +43 -0
- package/build/database/record/validators/base.js +27 -0
- package/build/database/record/validators/format.js +50 -0
- package/build/database/record/validators/presence.js +24 -0
- package/build/database/record/validators/uniqueness.js +124 -0
- package/build/database/table-data/index.js +241 -0
- package/build/database/table-data/table-column.js +416 -0
- package/build/database/table-data/table-foreign-key.js +69 -0
- package/build/database/table-data/table-index.js +46 -0
- package/build/database/table-data/table-reference.js +13 -0
- package/build/database/use-database.js +48 -0
- package/build/environment-handlers/base.js +561 -0
- package/build/environment-handlers/browser.js +338 -0
- package/build/environment-handlers/node/cli/commands/background-jobs-main.js +21 -0
- package/build/environment-handlers/node/cli/commands/background-jobs-runner.js +24 -0
- package/build/environment-handlers/node/cli/commands/background-jobs-worker.js +47 -0
- package/build/environment-handlers/node/cli/commands/beacon.js +21 -0
- package/build/environment-handlers/node/cli/commands/cli-command-context.js +31 -0
- package/build/environment-handlers/node/cli/commands/console.js +149 -0
- package/build/environment-handlers/node/cli/commands/db/schema/dump.js +43 -0
- package/build/environment-handlers/node/cli/commands/db/schema/load.js +69 -0
- package/build/environment-handlers/node/cli/commands/db/seed.js +79 -0
- package/build/environment-handlers/node/cli/commands/destroy/migration.js +47 -0
- package/build/environment-handlers/node/cli/commands/generate/base-models.js +396 -0
- package/build/environment-handlers/node/cli/commands/generate/frontend-models.js +872 -0
- package/build/environment-handlers/node/cli/commands/generate/migration.js +45 -0
- package/build/environment-handlers/node/cli/commands/generate/model.js +45 -0
- package/build/environment-handlers/node/cli/commands/init.js +68 -0
- package/build/environment-handlers/node/cli/commands/routes.js +63 -0
- package/build/environment-handlers/node/cli/commands/run-script.js +85 -0
- package/build/environment-handlers/node/cli/commands/runner.js +84 -0
- package/build/environment-handlers/node/cli/commands/server.js +151 -0
- package/build/environment-handlers/node/cli/commands/test.js +118 -0
- package/build/environment-handlers/node.js +887 -0
- package/build/error-logger.js +30 -0
- package/build/frontend-model-controller.js +3491 -0
- package/build/frontend-model-resource/base-resource.js +935 -0
- package/build/frontend-models/base.js +4004 -0
- package/build/frontend-models/clear-pending-debounced-callback.js +16 -0
- package/build/frontend-models/event-hook-models.js +49 -0
- package/build/frontend-models/model-registry.js +28 -0
- package/build/frontend-models/outgoing-event-buffer.js +51 -0
- package/build/frontend-models/preloader.js +169 -0
- package/build/frontend-models/query.js +2245 -0
- package/build/frontend-models/resource-config-validation.js +56 -0
- package/build/frontend-models/resource-definition.js +399 -0
- package/build/frontend-models/transport-serialization.js +369 -0
- package/build/frontend-models/use-created-event.js +21 -0
- package/build/frontend-models/use-destroyed-event.js +148 -0
- package/build/frontend-models/use-model-class-event.js +164 -0
- package/build/frontend-models/use-updated-event.js +152 -0
- package/build/frontend-models/websocket-channel.js +494 -0
- package/build/frontend-models/websocket-publishers.js +224 -0
- package/build/http-client/header.js +17 -0
- package/build/http-client/index.js +139 -0
- package/build/http-client/request.js +94 -0
- package/build/http-client/response.js +151 -0
- package/build/http-client/websocket-client.js +27 -0
- package/build/http-server/client/index.js +507 -0
- package/build/http-server/client/params-to-object.js +152 -0
- package/build/http-server/client/request-buffer/form-data-part.js +139 -0
- package/build/http-server/client/request-buffer/header.js +19 -0
- package/build/http-server/client/request-buffer/index.js +535 -0
- package/build/http-server/client/request-parser.js +195 -0
- package/build/http-server/client/request-runner.js +321 -0
- package/build/http-server/client/request-timing.js +171 -0
- package/build/http-server/client/request.js +114 -0
- package/build/http-server/client/response.js +251 -0
- package/build/http-server/client/uploaded-file/memory-uploaded-file.js +32 -0
- package/build/http-server/client/uploaded-file/temporary-uploaded-file.js +32 -0
- package/build/http-server/client/uploaded-file/uploaded-file.js +36 -0
- package/build/http-server/client/websocket-request.js +147 -0
- package/build/http-server/client/websocket-session.js +1755 -0
- package/build/http-server/cookie.js +245 -0
- package/build/http-server/development-reloader.js +240 -0
- package/build/http-server/index.js +561 -0
- package/build/http-server/remote-address.js +77 -0
- package/build/http-server/server-client.js +222 -0
- package/build/http-server/server-lock.js +178 -0
- package/build/http-server/websocket-channel-subscribers.js +110 -0
- package/build/http-server/websocket-channel.js +137 -0
- package/build/http-server/websocket-connection.js +118 -0
- package/build/http-server/websocket-event-log-store.js +433 -0
- package/build/http-server/websocket-events-host.js +170 -0
- package/build/http-server/websocket-events.js +50 -0
- package/build/http-server/worker-handler/channel-subscriber-dispatch.js +28 -0
- package/build/http-server/worker-handler/in-process.js +155 -0
- package/build/http-server/worker-handler/index.js +370 -0
- package/build/http-server/worker-handler/worker-script.js +6 -0
- package/build/http-server/worker-handler/worker-thread.js +286 -0
- package/build/index.js +1 -2
- package/build/initializer.js +39 -0
- package/build/jobs/mail-delivery.js +22 -0
- package/build/logger/base-logger.js +34 -0
- package/build/logger/console-logger.js +28 -0
- package/build/logger/file-logger.js +36 -0
- package/build/logger/outputs/array-output.js +50 -0
- package/build/logger/outputs/console-output.js +32 -0
- package/build/logger/outputs/file-output.js +55 -0
- package/build/logger/outputs/stdout-output.js +64 -0
- package/build/logger.js +507 -0
- package/build/mailer/backends/smtp.js +197 -0
- package/build/mailer/base.js +337 -0
- package/build/mailer/delivery.js +70 -0
- package/build/mailer/index.js +24 -0
- package/build/mailer.js +15 -0
- package/build/plugins/sqljs-wasm-route-controller.js +70 -0
- package/build/plugins/sqljs-wasm-route.js +71 -0
- package/build/record-payload-values.js +83 -0
- package/build/routes/app-routes.js +17 -0
- package/build/routes/base-route.js +133 -0
- package/build/routes/basic-route.js +109 -0
- package/build/routes/built-in/debug/controller.js +12 -0
- package/build/routes/built-in/errors/controller.js +7 -0
- package/build/routes/get-route.js +75 -0
- package/build/routes/hooks/frontend-model-command-route-hook.js +100 -0
- package/build/routes/index.js +50 -0
- package/build/routes/namespace-route.js +51 -0
- package/build/routes/plugin-routes.js +141 -0
- package/build/routes/post-route.js +74 -0
- package/build/routes/resolver.js +535 -0
- package/build/routes/resource-route.js +154 -0
- package/build/routes/root-route.js +11 -0
- package/build/src/authorization/ability.d.ts +24 -23
- package/build/src/authorization/ability.d.ts.map +1 -1
- package/build/src/authorization/ability.js +14 -13
- package/build/src/authorization/base-resource.d.ts +20 -26
- package/build/src/authorization/base-resource.d.ts.map +1 -1
- package/build/src/authorization/base-resource.js +13 -11
- package/build/src/configuration-types.d.ts +21 -2
- package/build/src/configuration-types.d.ts.map +1 -1
- package/build/src/configuration-types.js +8 -2
- package/build/src/database/query/where-combinator.d.ts.map +1 -1
- package/build/src/database/query/where-combinator.js +1 -2
- package/build/src/database/record/acts-as-list.js +2 -2
- package/build/src/database/record/attachments/store.d.ts +1 -1
- package/build/src/database/record/attachments/store.d.ts.map +1 -1
- package/build/src/database/record/attachments/store.js +2 -2
- package/build/src/database/record/index.d.ts +82 -20
- package/build/src/database/record/index.d.ts.map +1 -1
- package/build/src/database/record/index.js +126 -13
- package/build/src/database/record/relationships/base.d.ts +2 -2
- package/build/src/database/record/relationships/base.d.ts.map +1 -1
- package/build/src/database/record/relationships/base.js +3 -3
- package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts +4 -2
- package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/generate/base-models.js +59 -36
- package/build/src/frontend-model-controller.d.ts +6 -6
- package/build/src/frontend-model-controller.d.ts.map +1 -1
- package/build/src/frontend-model-controller.js +4 -4
- package/build/src/frontend-model-resource/base-resource.d.ts +18 -17
- package/build/src/frontend-model-resource/base-resource.d.ts.map +1 -1
- package/build/src/frontend-model-resource/base-resource.js +22 -10
- package/build/src/frontend-models/base.d.ts +19 -12
- package/build/src/frontend-models/base.d.ts.map +1 -1
- package/build/src/frontend-models/base.js +79 -48
- package/build/src/frontend-models/preloader.d.ts +6 -6
- package/build/src/frontend-models/preloader.d.ts.map +1 -1
- package/build/src/frontend-models/preloader.js +5 -5
- package/build/src/frontend-models/query.d.ts.map +1 -1
- package/build/src/frontend-models/query.js +1 -4
- package/build/src/utils/ransack.d.ts.map +1 -1
- package/build/src/utils/ransack.js +1 -2
- package/build/templates/configuration.js +61 -0
- package/build/templates/generate-migration.js +11 -0
- package/build/templates/generate-model.js +6 -0
- package/build/templates/routes.js +11 -0
- package/build/testing/base-expect.js +17 -0
- package/build/testing/browser-frontend-model-event-hook-scenarios.js +520 -0
- package/build/testing/browser-test-app.js +32 -0
- package/build/testing/expect-to-change.js +55 -0
- package/build/testing/expect-utils.js +269 -0
- package/build/testing/expect.js +763 -0
- package/build/testing/request-client.js +90 -0
- package/build/testing/test-files-finder.js +364 -0
- package/build/testing/test-filter-parser.js +198 -0
- package/build/testing/test-runner.js +1168 -0
- package/build/testing/test-suite-splitter.js +177 -0
- package/build/testing/test.js +370 -0
- package/build/utils/backtrace-cleaner-node.js +87 -0
- package/build/utils/backtrace-cleaner.js +266 -0
- package/build/utils/ensure-error.js +15 -0
- package/build/utils/event-emitter.js +8 -0
- package/build/utils/file-exists.js +18 -0
- package/build/utils/format-value.js +101 -0
- package/build/utils/model-scope.js +56 -0
- package/build/utils/nest-callbacks.js +22 -0
- package/build/utils/plain-object.js +14 -0
- package/build/utils/ransack.js +859 -0
- package/build/utils/rest-args-error.js +14 -0
- package/build/utils/singularize-model-name.js +18 -0
- package/build/utils/split-sql-statements.js +88 -0
- package/build/utils/to-import-specifier.js +53 -0
- package/build/utils/with-tracked-stack-async-hooks.js +103 -0
- package/build/utils/with-tracked-stack.js +38 -0
- package/build/velocious-error.js +34 -0
- package/index.js +1 -0
- package/package.json +10 -4
- package/scripts/clean-build.js +8 -0
- package/scripts/ensure-bin-executable.js +13 -0
- package/scripts/run-tests.js +37 -0
- package/scripts/test-browser.js +486 -0
- package/src/application.js +229 -0
- package/src/authorization/ability.js +329 -0
- package/src/authorization/base-resource.js +143 -0
- package/src/background-jobs/client.js +50 -0
- package/src/background-jobs/cron-expression.js +277 -0
- package/src/background-jobs/forked-runner-child.js +86 -0
- package/src/background-jobs/job-record.js +13 -0
- package/src/background-jobs/job-registry.js +92 -0
- package/src/background-jobs/job-runner.js +107 -0
- package/src/background-jobs/job.js +77 -0
- package/src/background-jobs/json-socket.js +78 -0
- package/src/background-jobs/main.js +926 -0
- package/src/background-jobs/normalize-error.js +26 -0
- package/src/background-jobs/scheduler.js +274 -0
- package/src/background-jobs/socket-request.js +68 -0
- package/src/background-jobs/status-reporter.js +101 -0
- package/src/background-jobs/store.js +994 -0
- package/src/background-jobs/types.js +70 -0
- package/src/background-jobs/web/authorization.js +89 -0
- package/src/background-jobs/web/controller.js +280 -0
- package/src/background-jobs/web/index.js +57 -0
- package/src/background-jobs/web/path-matcher.js +74 -0
- package/src/background-jobs/web/registry.js +49 -0
- package/src/background-jobs/worker.js +683 -0
- package/src/beacon/client.js +330 -0
- package/src/beacon/in-process-broker.js +71 -0
- package/src/beacon/in-process-client.js +139 -0
- package/src/beacon/server.js +148 -0
- package/src/beacon/types.js +55 -0
- package/src/cli/base-command.js +67 -0
- package/src/cli/browser-cli.js +45 -0
- package/src/cli/commands/background-jobs-main.js +7 -0
- package/src/cli/commands/background-jobs-runner.js +7 -0
- package/src/cli/commands/background-jobs-worker.js +7 -0
- package/src/cli/commands/beacon.js +7 -0
- package/src/cli/commands/console.js +12 -0
- package/src/cli/commands/db/base-command.js +82 -0
- package/src/cli/commands/db/create.js +64 -0
- package/src/cli/commands/db/drop.js +75 -0
- package/src/cli/commands/db/migrate.js +17 -0
- package/src/cli/commands/db/reset.js +22 -0
- package/src/cli/commands/db/rollback.js +15 -0
- package/src/cli/commands/db/schema/dump.js +12 -0
- package/src/cli/commands/db/schema/load.js +12 -0
- package/src/cli/commands/db/seed.js +12 -0
- package/src/cli/commands/db/tenants/check.js +38 -0
- package/src/cli/commands/db/tenants/create.js +33 -0
- package/src/cli/commands/db/tenants/migrate.js +49 -0
- package/src/cli/commands/destroy/migration.js +7 -0
- package/src/cli/commands/generate/base-models.js +7 -0
- package/src/cli/commands/generate/frontend-models.js +12 -0
- package/src/cli/commands/generate/migration.js +7 -0
- package/src/cli/commands/generate/model.js +7 -0
- package/src/cli/commands/init.js +11 -0
- package/src/cli/commands/routes.js +7 -0
- package/src/cli/commands/run-script.js +12 -0
- package/src/cli/commands/runner.js +12 -0
- package/src/cli/commands/server.js +7 -0
- package/src/cli/commands/test.js +9 -0
- package/src/cli/index.js +152 -0
- package/src/cli/tenant-database-command-helper.js +198 -0
- package/src/cli/use-browser-cli.js +30 -0
- package/src/configuration-resolver.js +65 -0
- package/src/configuration-types.js +429 -0
- package/src/configuration.js +2590 -0
- package/src/controller.js +421 -0
- package/src/current-configuration.js +31 -0
- package/src/current.js +80 -0
- package/src/database/annotations-async-hooks.js +47 -0
- package/src/database/annotations.js +40 -0
- package/src/database/drivers/base-column.js +182 -0
- package/src/database/drivers/base-columns-index.js +81 -0
- package/src/database/drivers/base-foreign-key.js +104 -0
- package/src/database/drivers/base-table.js +156 -0
- package/src/database/drivers/base.js +1609 -0
- package/src/database/drivers/mssql/column.js +74 -0
- package/src/database/drivers/mssql/columns-index.js +6 -0
- package/src/database/drivers/mssql/connect-connection.js +16 -0
- package/src/database/drivers/mssql/foreign-key.js +12 -0
- package/src/database/drivers/mssql/index.js +590 -0
- package/src/database/drivers/mssql/options.js +79 -0
- package/src/database/drivers/mssql/query-parser.js +6 -0
- package/src/database/drivers/mssql/sql/alter-table.js +4 -0
- package/src/database/drivers/mssql/sql/create-database.js +36 -0
- package/src/database/drivers/mssql/sql/create-index.js +4 -0
- package/src/database/drivers/mssql/sql/create-table.js +4 -0
- package/src/database/drivers/mssql/sql/delete.js +19 -0
- package/src/database/drivers/mssql/sql/drop-database.js +36 -0
- package/src/database/drivers/mssql/sql/drop-table.js +4 -0
- package/src/database/drivers/mssql/sql/insert.js +4 -0
- package/src/database/drivers/mssql/sql/update.js +31 -0
- package/src/database/drivers/mssql/sql/upsert.js +23 -0
- package/src/database/drivers/mssql/structure-sql.js +120 -0
- package/src/database/drivers/mssql/table.js +145 -0
- package/src/database/drivers/mysql/column.js +112 -0
- package/src/database/drivers/mysql/columns-index.js +22 -0
- package/src/database/drivers/mysql/foreign-key.js +12 -0
- package/src/database/drivers/mysql/index.js +473 -0
- package/src/database/drivers/mysql/options.js +34 -0
- package/src/database/drivers/mysql/query-parser.js +6 -0
- package/src/database/drivers/mysql/query.js +37 -0
- package/src/database/drivers/mysql/sql/alter-table.js +6 -0
- package/src/database/drivers/mysql/sql/create-database.js +39 -0
- package/src/database/drivers/mysql/sql/create-index.js +6 -0
- package/src/database/drivers/mysql/sql/create-table.js +6 -0
- package/src/database/drivers/mysql/sql/delete.js +21 -0
- package/src/database/drivers/mysql/sql/drop-database.js +6 -0
- package/src/database/drivers/mysql/sql/drop-table.js +6 -0
- package/src/database/drivers/mysql/sql/insert.js +6 -0
- package/src/database/drivers/mysql/sql/update.js +33 -0
- package/src/database/drivers/mysql/sql/upsert.js +13 -0
- package/src/database/drivers/mysql/structure-sql.js +93 -0
- package/src/database/drivers/mysql/table.js +121 -0
- package/src/database/drivers/pgsql/column.js +90 -0
- package/src/database/drivers/pgsql/columns-index.js +6 -0
- package/src/database/drivers/pgsql/foreign-key.js +12 -0
- package/src/database/drivers/pgsql/index.js +441 -0
- package/src/database/drivers/pgsql/options.js +32 -0
- package/src/database/drivers/pgsql/query-parser.js +6 -0
- package/src/database/drivers/pgsql/sql/alter-table.js +6 -0
- package/src/database/drivers/pgsql/sql/create-database.js +38 -0
- package/src/database/drivers/pgsql/sql/create-index.js +6 -0
- package/src/database/drivers/pgsql/sql/create-table.js +6 -0
- package/src/database/drivers/pgsql/sql/delete.js +21 -0
- package/src/database/drivers/pgsql/sql/drop-database.js +6 -0
- package/src/database/drivers/pgsql/sql/drop-table.js +6 -0
- package/src/database/drivers/pgsql/sql/insert.js +6 -0
- package/src/database/drivers/pgsql/sql/update.js +33 -0
- package/src/database/drivers/pgsql/sql/upsert.js +14 -0
- package/src/database/drivers/pgsql/structure-sql.js +126 -0
- package/src/database/drivers/pgsql/table.js +135 -0
- package/src/database/drivers/sqlite/base.js +509 -0
- package/src/database/drivers/sqlite/column.js +75 -0
- package/src/database/drivers/sqlite/columns-index.js +30 -0
- package/src/database/drivers/sqlite/connection-sql-js.js +46 -0
- package/src/database/drivers/sqlite/foreign-key.js +24 -0
- package/src/database/drivers/sqlite/index.js +394 -0
- package/src/database/drivers/sqlite/index.native.js +72 -0
- package/src/database/drivers/sqlite/index.web.js +99 -0
- package/src/database/drivers/sqlite/options.js +32 -0
- package/src/database/drivers/sqlite/query-parser.js +6 -0
- package/src/database/drivers/sqlite/query.js +35 -0
- package/src/database/drivers/sqlite/query.native.js +35 -0
- package/src/database/drivers/sqlite/query.web.js +49 -0
- package/src/database/drivers/sqlite/sql/alter-table.js +187 -0
- package/src/database/drivers/sqlite/sql/create-index.js +6 -0
- package/src/database/drivers/sqlite/sql/create-table.js +6 -0
- package/src/database/drivers/sqlite/sql/delete.js +26 -0
- package/src/database/drivers/sqlite/sql/drop-table.js +6 -0
- package/src/database/drivers/sqlite/sql/insert.js +6 -0
- package/src/database/drivers/sqlite/sql/update.js +33 -0
- package/src/database/drivers/sqlite/sql/upsert.js +14 -0
- package/src/database/drivers/sqlite/structure-sql.js +56 -0
- package/src/database/drivers/sqlite/table-rebuilder.js +96 -0
- package/src/database/drivers/sqlite/table.js +131 -0
- package/src/database/drivers/structure-sql/utils.js +35 -0
- package/src/database/handler.js +13 -0
- package/src/database/initializer-from-require-context.js +101 -0
- package/src/database/migration/index.js +438 -0
- package/src/database/migrator/files-finder.js +55 -0
- package/src/database/migrator/types.js +31 -0
- package/src/database/migrator.js +557 -0
- package/src/database/pool/async-tracked-multi-connection.js +1164 -0
- package/src/database/pool/base-methods-forward.js +52 -0
- package/src/database/pool/base.js +380 -0
- package/src/database/pool/single-multi-use.js +118 -0
- package/src/database/query/alter-table-base.js +104 -0
- package/src/database/query/base.js +49 -0
- package/src/database/query/create-database-base.js +42 -0
- package/src/database/query/create-index-base.js +117 -0
- package/src/database/query/create-table-base.js +205 -0
- package/src/database/query/delete-base.js +19 -0
- package/src/database/query/drop-database-base.js +38 -0
- package/src/database/query/drop-table-base.js +58 -0
- package/src/database/query/from-base.js +36 -0
- package/src/database/query/from-plain.js +16 -0
- package/src/database/query/from-table.js +18 -0
- package/src/database/query/index.js +533 -0
- package/src/database/query/insert-base.js +172 -0
- package/src/database/query/join-base.js +43 -0
- package/src/database/query/join-object.js +167 -0
- package/src/database/query/join-plain.js +18 -0
- package/src/database/query/join-tracker.js +93 -0
- package/src/database/query/model-class-query.js +1577 -0
- package/src/database/query/order-base.js +33 -0
- package/src/database/query/order-column.js +77 -0
- package/src/database/query/order-plain.js +28 -0
- package/src/database/query/preloader/belongs-to.js +267 -0
- package/src/database/query/preloader/ensure-model-class-initialized.js +18 -0
- package/src/database/query/preloader/has-many.js +316 -0
- package/src/database/query/preloader/has-one.js +123 -0
- package/src/database/query/preloader/selection.js +152 -0
- package/src/database/query/preloader.js +201 -0
- package/src/database/query/query-data.js +305 -0
- package/src/database/query/select-base.js +30 -0
- package/src/database/query/select-plain.js +18 -0
- package/src/database/query/select-table-and-column.js +28 -0
- package/src/database/query/update-base.js +41 -0
- package/src/database/query/upsert-base.js +103 -0
- package/src/database/query/where-base.js +38 -0
- package/src/database/query/where-combinator.js +31 -0
- package/src/database/query/where-hash.js +77 -0
- package/src/database/query/where-model-class-hash.js +505 -0
- package/src/database/query/where-not.js +23 -0
- package/src/database/query/where-plain.js +20 -0
- package/src/database/query/with-count.js +219 -0
- package/src/database/query-parser/base-query-parser.js +40 -0
- package/src/database/query-parser/from-parser.js +49 -0
- package/src/database/query-parser/group-parser.js +55 -0
- package/src/database/query-parser/joins-parser.js +37 -0
- package/src/database/query-parser/limit-parser.js +77 -0
- package/src/database/query-parser/options.js +94 -0
- package/src/database/query-parser/order-parser.js +45 -0
- package/src/database/query-parser/select-parser.js +67 -0
- package/src/database/query-parser/where-parser.js +46 -0
- package/src/database/record/acts-as-list.js +374 -0
- package/src/database/record/attachments/download.js +49 -0
- package/src/database/record/attachments/handle.js +188 -0
- package/src/database/record/attachments/normalize-input.js +213 -0
- package/src/database/record/attachments/storage-drivers/filesystem.js +114 -0
- package/src/database/record/attachments/storage-drivers/native.js +146 -0
- package/src/database/record/attachments/storage-drivers/s3.js +245 -0
- package/src/database/record/attachments/store.js +591 -0
- package/src/database/record/index.js +4094 -0
- package/src/database/record/instance-relationships/base.js +289 -0
- package/src/database/record/instance-relationships/belongs-to.js +84 -0
- package/src/database/record/instance-relationships/has-many.js +284 -0
- package/src/database/record/instance-relationships/has-one.js +117 -0
- package/src/database/record/record-not-found-error.js +3 -0
- package/src/database/record/relationships/base.js +195 -0
- package/src/database/record/relationships/belongs-to.js +57 -0
- package/src/database/record/relationships/has-many.js +46 -0
- package/src/database/record/relationships/has-one.js +46 -0
- package/src/database/record/state-machine.js +278 -0
- package/src/database/record/user-module.js +43 -0
- package/src/database/record/validators/base.js +27 -0
- package/src/database/record/validators/format.js +50 -0
- package/src/database/record/validators/presence.js +24 -0
- package/src/database/record/validators/uniqueness.js +124 -0
- package/src/database/table-data/index.js +241 -0
- package/src/database/table-data/table-column.js +416 -0
- package/src/database/table-data/table-foreign-key.js +69 -0
- package/src/database/table-data/table-index.js +46 -0
- package/src/database/table-data/table-reference.js +13 -0
- package/src/database/use-database.js +48 -0
- package/src/environment-handlers/base.js +561 -0
- package/src/environment-handlers/browser.js +338 -0
- package/src/environment-handlers/node/cli/commands/background-jobs-main.js +21 -0
- package/src/environment-handlers/node/cli/commands/background-jobs-runner.js +24 -0
- package/src/environment-handlers/node/cli/commands/background-jobs-worker.js +47 -0
- package/src/environment-handlers/node/cli/commands/beacon.js +21 -0
- package/src/environment-handlers/node/cli/commands/cli-command-context.js +31 -0
- package/src/environment-handlers/node/cli/commands/console.js +149 -0
- package/src/environment-handlers/node/cli/commands/db/schema/dump.js +43 -0
- package/src/environment-handlers/node/cli/commands/db/schema/load.js +69 -0
- package/src/environment-handlers/node/cli/commands/db/seed.js +79 -0
- package/src/environment-handlers/node/cli/commands/destroy/migration.js +47 -0
- package/src/environment-handlers/node/cli/commands/generate/base-models.js +396 -0
- package/src/environment-handlers/node/cli/commands/generate/frontend-models.js +872 -0
- package/src/environment-handlers/node/cli/commands/generate/migration.js +45 -0
- package/src/environment-handlers/node/cli/commands/generate/model.js +45 -0
- package/src/environment-handlers/node/cli/commands/init.js +68 -0
- package/src/environment-handlers/node/cli/commands/routes.js +63 -0
- package/src/environment-handlers/node/cli/commands/run-script.js +85 -0
- package/src/environment-handlers/node/cli/commands/runner.js +84 -0
- package/src/environment-handlers/node/cli/commands/server.js +151 -0
- package/src/environment-handlers/node/cli/commands/test.js +118 -0
- package/src/environment-handlers/node.js +887 -0
- package/src/error-logger.js +30 -0
- package/src/frontend-model-controller.js +3491 -0
- package/src/frontend-model-resource/base-resource.js +935 -0
- package/src/frontend-models/base.js +4004 -0
- package/src/frontend-models/clear-pending-debounced-callback.js +16 -0
- package/src/frontend-models/event-hook-models.js +49 -0
- package/src/frontend-models/model-registry.js +28 -0
- package/src/frontend-models/outgoing-event-buffer.js +51 -0
- package/src/frontend-models/preloader.js +169 -0
- package/src/frontend-models/query.js +2245 -0
- package/src/frontend-models/resource-config-validation.js +56 -0
- package/src/frontend-models/resource-definition.js +399 -0
- package/src/frontend-models/transport-serialization.js +369 -0
- package/src/frontend-models/use-created-event.js +21 -0
- package/src/frontend-models/use-destroyed-event.js +148 -0
- package/src/frontend-models/use-model-class-event.js +164 -0
- package/src/frontend-models/use-updated-event.js +152 -0
- package/src/frontend-models/websocket-channel.js +494 -0
- package/src/frontend-models/websocket-publishers.js +224 -0
- package/src/http-client/header.js +17 -0
- package/src/http-client/index.js +139 -0
- package/src/http-client/request.js +94 -0
- package/src/http-client/response.js +151 -0
- package/src/http-client/websocket-client.js +27 -0
- package/src/http-server/client/index.js +507 -0
- package/src/http-server/client/params-to-object.js +152 -0
- package/src/http-server/client/request-buffer/form-data-part.js +139 -0
- package/src/http-server/client/request-buffer/header.js +19 -0
- package/src/http-server/client/request-buffer/index.js +535 -0
- package/src/http-server/client/request-parser.js +195 -0
- package/src/http-server/client/request-runner.js +321 -0
- package/src/http-server/client/request-timing.js +171 -0
- package/src/http-server/client/request.js +114 -0
- package/src/http-server/client/response.js +251 -0
- package/src/http-server/client/uploaded-file/memory-uploaded-file.js +32 -0
- package/src/http-server/client/uploaded-file/temporary-uploaded-file.js +32 -0
- package/src/http-server/client/uploaded-file/uploaded-file.js +36 -0
- package/src/http-server/client/websocket-request.js +147 -0
- package/src/http-server/client/websocket-session.js +1755 -0
- package/src/http-server/cookie.js +245 -0
- package/src/http-server/development-reloader.js +240 -0
- package/src/http-server/index.js +561 -0
- package/src/http-server/remote-address.js +77 -0
- package/src/http-server/server-client.js +222 -0
- package/src/http-server/server-lock.js +178 -0
- package/src/http-server/websocket-channel-subscribers.js +110 -0
- package/src/http-server/websocket-channel.js +137 -0
- package/src/http-server/websocket-connection.js +118 -0
- package/src/http-server/websocket-event-log-store.js +433 -0
- package/src/http-server/websocket-events-host.js +170 -0
- package/src/http-server/websocket-events.js +50 -0
- package/src/http-server/worker-handler/channel-subscriber-dispatch.js +28 -0
- package/src/http-server/worker-handler/in-process.js +155 -0
- package/src/http-server/worker-handler/index.js +370 -0
- package/src/http-server/worker-handler/worker-script.js +6 -0
- package/src/http-server/worker-handler/worker-thread.js +286 -0
- package/src/initializer.js +39 -0
- package/src/jobs/.gitkeep +1 -0
- package/src/jobs/mail-delivery.js +22 -0
- package/src/logger/base-logger.js +34 -0
- package/src/logger/console-logger.js +28 -0
- package/src/logger/file-logger.js +36 -0
- package/src/logger/outputs/array-output.js +50 -0
- package/src/logger/outputs/console-output.js +32 -0
- package/src/logger/outputs/file-output.js +55 -0
- package/src/logger/outputs/stdout-output.js +64 -0
- package/src/logger.js +507 -0
- package/src/mailer/backends/smtp.js +197 -0
- package/src/mailer/base.js +337 -0
- package/src/mailer/delivery.js +70 -0
- package/src/mailer/index.js +24 -0
- package/src/mailer.js +15 -0
- package/src/plugins/sqljs-wasm-route-controller.js +70 -0
- package/src/plugins/sqljs-wasm-route.js +71 -0
- package/src/record-payload-values.js +83 -0
- package/src/routes/app-routes.js +17 -0
- package/src/routes/base-route.js +133 -0
- package/src/routes/basic-route.js +109 -0
- package/src/routes/built-in/debug/controller.js +12 -0
- package/src/routes/built-in/errors/controller.js +7 -0
- package/src/routes/built-in/errors/not-found.ejs +1 -0
- package/src/routes/get-route.js +75 -0
- package/src/routes/hooks/frontend-model-command-route-hook.js +100 -0
- package/src/routes/index.js +50 -0
- package/src/routes/namespace-route.js +51 -0
- package/src/routes/plugin-routes.js +141 -0
- package/src/routes/post-route.js +74 -0
- package/src/routes/resolver.js +535 -0
- package/src/routes/resource-route.js +154 -0
- package/src/routes/root-route.js +11 -0
- package/src/templates/configuration.js +61 -0
- package/src/templates/generate-migration.js +11 -0
- package/src/templates/generate-model.js +6 -0
- package/src/templates/routes.js +11 -0
- package/src/testing/base-expect.js +17 -0
- package/src/testing/browser-frontend-model-event-hook-scenarios.js +520 -0
- package/src/testing/browser-test-app.js +32 -0
- package/src/testing/expect-to-change.js +55 -0
- package/src/testing/expect-utils.js +269 -0
- package/src/testing/expect.js +763 -0
- package/src/testing/request-client.js +90 -0
- package/src/testing/test-files-finder.js +364 -0
- package/src/testing/test-filter-parser.js +198 -0
- package/src/testing/test-runner.js +1168 -0
- package/src/testing/test-suite-splitter.js +177 -0
- package/src/testing/test.js +370 -0
- package/src/types/external-modules.d.ts +57 -0
- package/src/utils/backtrace-cleaner-node.js +87 -0
- package/src/utils/backtrace-cleaner.js +266 -0
- package/src/utils/ensure-error.js +15 -0
- package/src/utils/event-emitter.js +8 -0
- package/src/utils/file-exists.js +18 -0
- package/src/utils/format-value.js +101 -0
- package/src/utils/model-scope.js +56 -0
- package/src/utils/nest-callbacks.js +22 -0
- package/src/utils/plain-object.js +14 -0
- package/src/utils/ransack.js +859 -0
- package/src/utils/rest-args-error.js +14 -0
- package/src/utils/singularize-model-name.js +18 -0
- package/src/utils/split-sql-statements.js +88 -0
- package/src/utils/to-import-specifier.js +53 -0
- package/src/utils/with-tracked-stack-async-hooks.js +103 -0
- package/src/utils/with-tracked-stack.js +38 -0
- package/src/velocious-error.js +34 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,1609 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CreateIndexSqlArgs type.
|
|
5
|
+
* @typedef {object} CreateIndexSqlArgs
|
|
6
|
+
* @property {Array<string | import("./../table-data/table-column.js").default>} columns - Columns to include in the index.
|
|
7
|
+
* @property {boolean} [ifNotExists] - Skip creation if the index already exists.
|
|
8
|
+
* @property {string} [name] - Explicit index name to use.
|
|
9
|
+
* @property {boolean} [unique] - Whether the index should enforce uniqueness.
|
|
10
|
+
* @property {string} tableName - Name of the table to add the index to.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* DropTableSqlArgsType type.
|
|
14
|
+
* @typedef {object} DropTableSqlArgsType
|
|
15
|
+
* @property {boolean} [cascade] - Whether dependent objects should be dropped too.
|
|
16
|
+
* @property {boolean} [ifExists] - Skip dropping if the table does not exist.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* DeleteSqlArgsType type.
|
|
20
|
+
* @typedef {object} DeleteSqlArgsType
|
|
21
|
+
* @property {string} tableName - Table name to delete from.
|
|
22
|
+
* @property {{[key: string]: ?}} conditions - Conditions used to build the delete WHERE clause.
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* InsertSqlArgsType type.
|
|
26
|
+
* @typedef {object} InsertSqlArgsType
|
|
27
|
+
* @property {string[]} [columns] - Column names for `rows` inserts.
|
|
28
|
+
* @property {{[key: string]: ?}} [data] - Column/value pairs for a single-row insert.
|
|
29
|
+
* @property {boolean} [multiple] - Whether this insert should be treated as multi-row.
|
|
30
|
+
* @property {string[]} [returnLastInsertedColumnNames] - Column names to return after insert.
|
|
31
|
+
* @property {Array<Array<?>>} [rows] - Row values for a multi-row insert.
|
|
32
|
+
* @property {string} tableName - Table name to insert into.
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* QueryRowType type.
|
|
36
|
+
* @typedef {Record<string, ?>} QueryRowType
|
|
37
|
+
* @typedef {Array<QueryRowType>} QueryResultType
|
|
38
|
+
*/
|
|
39
|
+
/**
|
|
40
|
+
* RetryableDatabaseErrorResult type.
|
|
41
|
+
* @typedef {object} RetryableDatabaseErrorResult
|
|
42
|
+
* @property {boolean} retry - Whether the error should be retried.
|
|
43
|
+
* @property {boolean} reconnect - Whether to reconnect before retrying.
|
|
44
|
+
* @property {number} [maxTries] - Override the max retry attempts.
|
|
45
|
+
* @property {number} [waitMs] - Wait time before retrying in milliseconds.
|
|
46
|
+
*/
|
|
47
|
+
/**
|
|
48
|
+
* QueryOptions type.
|
|
49
|
+
* @typedef {object} QueryOptions
|
|
50
|
+
* @property {string} [logName] - Query log subject.
|
|
51
|
+
* @property {boolean} [logQuery] - Whether to log the query.
|
|
52
|
+
* @property {boolean} [processListComment] - Whether to add process-list comments to the query.
|
|
53
|
+
* @property {string} [sourceStack] - Stack captured at the caller boundary.
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* ActiveQueryDebugSnapshot type.
|
|
58
|
+
* @typedef {object} ActiveQueryDebugSnapshot
|
|
59
|
+
* @property {string[]} annotations - Database annotations active when the query started.
|
|
60
|
+
* @property {string} logName - Query log name.
|
|
61
|
+
* @property {number} startedAtUnixMs - Query start timestamp.
|
|
62
|
+
* @property {number} runningMs - Query runtime in milliseconds.
|
|
63
|
+
* @property {string} sqlPreview - Truncated SQL preview.
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* DatabaseConnectionDebugSnapshot type.
|
|
68
|
+
* @typedef {object} DatabaseConnectionDebugSnapshot
|
|
69
|
+
* @property {ActiveQueryDebugSnapshot | null} activeQuery - Currently running query, if any.
|
|
70
|
+
* @property {number | undefined} checkedOutAtUnixMs - Checkout start timestamp for active checkouts.
|
|
71
|
+
* @property {number | undefined} checkoutAgeMs - Active checkout age in milliseconds.
|
|
72
|
+
* @property {string | undefined} checkoutName - Human-readable checkout name.
|
|
73
|
+
* @property {string} driverClass - Driver class name.
|
|
74
|
+
* @property {number | undefined} idSeq - Pool checkout ID sequence.
|
|
75
|
+
* @property {number} openTransactions - Number of open transaction frames.
|
|
76
|
+
* @property {number} schemaCacheEntries - Number of cached schema metadata entries.
|
|
77
|
+
*/
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* ActiveQueryState type.
|
|
81
|
+
* @typedef {object} ActiveQueryState
|
|
82
|
+
* @property {string[]} annotations - Database annotations active when the query started.
|
|
83
|
+
* @property {string} logName - Query log name.
|
|
84
|
+
* @property {number} startedAtUnixMs - Query start timestamp.
|
|
85
|
+
* @property {string} sqlPreview - Truncated SQL preview.
|
|
86
|
+
*/
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* UpdateSqlArgsType type.
|
|
90
|
+
* @typedef {object}UpdateSqlArgsType
|
|
91
|
+
* @property {object} conditions - Conditions used to build the update WHERE clause.
|
|
92
|
+
* @property {object} data - Column/value pairs to update.
|
|
93
|
+
* @property {string} tableName - Table name to update.
|
|
94
|
+
*/
|
|
95
|
+
/**
|
|
96
|
+
* UpsertSqlArgsType type.
|
|
97
|
+
* @typedef {object}UpsertSqlArgsType
|
|
98
|
+
* @property {string[]} conflictColumns - Columns that define a conflict.
|
|
99
|
+
* @property {object} data - Column/value pairs to insert.
|
|
100
|
+
* @property {string} tableName - Table name to upsert into.
|
|
101
|
+
* @property {string[]} updateColumns - Columns to update on conflict.
|
|
102
|
+
*/
|
|
103
|
+
|
|
104
|
+
import BacktraceCleaner from "../../utils/backtrace-cleaner.js"
|
|
105
|
+
import { getDatabaseAnnotations } from "../annotations.js"
|
|
106
|
+
import Logger from "../../logger.js"
|
|
107
|
+
import Query from "../query/index.js"
|
|
108
|
+
import Handler from "../handler.js"
|
|
109
|
+
import Mutex from "epic-locks/build/mutex.js"
|
|
110
|
+
import strftime from "strftime"
|
|
111
|
+
import UUID from "pure-uuid"
|
|
112
|
+
import TableData from "../table-data/index.js"
|
|
113
|
+
import TableColumn from "../table-data/table-column.js"
|
|
114
|
+
import TableForeignKey from "../table-data/table-foreign-key.js"
|
|
115
|
+
import wait from "awaitery/build/wait.js"
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Runs now ms.
|
|
119
|
+
* @returns {number} - Current high-resolution-ish timestamp in milliseconds.
|
|
120
|
+
*/
|
|
121
|
+
function nowMs() {
|
|
122
|
+
if (globalThis.performance && typeof globalThis.performance.now == "function") {
|
|
123
|
+
return globalThis.performance.now()
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return Date.now()
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Runs format elapsed ms.
|
|
131
|
+
* @param {number} elapsedMs - Elapsed milliseconds.
|
|
132
|
+
* @returns {string} - Formatted elapsed milliseconds.
|
|
133
|
+
*/
|
|
134
|
+
function formatElapsedMs(elapsedMs) {
|
|
135
|
+
return `${Math.max(elapsedMs, 0).toFixed(1)}ms`
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export default class VelociousDatabaseDriversBase {
|
|
139
|
+
/**
|
|
140
|
+
* Id seq.
|
|
141
|
+
@type {number | undefined} */
|
|
142
|
+
idSeq = undefined
|
|
143
|
+
/**
|
|
144
|
+
* Narrows the runtime value to the documented type.
|
|
145
|
+
@type {Array<Array<() => void | Promise<void>>>} */
|
|
146
|
+
_afterCommitCallbackFrames
|
|
147
|
+
/**
|
|
148
|
+
* Narrows the runtime value to the documented type.
|
|
149
|
+
@type {Map<string, Promise<?>>} */
|
|
150
|
+
_schemaCache
|
|
151
|
+
/**
|
|
152
|
+
* Narrows the runtime value to the documented type.
|
|
153
|
+
@type {(() => void) | undefined} */
|
|
154
|
+
_schemaCacheInvalidator
|
|
155
|
+
/**
|
|
156
|
+
* Narrows the runtime value to the documented type.
|
|
157
|
+
@type {string | undefined} */
|
|
158
|
+
_connectionCheckoutName
|
|
159
|
+
/**
|
|
160
|
+
* Active query.
|
|
161
|
+
@type {ActiveQueryState | null} */
|
|
162
|
+
_activeQuery = null
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Runs constructor.
|
|
166
|
+
* @param {import("../../configuration-types.js").DatabaseConfigurationType} config - Configuration object.
|
|
167
|
+
* @param {import("../../configuration.js").default} configuration - Configuration instance.
|
|
168
|
+
*/
|
|
169
|
+
constructor(config, configuration) {
|
|
170
|
+
this._args = config
|
|
171
|
+
this.configuration = configuration
|
|
172
|
+
this.mutex = new Mutex() // Can be used to lock this instance for exclusive use
|
|
173
|
+
this.logger = new Logger(this)
|
|
174
|
+
this._afterCommitCallbackFrames = []
|
|
175
|
+
this._transactionsCount = 0
|
|
176
|
+
this._transactionsActionsMutex = new Mutex()
|
|
177
|
+
this._schemaCache = new Map()
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Runs add foreign key.
|
|
182
|
+
* @param {string} tableName - Table name.
|
|
183
|
+
* @param {string} columnName - Column name.
|
|
184
|
+
* @param {string} referencedTableName - Referenced table name.
|
|
185
|
+
* @param {string} referencedColumnName - Referenced column name.
|
|
186
|
+
* @param {object} args - Options object.
|
|
187
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
188
|
+
*/
|
|
189
|
+
async addForeignKey(tableName, columnName, referencedTableName, referencedColumnName, args) {
|
|
190
|
+
this._assertNotReadOnly()
|
|
191
|
+
const tableForeignKeyArgs = Object.assign(
|
|
192
|
+
{
|
|
193
|
+
columnName,
|
|
194
|
+
tableName,
|
|
195
|
+
referencedColumnName,
|
|
196
|
+
referencedTableName
|
|
197
|
+
},
|
|
198
|
+
args
|
|
199
|
+
)
|
|
200
|
+
const tableForeignKey = new TableForeignKey(tableForeignKeyArgs)
|
|
201
|
+
const tableData = new TableData(tableName)
|
|
202
|
+
|
|
203
|
+
tableData.addForeignKey(tableForeignKey)
|
|
204
|
+
|
|
205
|
+
const alterTableSQLs = await this.alterTableSQLs(tableData)
|
|
206
|
+
|
|
207
|
+
for (const alterTableSQL of alterTableSQLs) {
|
|
208
|
+
await this.query(alterTableSQL)
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Runs alter table sqls.
|
|
214
|
+
* @abstract
|
|
215
|
+
* @param {import("../table-data/index.js").default} _tableData - Table data.
|
|
216
|
+
* @returns {Promise<string[]>} - Resolves with SQL statements.
|
|
217
|
+
*/
|
|
218
|
+
alterTableSQLs(_tableData) {
|
|
219
|
+
throw new Error("alterTableSQLs not implemented")
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Runs connect.
|
|
224
|
+
* @abstract
|
|
225
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
226
|
+
*/
|
|
227
|
+
connect() {
|
|
228
|
+
throw new Error("'connect' not implemented")
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Optional close hook for database drivers.
|
|
233
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
234
|
+
*/
|
|
235
|
+
async close() {
|
|
236
|
+
// No-op by default
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Runs set connection checkout name.
|
|
241
|
+
* @param {string | undefined} name - Human-readable name for this active checkout.
|
|
242
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
243
|
+
*/
|
|
244
|
+
async setConnectionCheckoutName(name) {
|
|
245
|
+
this._connectionCheckoutName = name
|
|
246
|
+
this._connectionCheckedOutAtUnixMs = Date.now()
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Runs clear connection checkout name.
|
|
251
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
252
|
+
*/
|
|
253
|
+
async clearConnectionCheckoutName() {
|
|
254
|
+
this._connectionCheckoutName = undefined
|
|
255
|
+
this._connectionCheckedOutAtUnixMs = undefined
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Runs reconnect.
|
|
260
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
261
|
+
*/
|
|
262
|
+
async reconnect() {
|
|
263
|
+
this.clearSchemaCache()
|
|
264
|
+
await this.close()
|
|
265
|
+
await this.connect()
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Runs create database sql.
|
|
270
|
+
* @abstract
|
|
271
|
+
* @param {string} databaseName - Database name.
|
|
272
|
+
* @param {object} [args] - Options object.
|
|
273
|
+
* @param {boolean} [args.ifNotExists] - Whether if not exists.
|
|
274
|
+
* @param {string} [args.databaseCharset] - Database-default character set (driver-specific; mysql/mariadb).
|
|
275
|
+
* @param {string} [args.databaseCollation] - Database-default collation (driver-specific; mysql/mariadb).
|
|
276
|
+
* @returns {string[]} - SQL statements.
|
|
277
|
+
*/
|
|
278
|
+
createDatabaseSql(databaseName, args) { throw new Error("'createDatabaseSql' not implemented") } // eslint-disable-line no-unused-vars
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Runs drop database sql.
|
|
282
|
+
* @abstract
|
|
283
|
+
* @param {string} databaseName - Database name.
|
|
284
|
+
* @param {object} [args] - Options object.
|
|
285
|
+
* @param {boolean} [args.ifExists] - Whether if exists.
|
|
286
|
+
* @returns {string[]} - SQL statements.
|
|
287
|
+
*/
|
|
288
|
+
dropDatabaseSql(databaseName, args) { throw new Error("'dropDatabaseSql' not implemented") } // eslint-disable-line no-unused-vars
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Runs create index sqls.
|
|
292
|
+
* @abstract
|
|
293
|
+
* @param {CreateIndexSqlArgs} indexData - Index data.
|
|
294
|
+
* @returns {Promise<string[]>} - Resolves with SQL statements.
|
|
295
|
+
*/
|
|
296
|
+
async createIndexSQLs(indexData) { // eslint-disable-line no-unused-vars
|
|
297
|
+
throw new Error("'createIndexSQLs' not implemented")
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Runs create table.
|
|
302
|
+
* @param {import("../table-data/index.js").default} tableData - Table data.
|
|
303
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
304
|
+
*/
|
|
305
|
+
async createTable(tableData) {
|
|
306
|
+
this._assertNotReadOnly()
|
|
307
|
+
const sqls = await this.createTableSql(tableData)
|
|
308
|
+
|
|
309
|
+
for (const sql of sqls) {
|
|
310
|
+
await this.query(sql)
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Runs create table sql.
|
|
316
|
+
* @abstract
|
|
317
|
+
* @param {import("../table-data/index.js").default} tableData - Table data.
|
|
318
|
+
* @returns {Promise<string[]>} - Resolves with SQL statements.
|
|
319
|
+
*/
|
|
320
|
+
async createTableSql(tableData) { // eslint-disable-line no-unused-vars
|
|
321
|
+
throw new Error("'createTableSql' not implemented")
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Runs delete.
|
|
326
|
+
* @param {DeleteSqlArgsType} args - Options object.
|
|
327
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
328
|
+
*/
|
|
329
|
+
async delete(args) {
|
|
330
|
+
this._assertNotReadOnly()
|
|
331
|
+
const sql = this.deleteSql(args)
|
|
332
|
+
|
|
333
|
+
await this.query(sql)
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Runs delete sql.
|
|
338
|
+
* @abstract
|
|
339
|
+
* @param {DeleteSqlArgsType} args - Options object.
|
|
340
|
+
* @returns {string} - SQL string.
|
|
341
|
+
*/
|
|
342
|
+
deleteSql(args) { // eslint-disable-line no-unused-vars
|
|
343
|
+
throw new Error(`'deleteSql' not implemented`)
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Runs drop table.
|
|
348
|
+
* @param {string} tableName - Table name.
|
|
349
|
+
* @param {DropTableSqlArgsType} [args] - Options object.
|
|
350
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
351
|
+
*/
|
|
352
|
+
async dropTable(tableName, args) {
|
|
353
|
+
this._assertNotReadOnly()
|
|
354
|
+
const sqls = await this.dropTableSQLs(tableName, args)
|
|
355
|
+
|
|
356
|
+
for (const sql of sqls) {
|
|
357
|
+
await this.query(sql)
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Runs drop table sqls.
|
|
363
|
+
* @abstract
|
|
364
|
+
* @param {string} tableName - Table name.
|
|
365
|
+
* @param {DropTableSqlArgsType} [args] - Options object.
|
|
366
|
+
* @returns {Promise<string[]>} - Resolves with SQL statements.
|
|
367
|
+
*/
|
|
368
|
+
async dropTableSQLs(tableName, args) { // eslint-disable-line no-unused-vars
|
|
369
|
+
throw new Error("dropTableSQLs not implemented")
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Runs escape.
|
|
374
|
+
* @abstract
|
|
375
|
+
* @param {?} value - Value to use.
|
|
376
|
+
* @returns {?} - The escape.
|
|
377
|
+
*/
|
|
378
|
+
escape(value) { // eslint-disable-line no-unused-vars
|
|
379
|
+
throw new Error("'escape' not implemented")
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Runs get args.
|
|
384
|
+
* @returns {import("../../configuration-types.js").DatabaseConfigurationType} - The args.
|
|
385
|
+
*/
|
|
386
|
+
getArgs() {
|
|
387
|
+
return this._args
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Runs get configuration.
|
|
392
|
+
* @returns {import("../../configuration.js").default} - The configuration.
|
|
393
|
+
*/
|
|
394
|
+
getConfiguration() {
|
|
395
|
+
if (!this.configuration) throw new Error("No configuration set")
|
|
396
|
+
|
|
397
|
+
return this.configuration
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Runs get id seq.
|
|
402
|
+
* @returns {number | undefined} - The id seq.
|
|
403
|
+
*/
|
|
404
|
+
getIdSeq() {
|
|
405
|
+
return this.idSeq
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Clears cached schema metadata for this driver instance.
|
|
410
|
+
* @returns {void} - No return value.
|
|
411
|
+
*/
|
|
412
|
+
clearSchemaCache() {
|
|
413
|
+
if (this._schemaCacheInvalidator) {
|
|
414
|
+
this._schemaCacheInvalidator()
|
|
415
|
+
return
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
this._clearLocalSchemaCache()
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Clears only the metadata cached on this driver instance.
|
|
423
|
+
* @returns {void} - No return value.
|
|
424
|
+
*/
|
|
425
|
+
_clearLocalSchemaCache() {
|
|
426
|
+
this._schemaCache.clear()
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Runs set schema cache invalidator.
|
|
431
|
+
* @param {() => void} invalidator - Callback used to clear schema caches that share this driver pool.
|
|
432
|
+
* @returns {void} - No return value.
|
|
433
|
+
*/
|
|
434
|
+
setSchemaCacheInvalidator(invalidator) {
|
|
435
|
+
this._schemaCacheInvalidator = invalidator
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Runs schema cache enabled.
|
|
440
|
+
* @returns {boolean} - Whether schema metadata caching is enabled.
|
|
441
|
+
*/
|
|
442
|
+
_schemaCacheEnabled() {
|
|
443
|
+
return this.getArgs().schemaCache !== false
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Runs cached schema metadata.
|
|
448
|
+
* @template T
|
|
449
|
+
* @param {string} cacheKey - Schema cache key.
|
|
450
|
+
* @param {() => Promise<T>} callback - Cache miss callback.
|
|
451
|
+
* @returns {Promise<T>} - Resolves with the cached metadata.
|
|
452
|
+
*/
|
|
453
|
+
async _cachedSchemaMetadata(cacheKey, callback) {
|
|
454
|
+
if (!this._schemaCacheEnabled()) return await callback()
|
|
455
|
+
|
|
456
|
+
const existingPromise = this._schemaCache.get(cacheKey)
|
|
457
|
+
|
|
458
|
+
if (existingPromise) {
|
|
459
|
+
return /** Narrows the runtime value to the documented type. @type {T} */ (this._schemaCacheReturnValue(await existingPromise))
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
const promise = (async () => await callback())()
|
|
463
|
+
|
|
464
|
+
this._schemaCache.set(cacheKey, promise)
|
|
465
|
+
|
|
466
|
+
try {
|
|
467
|
+
return /** Narrows the runtime value to the documented type. @type {T} */ (this._schemaCacheReturnValue(await promise))
|
|
468
|
+
} catch (error) {
|
|
469
|
+
if (this._schemaCache.get(cacheKey) === promise) {
|
|
470
|
+
this._schemaCache.delete(cacheKey)
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
throw error
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Runs cached table schema metadata.
|
|
479
|
+
* @template T
|
|
480
|
+
* @param {string} tableName - Table name.
|
|
481
|
+
* @param {string} metadataName - Metadata name.
|
|
482
|
+
* @param {() => Promise<T>} callback - Cache miss callback.
|
|
483
|
+
* @returns {Promise<T>} - Resolves with the cached table metadata.
|
|
484
|
+
*/
|
|
485
|
+
async _cachedTableSchemaMetadata(tableName, metadataName, callback) {
|
|
486
|
+
return await this._cachedSchemaMetadata(`table:${tableName}:${metadataName}`, callback)
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Runs schema cache return value.
|
|
491
|
+
* @param {?} value - Cached value.
|
|
492
|
+
* @returns {?} - Value returned to callers.
|
|
493
|
+
*/
|
|
494
|
+
_schemaCacheReturnValue(value) {
|
|
495
|
+
if (Array.isArray(value)) return value.slice()
|
|
496
|
+
|
|
497
|
+
return value
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Runs get tables.
|
|
502
|
+
* @abstract
|
|
503
|
+
* @returns {Promise<Array<import("./base-table.js").default>>} - Resolves with the tables.
|
|
504
|
+
*/
|
|
505
|
+
getTables() {
|
|
506
|
+
throw new Error(`${this.constructor.name}#getTables not implemented`)
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Runs structure sql.
|
|
511
|
+
* @returns {Promise<string | null>} - Resolves with SQL string.
|
|
512
|
+
*/
|
|
513
|
+
async structureSql() {
|
|
514
|
+
return null
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* Runs get table by name.
|
|
519
|
+
* @param {string} name - Name.
|
|
520
|
+
* @param {object} [args] - Options object.
|
|
521
|
+
* @param {boolean} args.throwError - Whether throw error.
|
|
522
|
+
* @returns {Promise<import("./base-table.js").default | undefined>} - Resolves with the table by name.
|
|
523
|
+
*/
|
|
524
|
+
async getTableByName(name, args) {
|
|
525
|
+
const tables = await this.getTables()
|
|
526
|
+
const tableNames = []
|
|
527
|
+
let table
|
|
528
|
+
|
|
529
|
+
for (const candidate of tables) {
|
|
530
|
+
const candidateName = candidate.getName()
|
|
531
|
+
|
|
532
|
+
if (candidateName == name) {
|
|
533
|
+
table = candidate
|
|
534
|
+
break
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
tableNames.push(candidateName)
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
if (!table && args?.throwError !== false) {
|
|
541
|
+
throw new Error(this._missingTableErrorMessage(name, tableNames))
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
return table
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* Runs missing table error message.
|
|
549
|
+
* @param {string} name - Table name.
|
|
550
|
+
* @param {string[]} tableNames - Available table names.
|
|
551
|
+
* @returns {string} - Error message.
|
|
552
|
+
*/
|
|
553
|
+
_missingTableErrorMessage(name, tableNames) {
|
|
554
|
+
const environment = this.getConfiguration().getEnvironment()
|
|
555
|
+
const args = this.getArgs()
|
|
556
|
+
const databaseName = args?.database || args?.name || args?.useDatabase || "unknown"
|
|
557
|
+
|
|
558
|
+
return `Couldn't find a table by that name "${name}" in: ${tableNames.join(", ")} (environment: ${environment}, database: ${databaseName})`
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Runs get table by name or fail.
|
|
563
|
+
* @param {string} name - Name.
|
|
564
|
+
* @returns {Promise<import("./base-table.js").default>} - Resolves with the table by name or fail.
|
|
565
|
+
*/
|
|
566
|
+
async getTableByNameOrFail(name) {
|
|
567
|
+
return /** Narrows the runtime value to the documented type. @type {import("./base-table.js").default} */ (await this.getTableByName(name, {throwError: true}))
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* Runs get type.
|
|
572
|
+
* @abstract
|
|
573
|
+
* @returns {string} - The type.
|
|
574
|
+
*/
|
|
575
|
+
getType() {
|
|
576
|
+
throw new Error("'type' not implemented")
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* Runs insert.
|
|
581
|
+
* @param {InsertSqlArgsType} args - Options object.
|
|
582
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
583
|
+
*/
|
|
584
|
+
async insert(args) {
|
|
585
|
+
this._assertNotReadOnly()
|
|
586
|
+
const sql = this.insertSql(args)
|
|
587
|
+
|
|
588
|
+
await this.query(sql)
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Runs insert multiple.
|
|
593
|
+
* @param {string} tableName - Table name.
|
|
594
|
+
* @param {Array<string>} columns - Column names.
|
|
595
|
+
* @param {Array<Array<?>>} rows - Rows to insert.
|
|
596
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
597
|
+
*/
|
|
598
|
+
async insertMultiple(tableName, columns, rows) {
|
|
599
|
+
this._assertNotReadOnly()
|
|
600
|
+
|
|
601
|
+
const sql = this.insertSql({columns, tableName, rows})
|
|
602
|
+
|
|
603
|
+
await this.query(sql)
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Runs insert sql.
|
|
608
|
+
* @abstract
|
|
609
|
+
* @param {InsertSqlArgsType} args - Options object.
|
|
610
|
+
* @returns {string} - SQL string.
|
|
611
|
+
*/
|
|
612
|
+
insertSql(args) { // eslint-disable-line no-unused-vars
|
|
613
|
+
throw new Error("'insertSql' not implemented")
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Runs upsert.
|
|
618
|
+
* @param {UpsertSqlArgsType} args - Options object.
|
|
619
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
620
|
+
*/
|
|
621
|
+
async upsert(args) {
|
|
622
|
+
this._assertNotReadOnly()
|
|
623
|
+
const sql = this.upsertSql(args)
|
|
624
|
+
|
|
625
|
+
await this.query(sql)
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Runs last insert id.
|
|
630
|
+
* @abstract
|
|
631
|
+
* @returns {Promise<number>} - Resolves with the last insert id.
|
|
632
|
+
*/
|
|
633
|
+
lastInsertID() {
|
|
634
|
+
throw new Error(`${this.constructor.name}#lastInsertID not implemented`)
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* Runs convert value.
|
|
639
|
+
* @param {?} value - Value to use.
|
|
640
|
+
* @returns {?} - The convert value.
|
|
641
|
+
*/
|
|
642
|
+
_convertValue(value) {
|
|
643
|
+
if (typeof value === "boolean") {
|
|
644
|
+
return value ? 1 : 0
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
if (value instanceof Date) {
|
|
648
|
+
return strftime("%F %T.%L", value)
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// JSON-encode plain objects/arrays so they land in JSON/text columns as valid
|
|
652
|
+
// JSON. Without this, drivers like mysql's escape() turn an object into
|
|
653
|
+
// `key` = value assignment pairs (its `SET ?` form), producing invalid SQL in
|
|
654
|
+
// a value position. Only PLAIN objects and arrays are encoded — class
|
|
655
|
+
// instances (e.g. model records, which are circular via _changes) and Buffers
|
|
656
|
+
// pass through untouched, since JSON.stringify on a record throws on its
|
|
657
|
+
// circular structure and a record is never a valid column value to serialize.
|
|
658
|
+
if (this._isJsonEncodableValue(value)) {
|
|
659
|
+
return JSON.stringify(value)
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
return value
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* Whether a value is a plain object or array that should be JSON-encoded for a
|
|
667
|
+
* JSON/text column. Excludes Buffers and class instances (e.g. model records).
|
|
668
|
+
* @param {?} value - Value to test.
|
|
669
|
+
* @returns {boolean} - Whether to JSON-encode the value.
|
|
670
|
+
*/
|
|
671
|
+
_isJsonEncodableValue(value) {
|
|
672
|
+
if (value === null || typeof value !== "object") return false
|
|
673
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) return false
|
|
674
|
+
if (Array.isArray(value)) return true
|
|
675
|
+
|
|
676
|
+
const prototype = Object.getPrototypeOf(value)
|
|
677
|
+
|
|
678
|
+
return prototype === Object.prototype || prototype === null
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* Runs options.
|
|
683
|
+
* @abstract
|
|
684
|
+
* @returns {import("../query-parser/options.js").default} - The options options.
|
|
685
|
+
*/
|
|
686
|
+
options() {
|
|
687
|
+
throw new Error("'options' not implemented.")
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* Runs quote.
|
|
692
|
+
* @param {?} value - Value to use.
|
|
693
|
+
* @returns {number | string} - The quote.
|
|
694
|
+
*/
|
|
695
|
+
quote(value) {
|
|
696
|
+
if (typeof value == "number") return value
|
|
697
|
+
|
|
698
|
+
const escapedValue = this.escape(value)
|
|
699
|
+
const result = `"${escapedValue}"`
|
|
700
|
+
|
|
701
|
+
return result
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* Runs quote column.
|
|
706
|
+
* @param {string} columnName - Column name.
|
|
707
|
+
* @returns {string} - The quote column.
|
|
708
|
+
*/
|
|
709
|
+
quoteColumn(columnName) {
|
|
710
|
+
return this.options().quoteColumnName(columnName)
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* Runs quote index.
|
|
715
|
+
* @param {string} columnName - Column name.
|
|
716
|
+
* @returns {string} - The quote index.
|
|
717
|
+
*/
|
|
718
|
+
quoteIndex(columnName) {
|
|
719
|
+
return this.options().quoteIndexName(columnName)
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* Runs quote table.
|
|
724
|
+
* @param {string} tableName - Table name.
|
|
725
|
+
* @returns {string} - The quote table.
|
|
726
|
+
*/
|
|
727
|
+
quoteTable(tableName) {
|
|
728
|
+
return this.options().quoteTableName(tableName)
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* Runs new query.
|
|
733
|
+
* @returns {Query} - The new query.
|
|
734
|
+
*/
|
|
735
|
+
newQuery() {
|
|
736
|
+
const handler = new Handler()
|
|
737
|
+
|
|
738
|
+
return new Query({
|
|
739
|
+
driver: this,
|
|
740
|
+
handler
|
|
741
|
+
})
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* Runs select.
|
|
746
|
+
* @param {string} tableName - Table name.
|
|
747
|
+
* @returns {Promise<QueryResultType>} - Resolves with the select.
|
|
748
|
+
*/
|
|
749
|
+
async select(tableName) {
|
|
750
|
+
const query = this.newQuery()
|
|
751
|
+
|
|
752
|
+
const sql = query
|
|
753
|
+
.from(tableName)
|
|
754
|
+
.toSql()
|
|
755
|
+
|
|
756
|
+
return await this.query(sql)
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Runs set id seq.
|
|
761
|
+
* @param {number | undefined} newIdSeq - New id seq.
|
|
762
|
+
* @returns {void} - No return value.
|
|
763
|
+
*/
|
|
764
|
+
setIdSeq(newIdSeq) {
|
|
765
|
+
this.idSeq = newIdSeq
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
/**
|
|
769
|
+
* Runs should set auto increment when primary key.
|
|
770
|
+
* @abstract
|
|
771
|
+
* @returns {boolean} - Whether set auto increment when primary key.
|
|
772
|
+
*/
|
|
773
|
+
shouldSetAutoIncrementWhenPrimaryKey() {
|
|
774
|
+
throw new Error(`'shouldSetAutoIncrementWhenPrimaryKey' not implemented`)
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
/**
|
|
778
|
+
* Runs supports default primary key uuid.
|
|
779
|
+
* @returns {boolean} - Whether supports default primary key uuid.
|
|
780
|
+
*/
|
|
781
|
+
supportsDefaultPrimaryKeyUUID() { return false }
|
|
782
|
+
|
|
783
|
+
/**
|
|
784
|
+
* Runs supports insert into returning.
|
|
785
|
+
* @abstract
|
|
786
|
+
* @returns {boolean} - Whether supports insert into returning.
|
|
787
|
+
*/
|
|
788
|
+
supportsInsertIntoReturning() { return false }
|
|
789
|
+
|
|
790
|
+
/**
|
|
791
|
+
* Runs table exists.
|
|
792
|
+
* @param {string} tableName - Table name.
|
|
793
|
+
* @returns {Promise<boolean>} - Resolves with Whether table exists.
|
|
794
|
+
*/
|
|
795
|
+
async tableExists(tableName) {
|
|
796
|
+
const tables = await this.getTables()
|
|
797
|
+
const table = tables.find((table) => table.getName() == tableName)
|
|
798
|
+
|
|
799
|
+
if (table) return true
|
|
800
|
+
|
|
801
|
+
return false
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* Runs transaction.
|
|
806
|
+
* @param {() => Promise<void>} callback - Callback function.
|
|
807
|
+
* @returns {Promise<?>} - Resolves with the transaction.
|
|
808
|
+
*/
|
|
809
|
+
async transaction(callback) {
|
|
810
|
+
const savePointName = this.generateSavePointName()
|
|
811
|
+
/**
|
|
812
|
+
* Callback frame.
|
|
813
|
+
@type {Array<() => void | Promise<void>>} */
|
|
814
|
+
const callbackFrame = []
|
|
815
|
+
let transactionStarted = false
|
|
816
|
+
let savePointStarted = false
|
|
817
|
+
|
|
818
|
+
this._afterCommitCallbackFrames.push(callbackFrame)
|
|
819
|
+
|
|
820
|
+
if (this._transactionsCount == 0) {
|
|
821
|
+
this.logger.debug("Start transaction")
|
|
822
|
+
await this.startTransaction()
|
|
823
|
+
transactionStarted = true
|
|
824
|
+
} else {
|
|
825
|
+
this.logger.debug("Start savepoint", savePointName)
|
|
826
|
+
await this.startSavePoint(savePointName)
|
|
827
|
+
savePointStarted = true
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
let result
|
|
831
|
+
|
|
832
|
+
try {
|
|
833
|
+
result = await callback()
|
|
834
|
+
|
|
835
|
+
if (savePointStarted) {
|
|
836
|
+
this.logger.debug("Release savepoint", savePointName)
|
|
837
|
+
await this.releaseSavePoint(savePointName)
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
if (transactionStarted) {
|
|
841
|
+
this.logger.debug("Commit transaction")
|
|
842
|
+
await this.commitTransaction()
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
await this._commitAfterCommitCallbackFrame()
|
|
846
|
+
} catch (error) {
|
|
847
|
+
if (error instanceof Error) {
|
|
848
|
+
this.logger.debug("Transaction error", error.message)
|
|
849
|
+
} else {
|
|
850
|
+
this.logger.debug("Transaction error", error)
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
let transactionRolledBack = false
|
|
854
|
+
|
|
855
|
+
if (savePointStarted) {
|
|
856
|
+
this.logger.debug("Rollback savepoint", savePointName)
|
|
857
|
+
try {
|
|
858
|
+
await this.rollbackSavePoint(savePointName)
|
|
859
|
+
} catch (savePointError) {
|
|
860
|
+
const message = savePointError instanceof Error ? savePointError.message : `${savePointError}`
|
|
861
|
+
|
|
862
|
+
// MySQL sometimes drops savepoints unexpectedly; fall back to rolling back the full transaction
|
|
863
|
+
if (message.includes("SAVEPOINT") || message.includes("ER_SP_DOES_NOT_EXIST")) {
|
|
864
|
+
this.logger.debug("Savepoint rollback failed; rolling back entire transaction instead")
|
|
865
|
+
await this.rollbackTransaction()
|
|
866
|
+
transactionRolledBack = true
|
|
867
|
+
} else {
|
|
868
|
+
throw savePointError
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
if (transactionStarted && !transactionRolledBack) {
|
|
874
|
+
this.logger.debug("Rollback transaction")
|
|
875
|
+
await this.rollbackTransaction()
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
this._afterCommitCallbackFrames.pop()
|
|
879
|
+
|
|
880
|
+
throw error
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
return result
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
/**
|
|
887
|
+
* Runs a callback after the surrounding transaction commits.
|
|
888
|
+
* If no transaction is active, the callback runs immediately.
|
|
889
|
+
* @param {() => void | Promise<void>} callback - Callback.
|
|
890
|
+
* @returns {Promise<void>} - Resolves when the callback has been registered or run.
|
|
891
|
+
*/
|
|
892
|
+
async afterCommit(callback) {
|
|
893
|
+
const currentFrame = this._afterCommitCallbackFrames[this._afterCommitCallbackFrames.length - 1]
|
|
894
|
+
|
|
895
|
+
if (!currentFrame) {
|
|
896
|
+
await callback()
|
|
897
|
+
return
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
currentFrame.push(callback)
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
/**
|
|
904
|
+
* Runs start transaction.
|
|
905
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
906
|
+
*/
|
|
907
|
+
async startTransaction() {
|
|
908
|
+
await this._transactionsActionsMutex.sync(async () => {
|
|
909
|
+
await this._startTransactionAction()
|
|
910
|
+
this._transactionsCount++
|
|
911
|
+
})
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
/**
|
|
915
|
+
* Runs start transaction action.
|
|
916
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
917
|
+
*/
|
|
918
|
+
async _startTransactionAction() {
|
|
919
|
+
await this.query("BEGIN TRANSACTION")
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
/**
|
|
923
|
+
* Runs commit transaction.
|
|
924
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
925
|
+
*/
|
|
926
|
+
async commitTransaction() {
|
|
927
|
+
await this._transactionsActionsMutex.sync(async () => {
|
|
928
|
+
await this._commitTransactionAction()
|
|
929
|
+
this._transactionsCount--
|
|
930
|
+
})
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
/**
|
|
934
|
+
* Runs commit transaction action.
|
|
935
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
936
|
+
*/
|
|
937
|
+
async _commitTransactionAction() {
|
|
938
|
+
await this.query("COMMIT")
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
/**
|
|
942
|
+
* Merges committed callbacks into the parent transaction frame or runs them when the outermost commit completes.
|
|
943
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
944
|
+
*/
|
|
945
|
+
async _commitAfterCommitCallbackFrame() {
|
|
946
|
+
const committedCallbacks = this._afterCommitCallbackFrames.pop()
|
|
947
|
+
|
|
948
|
+
if (!committedCallbacks || committedCallbacks.length === 0) return
|
|
949
|
+
|
|
950
|
+
const parentFrame = this._afterCommitCallbackFrames[this._afterCommitCallbackFrames.length - 1]
|
|
951
|
+
|
|
952
|
+
if (parentFrame) {
|
|
953
|
+
parentFrame.push(...committedCallbacks)
|
|
954
|
+
return
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
for (const callback of committedCallbacks) {
|
|
958
|
+
await callback()
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
/**
|
|
963
|
+
* Runs query.
|
|
964
|
+
* @param {string} sql - SQL string.
|
|
965
|
+
* @param {QueryOptions} [options] - Query options.
|
|
966
|
+
* @returns {Promise<QueryResultType>} - Resolves with the query.
|
|
967
|
+
*/
|
|
968
|
+
async query(sql, options = {}) {
|
|
969
|
+
this._assertWritableQuery(sql)
|
|
970
|
+
|
|
971
|
+
let tries = 0
|
|
972
|
+
const maxTries = 5
|
|
973
|
+
const requestTiming = this.configuration.getCurrentRequestTiming()
|
|
974
|
+
const logQuery = options.logQuery ?? this._queryLoggingEnabled()
|
|
975
|
+
const sourceStack = logQuery ? (options.sourceStack || Error().stack) : undefined
|
|
976
|
+
const querySql = this._querySqlWithProcessListComment(sql, options)
|
|
977
|
+
|
|
978
|
+
while (tries < maxTries) {
|
|
979
|
+
tries++
|
|
980
|
+
|
|
981
|
+
try {
|
|
982
|
+
return await this._queryActualWithLogging({originalSql: sql, querySql}, {...options, logQuery, sourceStack}, requestTiming, tries)
|
|
983
|
+
} catch (error) {
|
|
984
|
+
if (!(error instanceof Error)) throw error
|
|
985
|
+
|
|
986
|
+
const retryInfo = this.retryableDatabaseError(error)
|
|
987
|
+
|
|
988
|
+
if (tries < maxTries && retryInfo.retry) {
|
|
989
|
+
if (retryInfo.reconnect) {
|
|
990
|
+
if (this._transactionsCount > 0) {
|
|
991
|
+
throw new Error(`Cannot reconnect while a transaction is active (${this._transactionsCount}). Original error: ${error.message}`, {cause: error})
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
await this.reconnect()
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
const waitMs = typeof retryInfo.waitMs === "number" && Number.isFinite(retryInfo.waitMs) ? retryInfo.waitMs : 100
|
|
998
|
+
|
|
999
|
+
if (waitMs > 0) await wait(waitMs)
|
|
1000
|
+
this.logger.warn(`Retrying query because failed with: ${error.stack}`)
|
|
1001
|
+
// Retry
|
|
1002
|
+
} else {
|
|
1003
|
+
throw error
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
throw new Error("'query' unexpected came here")
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
/**
|
|
1012
|
+
* Runs query actual with logging.
|
|
1013
|
+
* @param {object} args - Options object.
|
|
1014
|
+
* @param {string} args.originalSql - Original SQL string before process-list comments.
|
|
1015
|
+
* @param {string} args.querySql - SQL string sent to the database.
|
|
1016
|
+
* @param {QueryOptions} options - Query options.
|
|
1017
|
+
* @param {import("../../http-server/client/request-timing.js").default | undefined} requestTiming - Request timing.
|
|
1018
|
+
* @param {number} tries - Query attempt count.
|
|
1019
|
+
* @returns {Promise<QueryResultType>} - Resolves with the query.
|
|
1020
|
+
*/
|
|
1021
|
+
async _queryActualWithLogging({originalSql, querySql}, options, requestTiming, tries) {
|
|
1022
|
+
const startedAtMs = nowMs()
|
|
1023
|
+
const previousActiveQuery = this._activeQuery
|
|
1024
|
+
this._activeQuery = {
|
|
1025
|
+
annotations: getDatabaseAnnotations(),
|
|
1026
|
+
logName: options.logName || "SQL",
|
|
1027
|
+
sqlPreview: this._debugSqlPreview(originalSql),
|
|
1028
|
+
startedAtUnixMs: Date.now()
|
|
1029
|
+
}
|
|
1030
|
+
let result
|
|
1031
|
+
|
|
1032
|
+
try {
|
|
1033
|
+
if (requestTiming && tries === 1) {
|
|
1034
|
+
result = await requestTiming.measureDbQuery(async () => await this._queryActual(querySql))
|
|
1035
|
+
} else if (requestTiming) {
|
|
1036
|
+
result = await requestTiming.measure("db", async () => await this._queryActual(querySql))
|
|
1037
|
+
} else {
|
|
1038
|
+
result = await this._queryActual(querySql)
|
|
1039
|
+
}
|
|
1040
|
+
} finally {
|
|
1041
|
+
this._activeQuery = previousActiveQuery
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
const elapsedMs = nowMs() - startedAtMs
|
|
1045
|
+
|
|
1046
|
+
if (options.logQuery !== false) {
|
|
1047
|
+
await this._logQuery({
|
|
1048
|
+
elapsedMs,
|
|
1049
|
+
logName: options.logName || "SQL",
|
|
1050
|
+
sourceStack: options.sourceStack,
|
|
1051
|
+
sql: originalSql
|
|
1052
|
+
})
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
if (this._schemaCacheInvalidatingSql(originalSql)) {
|
|
1056
|
+
this.clearSchemaCache()
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
return result
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
/**
|
|
1063
|
+
* Runs get debug snapshot.
|
|
1064
|
+
* @returns {DatabaseConnectionDebugSnapshot} - Diagnostic snapshot for this connection.
|
|
1065
|
+
*/
|
|
1066
|
+
getDebugSnapshot() {
|
|
1067
|
+
const now = Date.now()
|
|
1068
|
+
const activeQuery = this._activeQuery
|
|
1069
|
+
|
|
1070
|
+
return {
|
|
1071
|
+
activeQuery: activeQuery ? {...activeQuery, runningMs: Math.max(0, now - activeQuery.startedAtUnixMs)} : null,
|
|
1072
|
+
checkoutAgeMs: this._connectionCheckedOutAtUnixMs ? Math.max(0, now - this._connectionCheckedOutAtUnixMs) : undefined,
|
|
1073
|
+
checkedOutAtUnixMs: this._connectionCheckedOutAtUnixMs,
|
|
1074
|
+
checkoutName: this._connectionCheckoutName,
|
|
1075
|
+
driverClass: this.constructor.name,
|
|
1076
|
+
idSeq: this.idSeq,
|
|
1077
|
+
openTransactions: this._transactionsCount,
|
|
1078
|
+
schemaCacheEntries: this._schemaCache.size
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
/**
|
|
1083
|
+
* Runs debug sql preview.
|
|
1084
|
+
* @param {string} sql - SQL to preview.
|
|
1085
|
+
* @returns {string} - Normalized truncated SQL preview for diagnostics.
|
|
1086
|
+
*/
|
|
1087
|
+
_debugSqlPreview(sql) {
|
|
1088
|
+
return sql
|
|
1089
|
+
.replace(/\s+/g, " ")
|
|
1090
|
+
.trim()
|
|
1091
|
+
.slice(0, 500)
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
/**
|
|
1095
|
+
* Runs query sql with process list comment.
|
|
1096
|
+
* @param {string} sql - SQL string.
|
|
1097
|
+
* @param {QueryOptions} options - Query options.
|
|
1098
|
+
* @returns {string} - SQL string with a leading process-list comment when annotations exist.
|
|
1099
|
+
*/
|
|
1100
|
+
_querySqlWithProcessListComment(sql, options) {
|
|
1101
|
+
if (options.processListComment === false) return sql
|
|
1102
|
+
|
|
1103
|
+
const parts = []
|
|
1104
|
+
|
|
1105
|
+
if (this._connectionCheckoutName) {
|
|
1106
|
+
parts.push(`checkout="${this._processListCommentValue(this._connectionCheckoutName)}"`)
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
const annotations = getDatabaseAnnotations()
|
|
1110
|
+
|
|
1111
|
+
if (annotations.length > 0) {
|
|
1112
|
+
parts.push(`annotations="${this._processListCommentValue(annotations.join(" > "))}"`)
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
if (parts.length === 0) return sql
|
|
1116
|
+
|
|
1117
|
+
return `/* velocious ${parts.join(" ")} */ ${sql}`
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
/**
|
|
1121
|
+
* Runs process list comment value.
|
|
1122
|
+
* @param {string} value - Raw process-list comment value.
|
|
1123
|
+
* @returns {string} - Sanitized process-list comment value.
|
|
1124
|
+
*/
|
|
1125
|
+
_processListCommentValue(value) {
|
|
1126
|
+
let sanitized = ""
|
|
1127
|
+
|
|
1128
|
+
for (const character of value) {
|
|
1129
|
+
const codePoint = character.codePointAt(0)
|
|
1130
|
+
|
|
1131
|
+
sanitized += codePoint !== undefined && (codePoint < 32 || codePoint === 127) ? " " : character
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
return sanitized
|
|
1135
|
+
.replace(/\*\//g, "* /")
|
|
1136
|
+
.replace(/\s+/g, " ")
|
|
1137
|
+
.trim()
|
|
1138
|
+
.slice(0, 200)
|
|
1139
|
+
.replace(/"/g, "'")
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
/**
|
|
1143
|
+
* Runs schema cache invalidating sql.
|
|
1144
|
+
* @param {string} sql - SQL string.
|
|
1145
|
+
* @returns {boolean} - Whether the SQL should invalidate schema metadata.
|
|
1146
|
+
*/
|
|
1147
|
+
_schemaCacheInvalidatingSql(sql) {
|
|
1148
|
+
const normalized = sql
|
|
1149
|
+
.trim()
|
|
1150
|
+
.replace(/^\ufeff/, "")
|
|
1151
|
+
.replace(/\/\*[\s\S]*?\*\//g, " ")
|
|
1152
|
+
.replace(/--[^\n]*(\n|$)/g, " ")
|
|
1153
|
+
.replace(/\s+/g, " ")
|
|
1154
|
+
.toLowerCase()
|
|
1155
|
+
|
|
1156
|
+
if (!normalized) return false
|
|
1157
|
+
if (/^(create|alter|drop|rename)\b/.test(normalized)) return true
|
|
1158
|
+
if (/^comment\s+on\b/.test(normalized)) return true
|
|
1159
|
+
if (/^exec(?:ute)?\s+sp_rename\b/.test(normalized)) return true
|
|
1160
|
+
if (/^if\b[\s\S]*\bbegin\s+(create|alter|drop|rename)\b/.test(normalized)) return true
|
|
1161
|
+
|
|
1162
|
+
return false
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
/**
|
|
1166
|
+
* Runs query logging enabled.
|
|
1167
|
+
* @returns {boolean} - Whether query logging is enabled for this driver.
|
|
1168
|
+
*/
|
|
1169
|
+
_queryLoggingEnabled() {
|
|
1170
|
+
if (typeof this.configuration?.getQueryLoggingEnabled !== "function") return true
|
|
1171
|
+
if (!this.configuration.getQueryLoggingEnabled()) return false
|
|
1172
|
+
|
|
1173
|
+
const logger = new Logger("SQL", {configuration: this.configuration})
|
|
1174
|
+
|
|
1175
|
+
return logger.isLevelEnabled("info")
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
/**
|
|
1179
|
+
* Runs log query.
|
|
1180
|
+
* @param {object} args - Options object.
|
|
1181
|
+
* @param {number} args.elapsedMs - Elapsed milliseconds.
|
|
1182
|
+
* @param {string} args.logName - Query log subject.
|
|
1183
|
+
* @param {string | undefined} args.sourceStack - Source stack.
|
|
1184
|
+
* @param {string} args.sql - SQL string.
|
|
1185
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
1186
|
+
*/
|
|
1187
|
+
async _logQuery({elapsedMs, logName, sourceStack, sql}) {
|
|
1188
|
+
const logger = new Logger(logName, {configuration: this.configuration})
|
|
1189
|
+
const sourceLine = this._querySourceLine(sourceStack)
|
|
1190
|
+
const message = sourceLine
|
|
1191
|
+
? `(${formatElapsedMs(elapsedMs)}) ${sql}\n ↳ ${sourceLine}`
|
|
1192
|
+
: `(${formatElapsedMs(elapsedMs)}) ${sql}`
|
|
1193
|
+
|
|
1194
|
+
await logger.info(message)
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
/**
|
|
1198
|
+
* Runs query source line.
|
|
1199
|
+
* @param {string | undefined} sourceStack - Source stack.
|
|
1200
|
+
* @returns {string | undefined} - Source line when an application frame is available.
|
|
1201
|
+
*/
|
|
1202
|
+
_querySourceLine(sourceStack) {
|
|
1203
|
+
if (!sourceStack) return undefined
|
|
1204
|
+
|
|
1205
|
+
const applicationDirectory = typeof this.configuration?.getDirectoryIfAvailable === "function"
|
|
1206
|
+
? this.configuration.getDirectoryIfAvailable()
|
|
1207
|
+
: this.configuration?.getDirectory?.()
|
|
1208
|
+
|
|
1209
|
+
if (!applicationDirectory) return undefined
|
|
1210
|
+
|
|
1211
|
+
const error = new Error("Query source")
|
|
1212
|
+
|
|
1213
|
+
error.stack = sourceStack
|
|
1214
|
+
|
|
1215
|
+
return BacktraceCleaner.getApplicationSourceLine(error, {
|
|
1216
|
+
applicationDirectory,
|
|
1217
|
+
frameworkSourceDirectory: this.configuration.getEnvironmentHandler().getFrameworkSourceDirectory()
|
|
1218
|
+
})
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
/**
|
|
1222
|
+
* Runs query actual.
|
|
1223
|
+
* @abstract
|
|
1224
|
+
* @param {string} sql - SQL string.
|
|
1225
|
+
* @returns {Promise<QueryResultType>} - Resolves with the query actual.
|
|
1226
|
+
*/
|
|
1227
|
+
_queryActual(sql) { // eslint-disable-line no-unused-vars
|
|
1228
|
+
throw new Error(`queryActual not implemented`)
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
/**
|
|
1232
|
+
* Runs query to sql.
|
|
1233
|
+
* @abstract
|
|
1234
|
+
* @param {Query} _query - Query instance.
|
|
1235
|
+
* @returns {string} - SQL string.
|
|
1236
|
+
*/
|
|
1237
|
+
queryToSql(_query) { throw new Error("queryToSql not implemented") }
|
|
1238
|
+
|
|
1239
|
+
/**
|
|
1240
|
+
* Runs retryable database error.
|
|
1241
|
+
* @param {Error} _error - Error instance.
|
|
1242
|
+
* @returns {RetryableDatabaseErrorResult} - Retry info.
|
|
1243
|
+
*/
|
|
1244
|
+
retryableDatabaseError(_error) {
|
|
1245
|
+
return {retry: false, reconnect: false}
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
/**
|
|
1249
|
+
* Runs assert writable query.
|
|
1250
|
+
* @param {string} sql - SQL string.
|
|
1251
|
+
* @returns {void} - No return value.
|
|
1252
|
+
*/
|
|
1253
|
+
_assertWritableQuery(sql) {
|
|
1254
|
+
if (!this.isReadOnly()) return
|
|
1255
|
+
if (!this._sqlLooksLikeWrite(sql)) return
|
|
1256
|
+
|
|
1257
|
+
throw new Error("Database is read-only")
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
/**
|
|
1261
|
+
* Runs assert not read only.
|
|
1262
|
+
* @returns {void} - No return value.
|
|
1263
|
+
*/
|
|
1264
|
+
_assertNotReadOnly() {
|
|
1265
|
+
if (this.isReadOnly()) {
|
|
1266
|
+
throw new Error("Database is read-only")
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
/**
|
|
1271
|
+
* Runs sql looks like write.
|
|
1272
|
+
* @param {string} sql - SQL string.
|
|
1273
|
+
* @returns {boolean} - SQL representation.
|
|
1274
|
+
*/
|
|
1275
|
+
_sqlLooksLikeWrite(sql) {
|
|
1276
|
+
const normalized = sql.trim().toLowerCase()
|
|
1277
|
+
|
|
1278
|
+
if (!normalized) return false
|
|
1279
|
+
|
|
1280
|
+
if (
|
|
1281
|
+
normalized.startsWith("select") ||
|
|
1282
|
+
normalized.startsWith("show") ||
|
|
1283
|
+
normalized.startsWith("pragma") ||
|
|
1284
|
+
normalized.startsWith("explain") ||
|
|
1285
|
+
normalized.startsWith("describe")
|
|
1286
|
+
) {
|
|
1287
|
+
return false
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
if (normalized.startsWith("with")) {
|
|
1291
|
+
const withMatch = normalized.match(/^\s*with[\s\S]+?\)\s*(select|insert|update|delete|merge|replace)\b/)
|
|
1292
|
+
|
|
1293
|
+
if (withMatch) {
|
|
1294
|
+
return withMatch[1] !== "select"
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
return false
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
const keywordMatch = normalized.match(/^\s*(\w+)/)
|
|
1301
|
+
const keyword = keywordMatch ? keywordMatch[1] : ""
|
|
1302
|
+
|
|
1303
|
+
return [
|
|
1304
|
+
"insert",
|
|
1305
|
+
"update",
|
|
1306
|
+
"delete",
|
|
1307
|
+
"create",
|
|
1308
|
+
"alter",
|
|
1309
|
+
"drop",
|
|
1310
|
+
"truncate",
|
|
1311
|
+
"merge",
|
|
1312
|
+
"replace"
|
|
1313
|
+
].includes(keyword)
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
/**
|
|
1317
|
+
* Runs is read only.
|
|
1318
|
+
* @returns {boolean} - Whether read only.
|
|
1319
|
+
*/
|
|
1320
|
+
isReadOnly() {
|
|
1321
|
+
return Boolean(this.getArgs().readOnly)
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
/**
|
|
1325
|
+
* Runs rollback transaction.
|
|
1326
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
1327
|
+
*/
|
|
1328
|
+
async rollbackTransaction() {
|
|
1329
|
+
await this._transactionsActionsMutex.sync(async () => {
|
|
1330
|
+
try {
|
|
1331
|
+
await this._rollbackTransactionAction()
|
|
1332
|
+
} finally {
|
|
1333
|
+
this._transactionsCount--
|
|
1334
|
+
|
|
1335
|
+
// A rolled-back transaction may have reverted DDL (e.g. a CREATE TABLE
|
|
1336
|
+
// run lazily inside the transaction), so any cached schema metadata is
|
|
1337
|
+
// now stale and must be invalidated. Without this, a later tableExists()
|
|
1338
|
+
// check can report a table that the rollback already removed, so callers
|
|
1339
|
+
// skip recreating it and then fail with "no such table".
|
|
1340
|
+
this.clearSchemaCache()
|
|
1341
|
+
}
|
|
1342
|
+
})
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
/**
|
|
1346
|
+
* Runs rollback transaction action.
|
|
1347
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
1348
|
+
*/
|
|
1349
|
+
async _rollbackTransactionAction() {
|
|
1350
|
+
await this.query("ROLLBACK")
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
/**
|
|
1354
|
+
* Runs generate save point name.
|
|
1355
|
+
* @returns {string} - The generate save point name.
|
|
1356
|
+
*/
|
|
1357
|
+
generateSavePointName() {
|
|
1358
|
+
return `sp${new UUID(4).format().replaceAll("-", "")}`
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
/**
|
|
1362
|
+
* Runs start save point.
|
|
1363
|
+
* @param {string} savePointName - Save point name.
|
|
1364
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
1365
|
+
*/
|
|
1366
|
+
async startSavePoint(savePointName) {
|
|
1367
|
+
await this._transactionsActionsMutex.sync(async () => {
|
|
1368
|
+
await this._startSavePointAction(savePointName)
|
|
1369
|
+
})
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
/**
|
|
1373
|
+
* Runs start save point action.
|
|
1374
|
+
* @param {string} savePointName - Save point name.
|
|
1375
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
1376
|
+
*/
|
|
1377
|
+
async _startSavePointAction(savePointName) {
|
|
1378
|
+
await this.query(`SAVEPOINT ${savePointName}`)
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
/**
|
|
1382
|
+
* Runs rename column.
|
|
1383
|
+
* @param {string} tableName - Table name.
|
|
1384
|
+
* @param {string} oldColumnName - Previous column name.
|
|
1385
|
+
* @param {string} newColumnName - New column name.
|
|
1386
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
1387
|
+
*/
|
|
1388
|
+
async renameColumn(tableName, oldColumnName, newColumnName) {
|
|
1389
|
+
this._assertNotReadOnly()
|
|
1390
|
+
const tableColumn = new TableColumn(oldColumnName)
|
|
1391
|
+
|
|
1392
|
+
tableColumn.setNewName(newColumnName)
|
|
1393
|
+
|
|
1394
|
+
const tableData = new TableData(tableName)
|
|
1395
|
+
|
|
1396
|
+
tableData.addColumn(tableColumn)
|
|
1397
|
+
|
|
1398
|
+
const alterTableSQLs = await this.alterTableSQLs(tableData)
|
|
1399
|
+
|
|
1400
|
+
for (const alterTableSQL of alterTableSQLs) {
|
|
1401
|
+
await this.query(alterTableSQL)
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
/**
|
|
1406
|
+
* Runs release save point.
|
|
1407
|
+
* @param {string} savePointName - Save point name.
|
|
1408
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
1409
|
+
*/
|
|
1410
|
+
async releaseSavePoint(savePointName) {
|
|
1411
|
+
await this._transactionsActionsMutex.sync(async () => {
|
|
1412
|
+
await this._releaseSavePointAction(savePointName)
|
|
1413
|
+
})
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
/**
|
|
1417
|
+
* Runs release save point action.
|
|
1418
|
+
* @param {string} savePointName - Save point name.
|
|
1419
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
1420
|
+
*/
|
|
1421
|
+
async _releaseSavePointAction(savePointName) {
|
|
1422
|
+
try {
|
|
1423
|
+
await this.query(`RELEASE SAVEPOINT ${savePointName}`)
|
|
1424
|
+
} catch (error) {
|
|
1425
|
+
const message = error instanceof Error ? error.message : `${error}`
|
|
1426
|
+
|
|
1427
|
+
// Savepoint may already be gone if the database rolled back automatically
|
|
1428
|
+
if (message.toLowerCase().includes("savepoint") && message.toLowerCase().includes("does not exist")) {
|
|
1429
|
+
this.logger.debug(`Release savepoint ignored because it no longer exists: ${savePointName}`)
|
|
1430
|
+
return
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
throw error
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
/**
|
|
1438
|
+
* Runs rollback save point.
|
|
1439
|
+
* @param {string} savePointName - Save point name.
|
|
1440
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
1441
|
+
*/
|
|
1442
|
+
async rollbackSavePoint(savePointName) {
|
|
1443
|
+
await this._transactionsActionsMutex.sync(async () => {
|
|
1444
|
+
await this._rollbackSavePointAction(savePointName)
|
|
1445
|
+
})
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
/**
|
|
1449
|
+
* Runs rollback save point action.
|
|
1450
|
+
* @param {string} savePointName - Save point name.
|
|
1451
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
1452
|
+
*/
|
|
1453
|
+
async _rollbackSavePointAction(savePointName) {
|
|
1454
|
+
await this.query(`ROLLBACK TO SAVEPOINT ${savePointName}`)
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
/**
|
|
1458
|
+
* Runs truncate all tables.
|
|
1459
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
1460
|
+
*/
|
|
1461
|
+
async truncateAllTables() {
|
|
1462
|
+
this._assertNotReadOnly()
|
|
1463
|
+
await this.withDisabledForeignKeys(async () => {
|
|
1464
|
+
let tries = 0
|
|
1465
|
+
|
|
1466
|
+
while(tries <= 5) {
|
|
1467
|
+
tries++
|
|
1468
|
+
|
|
1469
|
+
const tables = await this.getTables()
|
|
1470
|
+
const truncateErrors = []
|
|
1471
|
+
|
|
1472
|
+
for (const table of tables) {
|
|
1473
|
+
if (table.getName() != "schema_migrations") {
|
|
1474
|
+
try {
|
|
1475
|
+
await table.truncate({cascade: true})
|
|
1476
|
+
} catch (error) {
|
|
1477
|
+
console.error(error)
|
|
1478
|
+
truncateErrors.push(error)
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
if (truncateErrors.length == 0) {
|
|
1484
|
+
break
|
|
1485
|
+
} else if (tries <= 5) {
|
|
1486
|
+
// A truncate failed — the schema cache may still list a table that was
|
|
1487
|
+
// dropped out from under us (e.g. a db:rollback test that left the
|
|
1488
|
+
// shared DB rolled back). Clear it so the next pass re-reads the live
|
|
1489
|
+
// table list and no longer tries to truncate a table that is gone.
|
|
1490
|
+
this.clearSchemaCache()
|
|
1491
|
+
} else {
|
|
1492
|
+
throw truncateErrors[0]
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
})
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
/**
|
|
1499
|
+
* Runs update.
|
|
1500
|
+
* @param {UpdateSqlArgsType} args - Options object.
|
|
1501
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
1502
|
+
*/
|
|
1503
|
+
async update(args) {
|
|
1504
|
+
this._assertNotReadOnly()
|
|
1505
|
+
const sql = this.updateSql(args)
|
|
1506
|
+
|
|
1507
|
+
await this.query(sql)
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
/**
|
|
1511
|
+
* Runs update sql.
|
|
1512
|
+
* @abstract
|
|
1513
|
+
* @param {UpdateSqlArgsType} args - Options object.
|
|
1514
|
+
* @returns {string} - SQL string.
|
|
1515
|
+
*/
|
|
1516
|
+
updateSql(args) { // eslint-disable-line no-unused-vars
|
|
1517
|
+
throw new Error("'disableForeignKeys' not implemented")
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
/**
|
|
1521
|
+
* Runs upsert sql.
|
|
1522
|
+
* @abstract
|
|
1523
|
+
* @param {UpsertSqlArgsType} args - Options object.
|
|
1524
|
+
* @returns {string} - SQL string.
|
|
1525
|
+
*/
|
|
1526
|
+
upsertSql(args) { // eslint-disable-line no-unused-vars
|
|
1527
|
+
throw new Error("'upsertSql' not implemented")
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
/**
|
|
1531
|
+
* Runs disable foreign keys.
|
|
1532
|
+
* @abstract
|
|
1533
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
1534
|
+
*/
|
|
1535
|
+
disableForeignKeys() {
|
|
1536
|
+
throw new Error("'disableForeignKeys' not implemented")
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
/**
|
|
1540
|
+
* Runs enable foreign keys.
|
|
1541
|
+
* @abstract
|
|
1542
|
+
* @returns {Promise<void>} - Resolves when complete.
|
|
1543
|
+
*/
|
|
1544
|
+
enableForeignKeys() {
|
|
1545
|
+
throw new Error("'enableForeignKeys' not implemented")
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
/**
|
|
1549
|
+
* Runs with disabled foreign keys.
|
|
1550
|
+
* @param {function() : void} callback - Callback function.
|
|
1551
|
+
* @returns {Promise<?>} - Resolves with the with disabled foreign keys.
|
|
1552
|
+
*/
|
|
1553
|
+
async withDisabledForeignKeys(callback) {
|
|
1554
|
+
await this.disableForeignKeys()
|
|
1555
|
+
|
|
1556
|
+
try {
|
|
1557
|
+
return await callback()
|
|
1558
|
+
} finally {
|
|
1559
|
+
await this.enableForeignKeys()
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
/**
|
|
1564
|
+
* Blocks until a named advisory lock is acquired on this connection.
|
|
1565
|
+
* Advisory locks are connection-scoped and do not interact with row or
|
|
1566
|
+
* table locks; they are purely cooperative between callers that use the
|
|
1567
|
+
* same name and let you serialize functionality without blocking readers
|
|
1568
|
+
* or writers that do not participate in the same lock.
|
|
1569
|
+
* @abstract
|
|
1570
|
+
* @param {string} name - Lock name.
|
|
1571
|
+
* @param {{timeoutMs?: number | null}} [_args] - Optional timeout in milliseconds; `null` or undefined blocks forever.
|
|
1572
|
+
* @returns {Promise<boolean>} - Resolves to true when the lock has been acquired, false if the timeout elapsed.
|
|
1573
|
+
*/
|
|
1574
|
+
acquireAdvisoryLock(name, _args = {}) {
|
|
1575
|
+
throw new Error(`'acquireAdvisoryLock' not implemented for ${this.constructor.name}`)
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
/**
|
|
1579
|
+
* Attempts to acquire a named advisory lock without blocking.
|
|
1580
|
+
* @abstract
|
|
1581
|
+
* @param {string} name - Lock name.
|
|
1582
|
+
* @returns {Promise<boolean>} - Resolves to true if the lock was acquired, false if it was already held.
|
|
1583
|
+
*/
|
|
1584
|
+
tryAcquireAdvisoryLock(name) { // eslint-disable-line no-unused-vars
|
|
1585
|
+
throw new Error(`'tryAcquireAdvisoryLock' not implemented for ${this.constructor.name}`)
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
/**
|
|
1589
|
+
* Releases a named advisory lock previously acquired on this connection.
|
|
1590
|
+
* @abstract
|
|
1591
|
+
* @param {string} name - Lock name.
|
|
1592
|
+
* @returns {Promise<boolean>} - Resolves to true if the lock was held by this session and has now been released.
|
|
1593
|
+
*/
|
|
1594
|
+
releaseAdvisoryLock(name) { // eslint-disable-line no-unused-vars
|
|
1595
|
+
throw new Error(`'releaseAdvisoryLock' not implemented for ${this.constructor.name}`)
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
/**
|
|
1599
|
+
* Checks whether a named advisory lock is currently held by any session.
|
|
1600
|
+
* Intended as an introspection helper; callers who need to act on the
|
|
1601
|
+
* result should prefer `tryAcquireAdvisoryLock` to avoid a TOCTOU race.
|
|
1602
|
+
* @abstract
|
|
1603
|
+
* @param {string} name - Lock name.
|
|
1604
|
+
* @returns {Promise<boolean>} - Resolves to true if the lock is held by ? session.
|
|
1605
|
+
*/
|
|
1606
|
+
isAdvisoryLockHeld(name) { // eslint-disable-line no-unused-vars
|
|
1607
|
+
throw new Error(`'isAdvisoryLockHeld' not implemented for ${this.constructor.name}`)
|
|
1608
|
+
}
|
|
1609
|
+
}
|