@fragno-dev/db 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +206 -140
- package/CHANGELOG.md +67 -0
- package/README.md +30 -9
- package/dist/adapters/adapters.d.ts +23 -21
- package/dist/adapters/adapters.d.ts.map +1 -1
- package/dist/adapters/adapters.js.map +1 -1
- package/dist/adapters/generic-sql/driver-config.d.ts +16 -1
- package/dist/adapters/generic-sql/driver-config.d.ts.map +1 -1
- package/dist/adapters/generic-sql/driver-config.js +23 -1
- package/dist/adapters/generic-sql/driver-config.js.map +1 -1
- package/dist/adapters/generic-sql/generic-sql-adapter.d.ts +27 -9
- package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -1
- package/dist/adapters/generic-sql/generic-sql-adapter.js +55 -16
- package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -1
- package/dist/adapters/generic-sql/generic-sql-uow-executor.js +129 -3
- package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -1
- package/dist/adapters/generic-sql/migration/dialect/mysql.js +24 -5
- package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -1
- package/dist/adapters/generic-sql/migration/dialect/postgres.js +6 -5
- package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -1
- package/dist/adapters/generic-sql/migration/dialect/sqlite.js +21 -10
- package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -1
- package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -1
- package/dist/adapters/generic-sql/migration/prepared-migrations.js +8 -8
- package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -1
- package/dist/adapters/generic-sql/migration/sql-generator.js +74 -51
- package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -1
- package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +6 -5
- package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -1
- package/dist/adapters/generic-sql/query/cursor-utils.js +42 -4
- package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -1
- package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +25 -17
- package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -1
- package/dist/adapters/generic-sql/query/select-builder.js +5 -3
- package/dist/adapters/generic-sql/query/select-builder.js.map +1 -1
- package/dist/adapters/generic-sql/query/sql-query-compiler.js +15 -12
- package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -1
- package/dist/adapters/generic-sql/query/where-builder.js +38 -28
- package/dist/adapters/generic-sql/query/where-builder.js.map +1 -1
- package/dist/adapters/generic-sql/sqlite-storage.d.ts +13 -0
- package/dist/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
- package/dist/adapters/generic-sql/sqlite-storage.js +15 -0
- package/dist/adapters/generic-sql/sqlite-storage.js.map +1 -0
- package/dist/adapters/generic-sql/uow-decoder.js +7 -3
- package/dist/adapters/generic-sql/uow-decoder.js.map +1 -1
- package/dist/adapters/generic-sql/uow-encoder.js +28 -8
- package/dist/adapters/generic-sql/uow-encoder.js.map +1 -1
- package/dist/adapters/in-memory/condition-evaluator.js +131 -0
- package/dist/adapters/in-memory/condition-evaluator.js.map +1 -0
- package/dist/adapters/in-memory/errors.d.ts +13 -0
- package/dist/adapters/in-memory/errors.d.ts.map +1 -0
- package/dist/adapters/in-memory/errors.js +23 -0
- package/dist/adapters/in-memory/errors.js.map +1 -0
- package/dist/adapters/in-memory/in-memory-adapter.d.ts +27 -0
- package/dist/adapters/in-memory/in-memory-adapter.d.ts.map +1 -0
- package/dist/adapters/in-memory/in-memory-adapter.js +176 -0
- package/dist/adapters/in-memory/in-memory-adapter.js.map +1 -0
- package/dist/adapters/in-memory/in-memory-uow.js +648 -0
- package/dist/adapters/in-memory/in-memory-uow.js.map +1 -0
- package/dist/adapters/in-memory/index.d.ts +4 -0
- package/dist/adapters/in-memory/index.js +4 -0
- package/dist/adapters/in-memory/options.d.ts +28 -0
- package/dist/adapters/in-memory/options.d.ts.map +1 -0
- package/dist/adapters/in-memory/options.js +61 -0
- package/dist/adapters/in-memory/options.js.map +1 -0
- package/dist/adapters/in-memory/reference-resolution.js +26 -0
- package/dist/adapters/in-memory/reference-resolution.js.map +1 -0
- package/dist/adapters/in-memory/sorted-array-index.js +129 -0
- package/dist/adapters/in-memory/sorted-array-index.js.map +1 -0
- package/dist/adapters/in-memory/store.js +71 -0
- package/dist/adapters/in-memory/store.js.map +1 -0
- package/dist/adapters/in-memory/value-comparison.js +28 -0
- package/dist/adapters/in-memory/value-comparison.js.map +1 -0
- package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -1
- package/dist/adapters/shared/uow-operation-compiler.js +11 -11
- package/dist/adapters/shared/uow-operation-compiler.js.map +1 -1
- package/dist/adapters/sql/index.d.ts +5 -0
- package/dist/adapters/sql/index.js +4 -0
- package/dist/db-fragment-definition-builder.d.ts +45 -96
- package/dist/db-fragment-definition-builder.d.ts.map +1 -1
- package/dist/db-fragment-definition-builder.js +121 -99
- package/dist/db-fragment-definition-builder.js.map +1 -1
- package/dist/dispatchers/cloudflare-do/index.d.ts +26 -0
- package/dist/dispatchers/cloudflare-do/index.d.ts.map +1 -0
- package/dist/dispatchers/cloudflare-do/index.js +63 -0
- package/dist/dispatchers/cloudflare-do/index.js.map +1 -0
- package/dist/dispatchers/node/index.d.ts +17 -0
- package/dist/dispatchers/node/index.d.ts.map +1 -0
- package/dist/dispatchers/node/index.js +59 -0
- package/dist/dispatchers/node/index.js.map +1 -0
- package/dist/fragments/internal-fragment.d.ts +172 -9
- package/dist/fragments/internal-fragment.d.ts.map +1 -1
- package/dist/fragments/internal-fragment.js +193 -74
- package/dist/fragments/internal-fragment.js.map +1 -1
- package/dist/fragments/internal-fragment.routes.js +29 -0
- package/dist/fragments/internal-fragment.routes.js.map +1 -0
- package/dist/fragments/internal-fragment.schema.d.ts +9 -0
- package/dist/fragments/internal-fragment.schema.d.ts.map +1 -0
- package/dist/fragments/internal-fragment.schema.js +22 -0
- package/dist/fragments/internal-fragment.schema.js.map +1 -0
- package/dist/hooks/durable-hooks-processor.d.ts +14 -0
- package/dist/hooks/durable-hooks-processor.d.ts.map +1 -0
- package/dist/hooks/durable-hooks-processor.js +32 -0
- package/dist/hooks/durable-hooks-processor.js.map +1 -0
- package/dist/hooks/hooks.d.ts +47 -4
- package/dist/hooks/hooks.d.ts.map +1 -1
- package/dist/hooks/hooks.js +106 -39
- package/dist/hooks/hooks.js.map +1 -1
- package/dist/migration-engine/auto-from-schema.js +14 -11
- package/dist/migration-engine/auto-from-schema.js.map +1 -1
- package/dist/migration-engine/generation-engine.d.ts +16 -10
- package/dist/migration-engine/generation-engine.d.ts.map +1 -1
- package/dist/migration-engine/generation-engine.js +72 -33
- package/dist/migration-engine/generation-engine.js.map +1 -1
- package/dist/migration-engine/shared.js.map +1 -1
- package/dist/mod.d.ts +17 -10
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +14 -8
- package/dist/mod.js.map +1 -1
- package/dist/naming/sql-naming.d.ts +19 -0
- package/dist/naming/sql-naming.d.ts.map +1 -0
- package/dist/naming/sql-naming.js +116 -0
- package/dist/naming/sql-naming.js.map +1 -0
- package/dist/node_modules/.pnpm/{rou3@0.7.10 → rou3@0.7.12}/node_modules/rou3/dist/index.js +8 -5
- package/dist/node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.js.map +1 -0
- package/dist/outbox/outbox-builder.js +156 -0
- package/dist/outbox/outbox-builder.js.map +1 -0
- package/dist/outbox/outbox.d.ts +52 -0
- package/dist/outbox/outbox.d.ts.map +1 -0
- package/dist/outbox/outbox.js +37 -0
- package/dist/outbox/outbox.js.map +1 -0
- package/dist/packages/fragno/dist/api/fragment-definition-builder.js +3 -2
- package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +1 -1
- package/dist/packages/fragno/dist/api/fragment-instantiator.js +164 -20
- package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +1 -1
- package/dist/packages/fragno/dist/api/request-input-context.js +67 -0
- package/dist/packages/fragno/dist/api/request-input-context.js.map +1 -1
- package/dist/packages/fragno/dist/api/route.js +14 -1
- package/dist/packages/fragno/dist/api/route.js.map +1 -1
- package/dist/packages/fragno/dist/internal/trace-context.js +12 -0
- package/dist/packages/fragno/dist/internal/trace-context.js.map +1 -0
- package/dist/query/column-defaults.js +20 -4
- package/dist/query/column-defaults.js.map +1 -1
- package/dist/query/cursor.d.ts +3 -1
- package/dist/query/cursor.d.ts.map +1 -1
- package/dist/query/cursor.js +45 -14
- package/dist/query/cursor.js.map +1 -1
- package/dist/query/db-now.d.ts +8 -0
- package/dist/query/db-now.d.ts.map +1 -0
- package/dist/query/db-now.js +7 -0
- package/dist/query/db-now.js.map +1 -0
- package/dist/query/serialize/create-sql-serializer.js +3 -2
- package/dist/query/serialize/create-sql-serializer.js.map +1 -1
- package/dist/query/serialize/dialect/mysql-serializer.js +12 -6
- package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -1
- package/dist/query/serialize/dialect/postgres-serializer.js +25 -7
- package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -1
- package/dist/query/serialize/dialect/sqlite-serializer.js +55 -11
- package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -1
- package/dist/query/serialize/sql-serializer.js +2 -2
- package/dist/query/serialize/sql-serializer.js.map +1 -1
- package/dist/query/simple-query-interface.d.ts +6 -1
- package/dist/query/simple-query-interface.d.ts.map +1 -1
- package/dist/query/unit-of-work/execute-unit-of-work.d.ts +351 -100
- package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -1
- package/dist/query/unit-of-work/execute-unit-of-work.js +440 -267
- package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -1
- package/dist/query/unit-of-work/unit-of-work.d.ts +67 -22
- package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
- package/dist/query/unit-of-work/unit-of-work.js +110 -13
- package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
- package/dist/query/value-decoding.js +8 -5
- package/dist/query/value-decoding.js.map +1 -1
- package/dist/query/value-encoding.js +29 -9
- package/dist/query/value-encoding.js.map +1 -1
- package/dist/schema/create.d.ts +40 -14
- package/dist/schema/create.d.ts.map +1 -1
- package/dist/schema/create.js +82 -42
- package/dist/schema/create.js.map +1 -1
- package/dist/schema/generate-id.d.ts +20 -0
- package/dist/schema/generate-id.d.ts.map +1 -0
- package/dist/schema/generate-id.js +28 -0
- package/dist/schema/generate-id.js.map +1 -0
- package/dist/schema/type-conversion/create-sql-type-mapper.js +3 -2
- package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -1
- package/dist/schema/type-conversion/dialect/sqlite.js +9 -0
- package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -1
- package/dist/schema/validator.d.ts +10 -0
- package/dist/schema/validator.d.ts.map +1 -0
- package/dist/schema/validator.js +123 -0
- package/dist/schema/validator.js.map +1 -0
- package/dist/schema-output/drizzle.d.ts +30 -0
- package/dist/schema-output/drizzle.d.ts.map +1 -0
- package/dist/{adapters/drizzle/generate.js → schema-output/drizzle.js} +82 -56
- package/dist/schema-output/drizzle.js.map +1 -0
- package/dist/schema-output/prisma.d.ts +17 -0
- package/dist/schema-output/prisma.d.ts.map +1 -0
- package/dist/schema-output/prisma.js +296 -0
- package/dist/schema-output/prisma.js.map +1 -0
- package/dist/util/default-database-adapter.js +61 -0
- package/dist/util/default-database-adapter.js.map +1 -0
- package/dist/with-database.d.ts +1 -1
- package/dist/with-database.d.ts.map +1 -1
- package/dist/with-database.js +12 -3
- package/dist/with-database.js.map +1 -1
- package/package.json +43 -28
- package/src/adapters/adapters.ts +30 -24
- package/src/adapters/drizzle/migrate-drizzle.test.ts +54 -33
- package/src/adapters/drizzle/migration-parity-drizzle-kit.test.ts +599 -0
- package/src/adapters/drizzle/test-utils.ts +12 -8
- package/src/adapters/generic-sql/driver-config.ts +38 -0
- package/src/adapters/generic-sql/generic-sql-adapter.test.ts +5 -5
- package/src/adapters/generic-sql/generic-sql-adapter.ts +110 -24
- package/src/adapters/generic-sql/generic-sql-uow-executor.test.ts +54 -0
- package/src/adapters/generic-sql/generic-sql-uow-executor.ts +231 -3
- package/src/adapters/generic-sql/migration/adapter-migration-parity.test.ts +118 -0
- package/src/adapters/generic-sql/migration/dialect/mysql.test.ts +26 -8
- package/src/adapters/generic-sql/migration/dialect/mysql.ts +46 -8
- package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +25 -7
- package/src/adapters/generic-sql/migration/dialect/postgres.ts +8 -4
- package/src/adapters/generic-sql/migration/dialect/sqlite.test.ts +47 -8
- package/src/adapters/generic-sql/migration/dialect/sqlite.ts +27 -12
- package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +128 -39
- package/src/adapters/generic-sql/migration/prepared-migrations.ts +15 -8
- package/src/adapters/generic-sql/migration/sql-generator.ts +142 -65
- package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +9 -6
- package/src/adapters/generic-sql/query/cursor-utils.test.ts +271 -0
- package/src/adapters/generic-sql/query/cursor-utils.ts +41 -6
- package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +27 -27
- package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +38 -24
- package/src/adapters/generic-sql/query/select-builder.test.ts +15 -11
- package/src/adapters/generic-sql/query/select-builder.ts +6 -2
- package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +52 -2
- package/src/adapters/generic-sql/query/sql-query-compiler.ts +50 -15
- package/src/adapters/generic-sql/query/where-builder.test.ts +91 -17
- package/src/adapters/generic-sql/query/where-builder.ts +90 -38
- package/src/adapters/{kysely/kysely-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-migrations.test.ts} +6 -6
- package/src/adapters/generic-sql/sql-adapter-pglite-pagination.test.ts +806 -0
- package/src/adapters/{drizzle/drizzle-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-queries.test.ts} +11 -11
- package/src/adapters/generic-sql/{test/generic-drizzle-adapter-sqlite3.test.ts → sql-adapter-sqlite3-driver.test.ts} +49 -35
- package/src/adapters/{drizzle/drizzle-adapter-sqlite3.test.ts → generic-sql/sql-adapter-sqlite3-uow.test.ts} +48 -32
- package/src/adapters/{kysely/kysely-adapter-sqlocal.test.ts → generic-sql/sql-adapter-sqlocal.test.ts} +6 -6
- package/src/adapters/generic-sql/sqlite-storage.ts +20 -0
- package/src/adapters/generic-sql/uow-decoder.test.ts +1 -1
- package/src/adapters/generic-sql/uow-decoder.ts +21 -3
- package/src/adapters/generic-sql/uow-encoder.test.ts +33 -2
- package/src/adapters/generic-sql/uow-encoder.ts +50 -11
- package/src/adapters/in-memory/condition-evaluator.test.ts +193 -0
- package/src/adapters/in-memory/condition-evaluator.ts +275 -0
- package/src/adapters/in-memory/errors.ts +20 -0
- package/src/adapters/in-memory/in-memory-adapter.ts +277 -0
- package/src/adapters/in-memory/in-memory-uow.mutations.test.ts +296 -0
- package/src/adapters/in-memory/in-memory-uow.retrieval.test.ts +100 -0
- package/src/adapters/in-memory/in-memory-uow.ts +1348 -0
- package/src/adapters/in-memory/index.ts +3 -0
- package/src/adapters/in-memory/options.test.ts +41 -0
- package/src/adapters/in-memory/options.ts +87 -0
- package/src/adapters/in-memory/reference-resolution.test.ts +50 -0
- package/src/adapters/in-memory/reference-resolution.ts +67 -0
- package/src/adapters/in-memory/sorted-array-index.test.ts +123 -0
- package/src/adapters/in-memory/sorted-array-index.ts +228 -0
- package/src/adapters/in-memory/store.test.ts +68 -0
- package/src/adapters/in-memory/store.ts +145 -0
- package/src/adapters/in-memory/value-comparison.ts +53 -0
- package/src/adapters/in-memory/value-normalization.test.ts +57 -0
- package/src/adapters/prisma/prisma-adapter-sqlite3.test.ts +1163 -0
- package/src/adapters/shared/from-unit-of-work-compiler.ts +3 -1
- package/src/adapters/shared/uow-operation-compiler.ts +26 -16
- package/src/adapters/sql/index.ts +12 -0
- package/src/db-fragment-definition-builder.test.ts +88 -54
- package/src/db-fragment-definition-builder.ts +201 -322
- package/src/db-fragment-instantiator.test.ts +169 -101
- package/src/db-fragment-integration.test.ts +301 -149
- package/src/dispatchers/cloudflare-do/index.test.ts +73 -0
- package/src/dispatchers/cloudflare-do/index.ts +104 -0
- package/src/dispatchers/node/index.test.ts +91 -0
- package/src/dispatchers/node/index.ts +87 -0
- package/src/fragments/internal-fragment.routes.ts +42 -0
- package/src/fragments/internal-fragment.schema.ts +51 -0
- package/src/fragments/internal-fragment.test.ts +730 -274
- package/src/fragments/internal-fragment.ts +447 -154
- package/src/hooks/durable-hooks-processor.test.ts +117 -0
- package/src/hooks/durable-hooks-processor.ts +67 -0
- package/src/hooks/hooks.test.ts +411 -259
- package/src/hooks/hooks.ts +265 -66
- package/src/migration-engine/auto-from-schema.test.ts +14 -14
- package/src/migration-engine/auto-from-schema.ts +5 -2
- package/src/migration-engine/create.test.ts +2 -2
- package/src/migration-engine/generation-engine.test.ts +229 -104
- package/src/migration-engine/generation-engine.ts +94 -64
- package/src/migration-engine/shared.ts +1 -0
- package/src/mod.ts +78 -30
- package/src/naming/sql-naming.ts +180 -0
- package/src/outbox/outbox-builder.ts +241 -0
- package/src/outbox/outbox.test.ts +253 -0
- package/src/outbox/outbox.ts +137 -0
- package/src/query/column-defaults.ts +41 -3
- package/src/query/condition-builder.test.ts +3 -3
- package/src/query/cursor.test.ts +116 -18
- package/src/query/cursor.ts +75 -26
- package/src/query/db-now.ts +6 -0
- package/src/query/query-type.test.ts +2 -2
- package/src/query/serialize/create-sql-serializer.ts +7 -2
- package/src/query/serialize/dialect/mysql-serializer.ts +12 -4
- package/src/query/serialize/dialect/postgres-serializer.ts +34 -4
- package/src/query/serialize/dialect/sqlite-serializer.test.ts +51 -1
- package/src/query/serialize/dialect/sqlite-serializer.ts +92 -9
- package/src/query/serialize/sql-serializer.ts +4 -4
- package/src/query/simple-query-interface.ts +5 -0
- package/src/query/unit-of-work/execute-unit-of-work.test.ts +1512 -1458
- package/src/query/unit-of-work/execute-unit-of-work.ts +1708 -596
- package/src/query/unit-of-work/tx-builder.test.ts +1041 -0
- package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +32 -32
- package/src/query/unit-of-work/unit-of-work-types.test.ts +1 -1
- package/src/query/unit-of-work/unit-of-work.test.ts +231 -36
- package/src/query/unit-of-work/unit-of-work.ts +229 -31
- package/src/query/value-decoding.test.ts +13 -2
- package/src/query/value-decoding.ts +17 -4
- package/src/query/value-encoding.test.ts +85 -2
- package/src/query/value-encoding.ts +56 -6
- package/src/schema/create.test.ts +129 -42
- package/src/schema/create.ts +187 -47
- package/src/schema/generate-id.test.ts +57 -0
- package/src/schema/generate-id.ts +38 -0
- package/src/schema/serialize.test.ts +14 -2
- package/src/schema/type-conversion/create-sql-type-mapper.ts +7 -2
- package/src/schema/type-conversion/dialect/sqlite.ts +18 -0
- package/src/schema/type-conversion/type-mapping.test.ts +25 -1
- package/src/schema/validator.test.ts +197 -0
- package/src/schema/validator.ts +231 -0
- package/src/{adapters/drizzle/generate.test.ts → schema-output/drizzle.test.ts} +179 -129
- package/src/{adapters/drizzle/generate.ts → schema-output/drizzle.ts} +143 -93
- package/src/schema-output/prisma.test.ts +536 -0
- package/src/schema-output/prisma.ts +573 -0
- package/src/util/default-database-adapter.ts +106 -0
- package/src/with-database.ts +22 -3
- package/tsdown.config.ts +6 -4
- package/dist/adapters/drizzle/drizzle-adapter.d.ts +0 -20
- package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +0 -1
- package/dist/adapters/drizzle/drizzle-adapter.js +0 -27
- package/dist/adapters/drizzle/drizzle-adapter.js.map +0 -1
- package/dist/adapters/drizzle/generate.d.ts +0 -30
- package/dist/adapters/drizzle/generate.d.ts.map +0 -1
- package/dist/adapters/drizzle/generate.js.map +0 -1
- package/dist/adapters/kysely/kysely-adapter.d.ts +0 -19
- package/dist/adapters/kysely/kysely-adapter.d.ts.map +0 -1
- package/dist/adapters/kysely/kysely-adapter.js +0 -17
- package/dist/adapters/kysely/kysely-adapter.js.map +0 -1
- package/dist/adapters/shared/table-name-mapper.d.ts +0 -12
- package/dist/adapters/shared/table-name-mapper.d.ts.map +0 -1
- package/dist/adapters/shared/table-name-mapper.js +0 -43
- package/dist/adapters/shared/table-name-mapper.js.map +0 -1
- package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js.map +0 -1
- package/dist/schema-generator/schema-generator.d.ts +0 -15
- package/dist/schema-generator/schema-generator.d.ts.map +0 -1
- package/src/adapters/drizzle/drizzle-adapter.ts +0 -39
- package/src/adapters/kysely/kysely-adapter.ts +0 -27
- package/src/adapters/shared/table-name-mapper.ts +0 -50
- package/src/schema-generator/schema-generator.ts +0 -12
- package/src/shared/config.ts +0 -10
- package/src/shared/connection-pool.ts +0 -24
- package/src/shared/prisma.ts +0 -45
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { buildCondition } from "../../../query/condition-builder.js";
|
|
2
1
|
import { createColdKysely } from "../migration/cold-kysely.js";
|
|
3
2
|
import { UOWOperationCompiler } from "../../shared/uow-operation-compiler.js";
|
|
3
|
+
import { buildCondition } from "../../../query/condition-builder.js";
|
|
4
4
|
import "./sql-query-compiler.js";
|
|
5
5
|
import { createSQLQueryCompiler } from "./create-sql-query-compiler.js";
|
|
6
6
|
import { buildCursorCondition } from "./cursor-utils.js";
|
|
@@ -14,25 +14,29 @@ import { buildFindOptions } from "../../../query/orm/orm.js";
|
|
|
14
14
|
* high-level business logic like cursor pagination, version checking, and index resolution.
|
|
15
15
|
*/
|
|
16
16
|
var GenericSQLUOWOperationCompiler = class extends UOWOperationCompiler {
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
sqliteStorageMode;
|
|
18
|
+
constructor(driverConfig, sqliteStorageMode, resolverFactory) {
|
|
19
|
+
super(driverConfig, resolverFactory);
|
|
20
|
+
this.sqliteStorageMode = sqliteStorageMode;
|
|
19
21
|
}
|
|
20
22
|
/**
|
|
21
23
|
* Get SQL compiler for a specific namespace
|
|
22
24
|
*/
|
|
23
|
-
getSQLCompiler(namespace) {
|
|
24
|
-
const
|
|
25
|
-
|
|
25
|
+
getSQLCompiler(schema, namespace) {
|
|
26
|
+
const resolver = this.getNamingResolver(schema, namespace ?? null);
|
|
27
|
+
const kysely = createColdKysely(this.driverConfig.databaseType);
|
|
28
|
+
const schemaName = resolver.getSchemaName();
|
|
29
|
+
return createSQLQueryCompiler(schemaName ? kysely.withSchema(schemaName) : kysely, this.driverConfig, this.sqliteStorageMode, resolver);
|
|
26
30
|
}
|
|
27
31
|
compileCount(op) {
|
|
28
|
-
const sqlCompiler = this.getSQLCompiler(op.namespace);
|
|
32
|
+
const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);
|
|
29
33
|
let conditions = op.options.where ? buildCondition(op.table.columns, op.options.where) : void 0;
|
|
30
34
|
if (conditions === true) conditions = void 0;
|
|
31
35
|
if (conditions === false) return null;
|
|
32
36
|
return sqlCompiler.compileCount(op.table, { where: conditions });
|
|
33
37
|
}
|
|
34
38
|
compileFind(op) {
|
|
35
|
-
const sqlCompiler = this.getSQLCompiler(op.namespace);
|
|
39
|
+
const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);
|
|
36
40
|
const { useIndex: _useIndex, orderByIndex, joins: join, after, before, pageSize,...findManyOptions } = op.options;
|
|
37
41
|
let indexColumns = [];
|
|
38
42
|
let orderDirection = "asc";
|
|
@@ -46,7 +50,7 @@ var GenericSQLUOWOperationCompiler = class extends UOWOperationCompiler {
|
|
|
46
50
|
let orderBy;
|
|
47
51
|
if (indexColumns.length > 0) orderBy = indexColumns.map((col) => [col, orderDirection]);
|
|
48
52
|
if ((after || before) && indexColumns.length > 1) throw new Error("Multi-column cursor pagination is not yet supported in Generic SQL implementation");
|
|
49
|
-
const cursorCondition = buildCursorCondition(after || before, indexColumns, orderDirection, !!after, this.driverConfig);
|
|
53
|
+
const cursorCondition = buildCursorCondition(after || before, indexColumns, orderDirection, !!after, this.driverConfig, this.sqliteStorageMode);
|
|
50
54
|
let combinedWhere;
|
|
51
55
|
if (findManyOptions.where) {
|
|
52
56
|
const whereResult = buildCondition(op.table.columns, findManyOptions.where);
|
|
@@ -70,30 +74,31 @@ var GenericSQLUOWOperationCompiler = class extends UOWOperationCompiler {
|
|
|
70
74
|
const compiledOptions = buildFindOptions(op.table, {
|
|
71
75
|
...findManyOptions,
|
|
72
76
|
where: combinedWhere ? () => combinedWhere : void 0,
|
|
73
|
-
orderBy: orderBy?.map(([col, dir]) => [col.
|
|
77
|
+
orderBy: orderBy?.map(([col, dir]) => [col.name, dir]),
|
|
74
78
|
limit: effectiveLimit
|
|
75
79
|
});
|
|
76
80
|
if (compiledOptions === false) return null;
|
|
77
81
|
return sqlCompiler.compileFindMany(op.table, compiledOptions);
|
|
78
82
|
}
|
|
79
83
|
compileCreate(op) {
|
|
80
|
-
const sqlCompiler = this.getSQLCompiler(op.namespace);
|
|
84
|
+
const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);
|
|
81
85
|
const table = this.getTable(op.schema, op.table);
|
|
82
86
|
return {
|
|
83
87
|
query: sqlCompiler.compileCreate(table, op.values),
|
|
88
|
+
operation: op,
|
|
84
89
|
op: "create",
|
|
85
90
|
expectedAffectedRows: null,
|
|
86
91
|
expectedReturnedRows: null
|
|
87
92
|
};
|
|
88
93
|
}
|
|
89
94
|
compileUpdate(op) {
|
|
90
|
-
const sqlCompiler = this.getSQLCompiler(op.namespace);
|
|
95
|
+
const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);
|
|
91
96
|
const table = this.getTable(op.schema, op.table);
|
|
92
97
|
const idColumn = table.getIdColumn();
|
|
93
98
|
const versionColumn = table.getVersionColumn();
|
|
94
99
|
const externalId = this.getExternalId(op.id);
|
|
95
100
|
const versionToCheck = this.getVersionToCheck(op.id, op.checkVersion);
|
|
96
|
-
const conditionsResult = versionToCheck !== void 0 ? buildCondition(table.columns, (eb) => eb.and(eb(idColumn.
|
|
101
|
+
const conditionsResult = versionToCheck !== void 0 ? buildCondition(table.columns, (eb) => eb.and(eb(idColumn.name, "=", externalId), eb(versionColumn.name, "=", versionToCheck))) : buildCondition(table.columns, (eb) => eb(idColumn.name, "=", externalId));
|
|
97
102
|
if (conditionsResult === false) return null;
|
|
98
103
|
const conditions = conditionsResult === true ? void 0 : conditionsResult;
|
|
99
104
|
const useReturningForCheck = op.checkVersion && this.driverConfig.supportsReturning && !this.driverConfig.supportsRowsAffected;
|
|
@@ -103,19 +108,20 @@ var GenericSQLUOWOperationCompiler = class extends UOWOperationCompiler {
|
|
|
103
108
|
where: conditions,
|
|
104
109
|
returning: useReturningForCheck
|
|
105
110
|
}),
|
|
111
|
+
operation: op,
|
|
106
112
|
op: "update",
|
|
107
113
|
expectedAffectedRows: useReturningForCheck ? null : op.checkVersion ? 1n : null,
|
|
108
114
|
expectedReturnedRows: useReturningForCheck ? 1 : null
|
|
109
115
|
};
|
|
110
116
|
}
|
|
111
117
|
compileDelete(op) {
|
|
112
|
-
const sqlCompiler = this.getSQLCompiler(op.namespace);
|
|
118
|
+
const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);
|
|
113
119
|
const table = this.getTable(op.schema, op.table);
|
|
114
120
|
const idColumn = table.getIdColumn();
|
|
115
121
|
const versionColumn = table.getVersionColumn();
|
|
116
122
|
const externalId = this.getExternalId(op.id);
|
|
117
123
|
const versionToCheck = this.getVersionToCheck(op.id, op.checkVersion);
|
|
118
|
-
const conditionsResult = versionToCheck !== void 0 ? buildCondition(table.columns, (eb) => eb.and(eb(idColumn.
|
|
124
|
+
const conditionsResult = versionToCheck !== void 0 ? buildCondition(table.columns, (eb) => eb.and(eb(idColumn.name, "=", externalId), eb(versionColumn.name, "=", versionToCheck))) : buildCondition(table.columns, (eb) => eb(idColumn.name, "=", externalId));
|
|
119
125
|
if (conditionsResult === false) return null;
|
|
120
126
|
const conditions = conditionsResult === true ? void 0 : conditionsResult;
|
|
121
127
|
const useReturningForCheck = op.checkVersion && this.driverConfig.supportsReturning && !this.driverConfig.supportsRowsAffected;
|
|
@@ -124,22 +130,24 @@ var GenericSQLUOWOperationCompiler = class extends UOWOperationCompiler {
|
|
|
124
130
|
where: conditions,
|
|
125
131
|
returning: useReturningForCheck
|
|
126
132
|
}),
|
|
133
|
+
operation: op,
|
|
127
134
|
op: "delete",
|
|
128
135
|
expectedAffectedRows: useReturningForCheck ? null : op.checkVersion ? 1n : null,
|
|
129
136
|
expectedReturnedRows: useReturningForCheck ? 1 : null
|
|
130
137
|
};
|
|
131
138
|
}
|
|
132
139
|
compileCheck(op) {
|
|
133
|
-
const sqlCompiler = this.getSQLCompiler(op.namespace);
|
|
140
|
+
const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);
|
|
134
141
|
const table = this.getTable(op.schema, op.table);
|
|
135
142
|
const idColumn = table.getIdColumn();
|
|
136
143
|
const versionColumn = table.getVersionColumn();
|
|
137
144
|
const externalId = op.id.externalId;
|
|
138
145
|
const version = op.id.version;
|
|
139
|
-
const condition = buildCondition(table.columns, (eb) => eb.and(eb(idColumn.
|
|
146
|
+
const condition = buildCondition(table.columns, (eb) => eb.and(eb(idColumn.name, "=", externalId), eb(versionColumn.name, "=", version)));
|
|
140
147
|
if (typeof condition === "boolean") throw new Error("Condition is a boolean, but should be a condition object.");
|
|
141
148
|
return {
|
|
142
149
|
query: sqlCompiler.compileCheck(table, condition),
|
|
150
|
+
operation: op,
|
|
143
151
|
op: "check",
|
|
144
152
|
expectedAffectedRows: null,
|
|
145
153
|
expectedReturnedRows: 1
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generic-sql-uow-operation-compiler.js","names":["indexColumns: AnyColumn[]","orderDirection: \"asc\" | \"desc\"","orderBy: [AnyColumn, \"asc\" | \"desc\"][] | undefined","combinedWhere: Condition | undefined","conditions: Condition | undefined"],"sources":["../../../../src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts"],"sourcesContent":["import { UOWOperationCompiler } from \"../../shared/uow-operation-compiler\";\nimport type { CompiledQuery } from \"kysely\";\nimport type { DriverConfig } from \"../driver-config\";\nimport type { TableNameMapper } from \"../../shared/table-name-mapper\";\nimport type {\n RetrievalOperation,\n MutationOperation,\n CompiledMutation,\n} from \"../../../query/unit-of-work/unit-of-work\";\nimport type { AnyColumn, AnySchema } from \"../../../schema/create\";\nimport { buildCondition } from \"../../../query/condition-builder\";\nimport { createSQLQueryCompiler } from \"./create-sql-query-compiler\";\nimport { SQLQueryCompiler } from \"./sql-query-compiler\";\nimport { buildCursorCondition } from \"./cursor-utils\";\nimport type { Condition } from \"../../../query/condition-builder\";\nimport { buildFindOptions } from \"../../../query/orm/orm\";\nimport type { AnySelectClause } from \"../../../query/simple-query-interface\";\nimport { createColdKysely } from \"../migration/cold-kysely\";\n\n/**\n * Generic SQL UOW Operation Compiler.\n *\n * Uses SQLQueryCompiler for dialect-specific SQL generation while handling\n * high-level business logic like cursor pagination, version checking, and index resolution.\n */\nexport class GenericSQLUOWOperationCompiler extends UOWOperationCompiler<CompiledQuery> {\n constructor(\n driverConfig: DriverConfig,\n mapperFactory?: (namespace: string | undefined) => TableNameMapper | undefined,\n ) {\n super(driverConfig, mapperFactory);\n }\n\n /**\n * Get SQL compiler for a specific namespace\n */\n private getSQLCompiler(namespace: string | undefined): SQLQueryCompiler {\n const mapper = this.getMapperForOperation(namespace);\n const kysely = createColdKysely(this.driverConfig.databaseType);\n return createSQLQueryCompiler(kysely, this.driverConfig, mapper);\n }\n\n override compileCount(\n op: RetrievalOperation<AnySchema> & { type: \"count\" },\n ): CompiledQuery | null {\n const sqlCompiler = this.getSQLCompiler(op.namespace);\n\n // Build where condition\n let conditions = op.options.where\n ? buildCondition(op.table.columns, op.options.where)\n : undefined;\n\n if (conditions === true) {\n conditions = undefined;\n }\n if (conditions === false) {\n return null;\n }\n\n return sqlCompiler.compileCount(op.table, { where: conditions });\n }\n\n override compileFind(op: RetrievalOperation<AnySchema> & { type: \"find\" }): CompiledQuery | null {\n const sqlCompiler = this.getSQLCompiler(op.namespace);\n\n // Extract options\n const {\n useIndex: _useIndex,\n orderByIndex,\n joins: join,\n after,\n before,\n pageSize,\n ...findManyOptions\n } = op.options;\n\n // Get index columns for ordering and cursor pagination\n let indexColumns: AnyColumn[] = [];\n let orderDirection: \"asc\" | \"desc\" = \"asc\";\n\n if (orderByIndex) {\n const index = op.table.indexes[orderByIndex.indexName];\n orderDirection = orderByIndex.direction;\n\n if (!index) {\n // If _primary index doesn't exist, fall back to internal ID column\n if (orderByIndex.indexName === \"_primary\") {\n indexColumns = [op.table.getIdColumn()];\n } else {\n throw new Error(\n `Index \"${orderByIndex.indexName}\" not found on table \"${op.table.name}\"`,\n );\n }\n } else {\n // Order by all columns in the index with the specified direction\n indexColumns = index.columns;\n }\n }\n\n // Convert orderByIndex to orderBy format\n let orderBy: [AnyColumn, \"asc\" | \"desc\"][] | undefined;\n if (indexColumns.length > 0) {\n orderBy = indexColumns.map((col) => [col, orderDirection]);\n }\n\n // Handle cursor pagination - build a cursor condition\n // TODO: Multi-column cursor pagination not yet supported\n if ((after || before) && indexColumns.length > 1) {\n throw new Error(\n \"Multi-column cursor pagination is not yet supported in Generic SQL implementation\",\n );\n }\n const cursorCondition = buildCursorCondition(\n after || before,\n indexColumns,\n orderDirection,\n !!after,\n this.driverConfig,\n );\n\n // Combine user where clause with cursor condition\n let combinedWhere: Condition | undefined;\n if (findManyOptions.where) {\n const whereResult = buildCondition(op.table.columns, findManyOptions.where);\n if (whereResult === true) {\n combinedWhere = undefined;\n } else if (whereResult === false) {\n return null;\n } else {\n combinedWhere = whereResult;\n }\n }\n\n if (cursorCondition) {\n if (combinedWhere) {\n combinedWhere = {\n type: \"and\",\n items: [combinedWhere, cursorCondition],\n };\n } else {\n combinedWhere = cursorCondition;\n }\n }\n\n // For cursor pagination, fetch one extra item to determine if there's a next page\n const effectiveLimit = pageSize && op.withCursor ? pageSize + 1 : pageSize;\n\n // When we have joins, use the query builder directly\n if (join && join.length > 0) {\n return sqlCompiler.compileFindMany(op.table, {\n select: (findManyOptions.select ?? true) as AnySelectClause,\n where: combinedWhere,\n orderBy,\n limit: effectiveLimit,\n join,\n });\n }\n\n // Otherwise, use buildFindOptions to process the query options\n const compiledOptions = buildFindOptions(op.table, {\n ...findManyOptions,\n where: combinedWhere ? () => combinedWhere! : undefined,\n orderBy: orderBy?.map(([col, dir]) => [col.ormName, dir]),\n limit: effectiveLimit,\n });\n\n if (compiledOptions === false) {\n return null;\n }\n\n return sqlCompiler.compileFindMany(op.table, compiledOptions);\n }\n\n override compileCreate(\n op: MutationOperation<AnySchema> & { type: \"create\" },\n ): CompiledMutation<CompiledQuery> | null {\n const sqlCompiler = this.getSQLCompiler(op.namespace);\n const table = this.getTable(op.schema, op.table);\n\n return {\n query: sqlCompiler.compileCreate(table, op.values),\n op: \"create\",\n expectedAffectedRows: null, // creates don't need affected row checks\n expectedReturnedRows: null,\n };\n }\n\n override compileUpdate(\n op: MutationOperation<AnySchema> & { type: \"update\" },\n ): CompiledMutation<CompiledQuery> | null {\n const sqlCompiler = this.getSQLCompiler(op.namespace);\n const table = this.getTable(op.schema, op.table);\n const idColumn = table.getIdColumn();\n const versionColumn = table.getVersionColumn();\n\n const externalId = this.getExternalId(op.id);\n const versionToCheck = this.getVersionToCheck(op.id, op.checkVersion);\n\n // Build WHERE clause that filters by ID and optionally by version\n const conditionsResult =\n versionToCheck !== undefined\n ? buildCondition(table.columns, (eb) =>\n eb.and(\n eb(idColumn.ormName, \"=\", externalId),\n eb(versionColumn.ormName, \"=\", versionToCheck),\n ),\n )\n : buildCondition(table.columns, (eb) => eb(idColumn.ormName, \"=\", externalId));\n\n if (conditionsResult === false) {\n return null;\n }\n\n const conditions: Condition | undefined =\n conditionsResult === true ? undefined : conditionsResult;\n\n // Determine if we should use RETURNING-based checking\n // Use RETURNING when driver supports it but doesn't support affected rows reporting\n const useReturningForCheck =\n op.checkVersion &&\n this.driverConfig.supportsReturning &&\n !this.driverConfig.supportsRowsAffected;\n\n const query = sqlCompiler.compileUpdate(table, {\n set: op.set,\n where: conditions,\n returning: useReturningForCheck,\n });\n\n return {\n query,\n op: \"update\",\n expectedAffectedRows: useReturningForCheck ? null : op.checkVersion ? 1n : null,\n expectedReturnedRows: useReturningForCheck ? 1 : null,\n };\n }\n\n override compileDelete(\n op: MutationOperation<AnySchema> & { type: \"delete\" },\n ): CompiledMutation<CompiledQuery> | null {\n const sqlCompiler = this.getSQLCompiler(op.namespace);\n const table = this.getTable(op.schema, op.table);\n const idColumn = table.getIdColumn();\n const versionColumn = table.getVersionColumn();\n\n const externalId = this.getExternalId(op.id);\n const versionToCheck = this.getVersionToCheck(op.id, op.checkVersion);\n\n // Build WHERE clause that filters by ID and optionally by version\n const conditionsResult =\n versionToCheck !== undefined\n ? buildCondition(table.columns, (eb) =>\n eb.and(\n eb(idColumn.ormName, \"=\", externalId),\n eb(versionColumn.ormName, \"=\", versionToCheck),\n ),\n )\n : buildCondition(table.columns, (eb) => eb(idColumn.ormName, \"=\", externalId));\n\n if (conditionsResult === false) {\n return null;\n }\n\n const conditions: Condition | undefined =\n conditionsResult === true ? undefined : conditionsResult;\n\n // Determine if we should use RETURNING-based checking\n // Use RETURNING when driver supports it but doesn't support affected rows reporting\n const useReturningForCheck =\n op.checkVersion &&\n this.driverConfig.supportsReturning &&\n !this.driverConfig.supportsRowsAffected;\n\n const query = sqlCompiler.compileDelete(table, {\n where: conditions,\n returning: useReturningForCheck,\n });\n\n return {\n query,\n op: \"delete\",\n expectedAffectedRows: useReturningForCheck ? null : op.checkVersion ? 1n : null,\n expectedReturnedRows: useReturningForCheck ? 1 : null,\n };\n }\n\n override compileCheck(\n op: MutationOperation<AnySchema> & { type: \"check\" },\n ): CompiledMutation<CompiledQuery> {\n const sqlCompiler = this.getSQLCompiler(op.namespace);\n const table = this.getTable(op.schema, op.table);\n const idColumn = table.getIdColumn();\n const versionColumn = table.getVersionColumn();\n\n const externalId = op.id.externalId;\n const version = op.id.version;\n\n // Build a SELECT 1 query to check if the row exists with the correct version\n const condition = buildCondition(table.columns, (eb) =>\n eb.and(eb(idColumn.ormName, \"=\", externalId), eb(versionColumn.ormName, \"=\", version)),\n );\n\n if (typeof condition === \"boolean\") {\n throw new Error(\"Condition is a boolean, but should be a condition object.\");\n }\n\n return {\n query: sqlCompiler.compileCheck(table, condition),\n op: \"check\",\n expectedAffectedRows: null,\n expectedReturnedRows: 1, // Check that exactly 1 row was returned\n };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"generic-sql-uow-operation-compiler.js","names":["indexColumns: AnyColumn[]","orderDirection: \"asc\" | \"desc\"","orderBy: [AnyColumn, \"asc\" | \"desc\"][] | undefined","combinedWhere: Condition | undefined","conditions: Condition | undefined"],"sources":["../../../../src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts"],"sourcesContent":["import { UOWOperationCompiler } from \"../../shared/uow-operation-compiler\";\nimport type { CompiledQuery } from \"kysely\";\nimport type { DriverConfig } from \"../driver-config\";\nimport type { NamingResolver } from \"../../../naming/sql-naming\";\nimport type { SQLiteStorageMode } from \"../sqlite-storage\";\nimport type {\n RetrievalOperation,\n MutationOperation,\n CompiledMutation,\n} from \"../../../query/unit-of-work/unit-of-work\";\nimport type { AnyColumn, AnySchema } from \"../../../schema/create\";\nimport { buildCondition } from \"../../../query/condition-builder\";\nimport { createSQLQueryCompiler } from \"./create-sql-query-compiler\";\nimport { SQLQueryCompiler } from \"./sql-query-compiler\";\nimport { buildCursorCondition } from \"./cursor-utils\";\nimport type { Condition } from \"../../../query/condition-builder\";\nimport { buildFindOptions } from \"../../../query/orm/orm\";\nimport type { AnySelectClause } from \"../../../query/simple-query-interface\";\nimport { createColdKysely } from \"../migration/cold-kysely\";\n\n/**\n * Generic SQL UOW Operation Compiler.\n *\n * Uses SQLQueryCompiler for dialect-specific SQL generation while handling\n * high-level business logic like cursor pagination, version checking, and index resolution.\n */\nexport class GenericSQLUOWOperationCompiler extends UOWOperationCompiler<CompiledQuery> {\n private readonly sqliteStorageMode?: SQLiteStorageMode;\n\n constructor(\n driverConfig: DriverConfig,\n sqliteStorageMode?: SQLiteStorageMode,\n resolverFactory?: (schema: AnySchema, namespace: string | null) => NamingResolver,\n ) {\n super(driverConfig, resolverFactory);\n this.sqliteStorageMode = sqliteStorageMode;\n }\n\n /**\n * Get SQL compiler for a specific namespace\n */\n private getSQLCompiler(\n schema: AnySchema,\n namespace: string | null | undefined,\n ): SQLQueryCompiler {\n const resolver = this.getNamingResolver(schema, namespace ?? null);\n const kysely = createColdKysely(this.driverConfig.databaseType);\n const schemaName = resolver.getSchemaName();\n const scopedKysely = schemaName ? kysely.withSchema(schemaName) : kysely;\n return createSQLQueryCompiler(\n scopedKysely,\n this.driverConfig,\n this.sqliteStorageMode,\n resolver,\n );\n }\n\n override compileCount(\n op: RetrievalOperation<AnySchema> & { type: \"count\" },\n ): CompiledQuery | null {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n\n // Build where condition\n let conditions = op.options.where\n ? buildCondition(op.table.columns, op.options.where)\n : undefined;\n\n if (conditions === true) {\n conditions = undefined;\n }\n if (conditions === false) {\n return null;\n }\n\n return sqlCompiler.compileCount(op.table, { where: conditions });\n }\n\n override compileFind(op: RetrievalOperation<AnySchema> & { type: \"find\" }): CompiledQuery | null {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n\n // Extract options\n const {\n useIndex: _useIndex,\n orderByIndex,\n joins: join,\n after,\n before,\n pageSize,\n ...findManyOptions\n } = op.options;\n\n // Get index columns for ordering and cursor pagination\n let indexColumns: AnyColumn[] = [];\n let orderDirection: \"asc\" | \"desc\" = \"asc\";\n\n if (orderByIndex) {\n const index = op.table.indexes[orderByIndex.indexName];\n orderDirection = orderByIndex.direction;\n\n if (!index) {\n // If _primary index doesn't exist, fall back to internal ID column\n if (orderByIndex.indexName === \"_primary\") {\n indexColumns = [op.table.getIdColumn()];\n } else {\n throw new Error(\n `Index \"${orderByIndex.indexName}\" not found on table \"${op.table.name}\"`,\n );\n }\n } else {\n // Order by all columns in the index with the specified direction\n indexColumns = index.columns;\n }\n }\n\n // Convert orderByIndex to orderBy format\n let orderBy: [AnyColumn, \"asc\" | \"desc\"][] | undefined;\n if (indexColumns.length > 0) {\n orderBy = indexColumns.map((col) => [col, orderDirection]);\n }\n\n // Handle cursor pagination - build a cursor condition\n // TODO: Multi-column cursor pagination not yet supported\n if ((after || before) && indexColumns.length > 1) {\n throw new Error(\n \"Multi-column cursor pagination is not yet supported in Generic SQL implementation\",\n );\n }\n const cursorCondition = buildCursorCondition(\n after || before,\n indexColumns,\n orderDirection,\n !!after,\n this.driverConfig,\n this.sqliteStorageMode,\n );\n\n // Combine user where clause with cursor condition\n let combinedWhere: Condition | undefined;\n if (findManyOptions.where) {\n const whereResult = buildCondition(op.table.columns, findManyOptions.where);\n if (whereResult === true) {\n combinedWhere = undefined;\n } else if (whereResult === false) {\n return null;\n } else {\n combinedWhere = whereResult;\n }\n }\n\n if (cursorCondition) {\n if (combinedWhere) {\n combinedWhere = {\n type: \"and\",\n items: [combinedWhere, cursorCondition],\n };\n } else {\n combinedWhere = cursorCondition;\n }\n }\n\n // For cursor pagination, fetch one extra item to determine if there's a next page\n const effectiveLimit = pageSize && op.withCursor ? pageSize + 1 : pageSize;\n\n // When we have joins, use the query builder directly\n if (join && join.length > 0) {\n return sqlCompiler.compileFindMany(op.table, {\n select: (findManyOptions.select ?? true) as AnySelectClause,\n where: combinedWhere,\n orderBy,\n limit: effectiveLimit,\n join,\n });\n }\n\n // Otherwise, use buildFindOptions to process the query options\n const compiledOptions = buildFindOptions(op.table, {\n ...findManyOptions,\n where: combinedWhere ? () => combinedWhere! : undefined,\n orderBy: orderBy?.map(([col, dir]) => [col.name, dir]),\n limit: effectiveLimit,\n });\n\n if (compiledOptions === false) {\n return null;\n }\n\n return sqlCompiler.compileFindMany(op.table, compiledOptions);\n }\n\n override compileCreate(\n op: MutationOperation<AnySchema> & { type: \"create\" },\n ): CompiledMutation<CompiledQuery> | null {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n const table = this.getTable(op.schema, op.table);\n\n return {\n query: sqlCompiler.compileCreate(table, op.values),\n operation: op,\n op: \"create\",\n expectedAffectedRows: null, // creates don't need affected row checks\n expectedReturnedRows: null,\n };\n }\n\n override compileUpdate(\n op: MutationOperation<AnySchema> & { type: \"update\" },\n ): CompiledMutation<CompiledQuery> | null {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n const table = this.getTable(op.schema, op.table);\n const idColumn = table.getIdColumn();\n const versionColumn = table.getVersionColumn();\n\n const externalId = this.getExternalId(op.id);\n const versionToCheck = this.getVersionToCheck(op.id, op.checkVersion);\n\n // Build WHERE clause that filters by ID and optionally by version\n const conditionsResult =\n versionToCheck !== undefined\n ? buildCondition(table.columns, (eb) =>\n eb.and(eb(idColumn.name, \"=\", externalId), eb(versionColumn.name, \"=\", versionToCheck)),\n )\n : buildCondition(table.columns, (eb) => eb(idColumn.name, \"=\", externalId));\n\n if (conditionsResult === false) {\n return null;\n }\n\n const conditions: Condition | undefined =\n conditionsResult === true ? undefined : conditionsResult;\n\n // Determine if we should use RETURNING-based checking\n // Use RETURNING when driver supports it but doesn't support affected rows reporting\n const useReturningForCheck =\n op.checkVersion &&\n this.driverConfig.supportsReturning &&\n !this.driverConfig.supportsRowsAffected;\n\n const query = sqlCompiler.compileUpdate(table, {\n set: op.set,\n where: conditions,\n returning: useReturningForCheck,\n });\n\n return {\n query,\n operation: op,\n op: \"update\",\n expectedAffectedRows: useReturningForCheck ? null : op.checkVersion ? 1n : null,\n expectedReturnedRows: useReturningForCheck ? 1 : null,\n };\n }\n\n override compileDelete(\n op: MutationOperation<AnySchema> & { type: \"delete\" },\n ): CompiledMutation<CompiledQuery> | null {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n const table = this.getTable(op.schema, op.table);\n const idColumn = table.getIdColumn();\n const versionColumn = table.getVersionColumn();\n\n const externalId = this.getExternalId(op.id);\n const versionToCheck = this.getVersionToCheck(op.id, op.checkVersion);\n\n // Build WHERE clause that filters by ID and optionally by version\n const conditionsResult =\n versionToCheck !== undefined\n ? buildCondition(table.columns, (eb) =>\n eb.and(eb(idColumn.name, \"=\", externalId), eb(versionColumn.name, \"=\", versionToCheck)),\n )\n : buildCondition(table.columns, (eb) => eb(idColumn.name, \"=\", externalId));\n\n if (conditionsResult === false) {\n return null;\n }\n\n const conditions: Condition | undefined =\n conditionsResult === true ? undefined : conditionsResult;\n\n // Determine if we should use RETURNING-based checking\n // Use RETURNING when driver supports it but doesn't support affected rows reporting\n const useReturningForCheck =\n op.checkVersion &&\n this.driverConfig.supportsReturning &&\n !this.driverConfig.supportsRowsAffected;\n\n const query = sqlCompiler.compileDelete(table, {\n where: conditions,\n returning: useReturningForCheck,\n });\n\n return {\n query,\n operation: op,\n op: \"delete\",\n expectedAffectedRows: useReturningForCheck ? null : op.checkVersion ? 1n : null,\n expectedReturnedRows: useReturningForCheck ? 1 : null,\n };\n }\n\n override compileCheck(\n op: MutationOperation<AnySchema> & { type: \"check\" },\n ): CompiledMutation<CompiledQuery> {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n const table = this.getTable(op.schema, op.table);\n const idColumn = table.getIdColumn();\n const versionColumn = table.getVersionColumn();\n\n const externalId = op.id.externalId;\n const version = op.id.version;\n\n // Build a SELECT 1 query to check if the row exists with the correct version\n const condition = buildCondition(table.columns, (eb) =>\n eb.and(eb(idColumn.name, \"=\", externalId), eb(versionColumn.name, \"=\", version)),\n );\n\n if (typeof condition === \"boolean\") {\n throw new Error(\"Condition is a boolean, but should be a condition object.\");\n }\n\n return {\n query: sqlCompiler.compileCheck(table, condition),\n operation: op,\n op: \"check\",\n expectedAffectedRows: null,\n expectedReturnedRows: 1, // Check that exactly 1 row was returned\n };\n }\n}\n"],"mappings":"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"}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* @returns Array of SQL select strings in the format "tableName.columnName as alias"
|
|
14
14
|
* @internal
|
|
15
15
|
*/
|
|
16
|
-
function mapSelect(select, table, options = {}) {
|
|
16
|
+
function mapSelect(select, table, resolver, options = {}) {
|
|
17
17
|
const { relation, tableName = table.name } = options;
|
|
18
18
|
const out = [];
|
|
19
19
|
const keys = Array.isArray(select) ? select : Object.keys(table.columns);
|
|
@@ -21,13 +21,15 @@ function mapSelect(select, table, options = {}) {
|
|
|
21
21
|
const col = table.columns[key];
|
|
22
22
|
if (Array.isArray(select) && col.isHidden) continue;
|
|
23
23
|
const name = relation ? `${relation}:${key}` : key;
|
|
24
|
-
|
|
24
|
+
const columnName = resolver ? resolver.getColumnName(table.name, col.name) : col.name;
|
|
25
|
+
out.push(`${tableName}.${columnName} as ${name}`);
|
|
25
26
|
}
|
|
26
27
|
for (const key in table.columns) {
|
|
27
28
|
const col = table.columns[key];
|
|
28
29
|
if (col.isHidden && !keys.includes(key)) {
|
|
29
30
|
const name = relation ? `${relation}:${key}` : key;
|
|
30
|
-
|
|
31
|
+
const columnName = resolver ? resolver.getColumnName(table.name, col.name) : col.name;
|
|
32
|
+
out.push(`${tableName}.${columnName} as ${name}`);
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
35
|
return out;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select-builder.js","names":["out: string[]","extendedKeys: string[]"],"sources":["../../../../src/adapters/generic-sql/query/select-builder.ts"],"sourcesContent":["import type { AnyTable } from \"../../../schema/create\";\nimport type { AnySelectClause } from \"../../../query/simple-query-interface\";\n\n/**\n * Maps a select clause to SQL column names with optional aliases.\n *\n * Converts application-level select clauses (either array of keys or \"select all\")\n * into SQL-compatible column selections with proper aliasing for relations.\n *\n * @param select - The select clause (array of keys or true for all columns)\n * @param table - The table schema containing column definitions\n * @param options - Optional configuration\n * @param options.relation - Relation name to prefix in aliases (for joined data)\n * @param options.tableName - Override the table name in the SQL (defaults to table.name)\n * @returns Array of SQL select strings in the format \"tableName.columnName as alias\"\n * @internal\n */\nexport function mapSelect(\n select: AnySelectClause,\n table: AnyTable,\n options: {\n relation?: string;\n tableName?: string;\n } = {},\n): string[] {\n const { relation, tableName = table.name } = options;\n const out: string[] = [];\n const keys = Array.isArray(select) ? select : Object.keys(table.columns);\n\n for (const key of keys) {\n const col = table.columns[key];\n\n // Skip hidden columns when explicitly selecting\n if (Array.isArray(select) && col.isHidden) {\n continue;\n }\n\n // Add the column to the select list\n const name = relation ? `${relation}:${key}` : key;\n out.push(`${tableName}.${
|
|
1
|
+
{"version":3,"file":"select-builder.js","names":["out: string[]","extendedKeys: string[]"],"sources":["../../../../src/adapters/generic-sql/query/select-builder.ts"],"sourcesContent":["import type { AnyTable } from \"../../../schema/create\";\nimport type { AnySelectClause } from \"../../../query/simple-query-interface\";\nimport type { NamingResolver } from \"../../../naming/sql-naming\";\n\n/**\n * Maps a select clause to SQL column names with optional aliases.\n *\n * Converts application-level select clauses (either array of keys or \"select all\")\n * into SQL-compatible column selections with proper aliasing for relations.\n *\n * @param select - The select clause (array of keys or true for all columns)\n * @param table - The table schema containing column definitions\n * @param options - Optional configuration\n * @param options.relation - Relation name to prefix in aliases (for joined data)\n * @param options.tableName - Override the table name in the SQL (defaults to table.name)\n * @returns Array of SQL select strings in the format \"tableName.columnName as alias\"\n * @internal\n */\nexport function mapSelect(\n select: AnySelectClause,\n table: AnyTable,\n resolver: NamingResolver | undefined,\n options: {\n relation?: string;\n tableName?: string;\n } = {},\n): string[] {\n const { relation, tableName = table.name } = options;\n const out: string[] = [];\n const keys = Array.isArray(select) ? select : Object.keys(table.columns);\n\n for (const key of keys) {\n const col = table.columns[key];\n\n // Skip hidden columns when explicitly selecting\n if (Array.isArray(select) && col.isHidden) {\n continue;\n }\n\n // Add the column to the select list\n const name = relation ? `${relation}:${key}` : key;\n const columnName = resolver ? resolver.getColumnName(table.name, col.name) : col.name;\n out.push(`${tableName}.${columnName} as ${name}`);\n }\n\n // Always include hidden columns (for FragnoId construction with internal ID and version)\n for (const key in table.columns) {\n const col = table.columns[key];\n if (col.isHidden && !keys.includes(key)) {\n const name = relation ? `${relation}:${key}` : key;\n const columnName = resolver ? resolver.getColumnName(table.name, col.name) : col.name;\n out.push(`${tableName}.${columnName} as ${name}`);\n }\n }\n\n return out;\n}\n\n/**\n * Result type from compiling a select clause with extensions.\n * @internal\n */\nexport interface CompiledSelect {\n /**\n * The final select clause to use in the query\n */\n result: AnySelectClause;\n\n /**\n * Keys that were added to the select clause (not originally requested)\n */\n extendedKeys: string[];\n\n /**\n * Removes the extended keys from a record (mutates the record).\n * Used to clean up keys that were only needed for join operations.\n *\n * @param record - The record to remove extended keys from\n * @returns The same record with extended keys removed\n */\n removeExtendedKeys: (record: Record<string, unknown>) => Record<string, unknown>;\n}\n\n/**\n * Builder for extending a select clause with additional keys.\n * @internal\n */\nexport interface SelectBuilder {\n /**\n * Adds a key to the select clause if not already present.\n * Tracks which keys were added for later removal.\n *\n * @param key - The key to add to the select clause\n */\n extend: (key: string) => void;\n\n /**\n * Compiles the select clause into its final form.\n *\n * @returns The compiled select information\n */\n compile: () => CompiledSelect;\n}\n\n/**\n * Creates a builder that can extend a select clause with additional keys.\n *\n * This is useful when you need to temporarily include columns for join operations\n * or other internal processing, but don't want them in the final result.\n *\n * @param original - The original select clause from the user\n * @returns A select builder with extend() and compile() methods\n * @internal\n */\nexport function extendSelect(original: AnySelectClause): SelectBuilder {\n const select = Array.isArray(original) ? new Set(original) : true;\n const extendedKeys: string[] = [];\n\n return {\n extend(key) {\n if (select === true || select.has(key)) {\n return;\n }\n\n select.add(key);\n extendedKeys.push(key);\n },\n compile() {\n return {\n result: select instanceof Set ? Array.from(select) : true,\n extendedKeys,\n removeExtendedKeys(record) {\n for (const key of extendedKeys) {\n delete record[key];\n }\n return record;\n },\n };\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,SAAgB,UACd,QACA,OACA,UACA,UAGI,EAAE,EACI;CACV,MAAM,EAAE,UAAU,YAAY,MAAM,SAAS;CAC7C,MAAMA,MAAgB,EAAE;CACxB,MAAM,OAAO,MAAM,QAAQ,OAAO,GAAG,SAAS,OAAO,KAAK,MAAM,QAAQ;AAExE,MAAK,MAAM,OAAO,MAAM;EACtB,MAAM,MAAM,MAAM,QAAQ;AAG1B,MAAI,MAAM,QAAQ,OAAO,IAAI,IAAI,SAC/B;EAIF,MAAM,OAAO,WAAW,GAAG,SAAS,GAAG,QAAQ;EAC/C,MAAM,aAAa,WAAW,SAAS,cAAc,MAAM,MAAM,IAAI,KAAK,GAAG,IAAI;AACjF,MAAI,KAAK,GAAG,UAAU,GAAG,WAAW,MAAM,OAAO;;AAInD,MAAK,MAAM,OAAO,MAAM,SAAS;EAC/B,MAAM,MAAM,MAAM,QAAQ;AAC1B,MAAI,IAAI,YAAY,CAAC,KAAK,SAAS,IAAI,EAAE;GACvC,MAAM,OAAO,WAAW,GAAG,SAAS,GAAG,QAAQ;GAC/C,MAAM,aAAa,WAAW,SAAS,cAAc,MAAM,MAAM,IAAI,KAAK,GAAG,IAAI;AACjF,OAAI,KAAK,GAAG,UAAU,GAAG,WAAW,MAAM,OAAO;;;AAIrD,QAAO;;;;;;;;;;;;AA2DT,SAAgB,aAAa,UAA0C;CACrE,MAAM,SAAS,MAAM,QAAQ,SAAS,GAAG,IAAI,IAAI,SAAS,GAAG;CAC7D,MAAMC,eAAyB,EAAE;AAEjC,QAAO;EACL,OAAO,KAAK;AACV,OAAI,WAAW,QAAQ,OAAO,IAAI,IAAI,CACpC;AAGF,UAAO,IAAI,IAAI;AACf,gBAAa,KAAK,IAAI;;EAExB,UAAU;AACR,UAAO;IACL,QAAQ,kBAAkB,MAAM,MAAM,KAAK,OAAO,GAAG;IACrD;IACA,mBAAmB,QAAQ;AACzB,UAAK,MAAM,OAAO,aAChB,QAAO,OAAO;AAEhB,YAAO;;IAEV;;EAEJ"}
|
|
@@ -17,26 +17,28 @@ var SQLQueryCompiler = class {
|
|
|
17
17
|
db;
|
|
18
18
|
driverConfig;
|
|
19
19
|
database;
|
|
20
|
-
|
|
20
|
+
resolver;
|
|
21
21
|
encoder;
|
|
22
|
-
|
|
22
|
+
sqliteStorageMode;
|
|
23
|
+
constructor(db, driverConfig, sqliteStorageMode, resolver) {
|
|
23
24
|
this.db = db;
|
|
24
25
|
this.driverConfig = driverConfig;
|
|
25
26
|
this.database = driverConfig.databaseType;
|
|
26
|
-
this.
|
|
27
|
-
this.
|
|
27
|
+
this.resolver = resolver;
|
|
28
|
+
this.sqliteStorageMode = sqliteStorageMode;
|
|
29
|
+
this.encoder = new UnitOfWorkEncoder(driverConfig, db, sqliteStorageMode, resolver);
|
|
28
30
|
}
|
|
29
31
|
/**
|
|
30
32
|
* Get the physical table name, applying namespace mapping if provided.
|
|
31
33
|
*/
|
|
32
34
|
getTableName(table) {
|
|
33
|
-
return this.
|
|
35
|
+
return this.resolver ? this.resolver.getTableName(table.name) : table.name;
|
|
34
36
|
}
|
|
35
37
|
/**
|
|
36
38
|
* Build WHERE clause from a condition tree.
|
|
37
39
|
*/
|
|
38
40
|
buildWhereClause(condition, eb, table) {
|
|
39
|
-
return buildWhere(condition, eb, this.driverConfig, this.
|
|
41
|
+
return buildWhere(condition, eb, this.driverConfig, this.sqliteStorageMode, this.resolver, table);
|
|
40
42
|
}
|
|
41
43
|
/**
|
|
42
44
|
* Process joins recursively to support nested joins.
|
|
@@ -49,7 +51,7 @@ var SQLQueryCompiler = class {
|
|
|
49
51
|
const targetTable = relation.table;
|
|
50
52
|
const fullPath = parentPath ? `${parentPath}:${relation.name}` : relation.name;
|
|
51
53
|
const joinName = fullPath.replace(/:/g, "_");
|
|
52
|
-
mappedSelect.push(...mapSelect(joinOptions.select, targetTable, {
|
|
54
|
+
mappedSelect.push(...mapSelect(joinOptions.select, targetTable, this.resolver, {
|
|
53
55
|
relation: fullPath,
|
|
54
56
|
tableName: joinName
|
|
55
57
|
}));
|
|
@@ -57,7 +59,7 @@ var SQLQueryCompiler = class {
|
|
|
57
59
|
const conditions = [];
|
|
58
60
|
for (const [left, right] of relation.on) {
|
|
59
61
|
const actualRight = targetTable.columns[right]?.role === "external-id" ? "_internalId" : right;
|
|
60
|
-
conditions.push(eb(`${parentTableName}.${parentTable.columns[left].name}`, "=", eb.ref(`${joinName}.${targetTable.columns[actualRight].name}`)));
|
|
62
|
+
conditions.push(eb(`${parentTableName}.${this.resolver ? this.resolver.getColumnName(parentTable.name, parentTable.columns[left].name) : parentTable.columns[left].name}`, "=", eb.ref(`${joinName}.${this.resolver ? this.resolver.getColumnName(targetTable.name, targetTable.columns[actualRight].name) : targetTable.columns[actualRight].name}`)));
|
|
61
63
|
}
|
|
62
64
|
if (joinOptions.where) conditions.push(this.buildWhereClause(joinOptions.where, eb, targetTable));
|
|
63
65
|
return eb.and(conditions);
|
|
@@ -83,12 +85,12 @@ var SQLQueryCompiler = class {
|
|
|
83
85
|
if (whereQuery) query = query.where((eb) => this.buildWhereClause(whereQuery, eb, table));
|
|
84
86
|
if (options.offset !== void 0) query = this.applyOffset(query, options.offset);
|
|
85
87
|
if (options.limit !== void 0) query = this.applyLimit(query, options.limit);
|
|
86
|
-
if (options.orderBy) for (const [col, mode] of options.orderBy) query = query.orderBy(fullSQLName(col, this.
|
|
88
|
+
if (options.orderBy) for (const [col, mode] of options.orderBy) query = query.orderBy(fullSQLName(col, this.resolver), mode);
|
|
87
89
|
const selectBuilder = extendSelect(options.select);
|
|
88
90
|
const mappedSelect = [];
|
|
89
91
|
if (options.join && options.join.length > 0) query = this.processJoins(query, options.join, table, this.getTableName(table), mappedSelect);
|
|
90
92
|
const compiledSelect = selectBuilder.compile();
|
|
91
|
-
mappedSelect.push(...mapSelect(compiledSelect.result, table, { tableName: this.getTableName(table) }));
|
|
93
|
+
mappedSelect.push(...mapSelect(compiledSelect.result, table, this.resolver, { tableName: this.getTableName(table) }));
|
|
92
94
|
return query.select(mappedSelect).compile();
|
|
93
95
|
}
|
|
94
96
|
/**
|
|
@@ -102,7 +104,7 @@ var SQLQueryCompiler = class {
|
|
|
102
104
|
});
|
|
103
105
|
let insert = this.db.insertInto(this.getTableName(table)).values(encodedValues);
|
|
104
106
|
if (this.driverConfig.supportsReturning) {
|
|
105
|
-
const columns = mapSelect(true, table, { tableName: this.getTableName(table) });
|
|
107
|
+
const columns = mapSelect(true, table, this.resolver, { tableName: this.getTableName(table) });
|
|
106
108
|
insert = this.applyReturning(insert, columns);
|
|
107
109
|
}
|
|
108
110
|
return insert.compile();
|
|
@@ -117,7 +119,8 @@ var SQLQueryCompiler = class {
|
|
|
117
119
|
generateDefaults: false
|
|
118
120
|
});
|
|
119
121
|
const versionCol = table.getVersionColumn();
|
|
120
|
-
|
|
122
|
+
const versionColumnName = this.resolver ? this.resolver.getColumnName(table.name, versionCol.name) : versionCol.name;
|
|
123
|
+
encoded[versionColumnName] = sql`coalesce(${sql.ref(versionColumnName)}, 0) + 1`;
|
|
121
124
|
let query = this.db.updateTable(this.getTableName(table)).set(encoded);
|
|
122
125
|
if (options.where) query = query.where((eb) => this.buildWhereClause(options.where, eb, table));
|
|
123
126
|
if (options.returning && this.driverConfig.supportsReturning) return query.returning(sql`1`.as("_returned")).compile();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql-query-compiler.js","names":["mappedSelect: string[]","insert: AnyInsertQueryBuilder"],"sources":["../../../../src/adapters/generic-sql/query/sql-query-compiler.ts"],"sourcesContent":["import type {\n CompiledQuery,\n Kysely,\n ExpressionBuilder,\n ExpressionWrapper,\n SelectQueryBuilder,\n InsertQueryBuilder,\n} from \"kysely\";\nimport { sql } from \"kysely\";\nimport type { SqlBool } from \"kysely\";\nimport type { AnyColumn, AnyTable } from \"../../../schema/create\";\nimport type { Condition } from \"../../../query/condition-builder\";\nimport type { DriverConfig, SupportedDatabase } from \"../driver-config\";\nimport type { TableNameMapper } from \"../../shared/table-name-mapper\";\nimport { buildWhere, fullSQLName } from \"./where-builder\";\nimport { mapSelect, extendSelect } from \"./select-builder\";\nimport type { CompiledJoin } from \"../../../query/orm/orm\";\nimport { UnitOfWorkEncoder } from \"../uow-encoder\";\n\n/**\n * Type helpers for Kysely query builders.\n *\n * These use `any` for database schema types because at this abstraction layer,\n * we cannot know the specific database schema - we work with generic query\n * compilation that needs to work across any schema.\n */\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyKysely = Kysely<any>;\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyExpressionBuilder = ExpressionBuilder<any, any>;\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyExpressionWrapper = ExpressionWrapper<any, any, SqlBool>;\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnySelectQueryBuilder<O = any> = SelectQueryBuilder<any, any, O>;\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyInsertQueryBuilder<O = any> = InsertQueryBuilder<any, any, O>;\n\n/**\n * Options for compiling a find operation\n */\nexport interface FindManyCompilerOptions {\n select: true | string[];\n where?: Condition;\n orderBy?: [AnyColumn, \"asc\" | \"desc\"][];\n limit?: number;\n offset?: number;\n join?: CompiledJoin[];\n}\n\n/**\n * Options for compiling a count operation\n */\nexport interface CountCompilerOptions {\n where?: Condition;\n}\n\n/**\n * Options for compiling an update operation\n */\nexport interface UpdateCompilerOptions {\n where?: Condition;\n set: Record<string, unknown>;\n /**\n * Whether to add RETURNING clause to the UPDATE query.\n * Used for version conflict detection when driver supports RETURNING but not affected rows.\n */\n returning?: boolean;\n}\n\n/**\n * Options for compiling a delete operation\n */\nexport interface DeleteCompilerOptions {\n where?: Condition;\n /**\n * Whether to add RETURNING clause to the DELETE query.\n * Used for version conflict detection when driver supports RETURNING but not affected rows.\n */\n returning?: boolean;\n}\n\n/**\n * Abstract base class for SQL query compilation.\n *\n * Similar to SQLGenerator for migrations, this class provides a framework\n * for compiling runtime queries with dialect-specific behavior.\n *\n * Each database dialect extends this class and implements the abstract methods\n * to handle database-specific SQL generation (like .limit() vs .top()).\n */\nexport abstract class SQLQueryCompiler {\n protected readonly db: AnyKysely;\n protected readonly driverConfig: DriverConfig;\n protected readonly database: SupportedDatabase;\n protected readonly mapper?: TableNameMapper;\n protected readonly encoder: UnitOfWorkEncoder;\n\n constructor(db: AnyKysely, driverConfig: DriverConfig, mapper?: TableNameMapper) {\n this.db = db;\n this.driverConfig = driverConfig;\n this.database = driverConfig.databaseType;\n this.mapper = mapper;\n this.encoder = new UnitOfWorkEncoder(driverConfig, db, mapper);\n }\n\n /**\n * Apply LIMIT clause to a query.\n * Different databases use different syntax (.limit() vs .top()).\n */\n protected abstract applyLimit<T>(query: T & { limit(limit: number): T }, limit: number): T;\n\n /**\n * Apply OFFSET clause to a query.\n * Some databases may not support offset.\n */\n protected abstract applyOffset<T>(query: T & { offset(offset: number): T }, offset: number): T;\n\n /**\n * Apply RETURNING clause to an insert/update query.\n * Returns the query with RETURNING if supported, otherwise returns as-is.\n */\n protected abstract applyReturning<T>(\n query: T & { returning(columns: string[]): T },\n columns: string[],\n ): T;\n\n /**\n * Get the physical table name, applying namespace mapping if provided.\n */\n protected getTableName(table: AnyTable): string {\n return this.mapper ? this.mapper.toPhysical(table.name) : table.name;\n }\n\n /**\n * Build WHERE clause from a condition tree.\n */\n protected buildWhereClause(condition: Condition, eb: AnyExpressionBuilder, table: AnyTable) {\n return buildWhere(condition, eb, this.driverConfig, this.mapper, table);\n }\n\n /**\n * Process joins recursively to support nested joins.\n */\n protected processJoins<O>(\n query: AnySelectQueryBuilder<O>,\n joins: CompiledJoin[],\n parentTable: AnyTable,\n parentTableName: string,\n mappedSelect: string[],\n parentPath: string = \"\",\n ): AnySelectQueryBuilder<O> {\n let result = query;\n\n for (const join of joins) {\n const { options: joinOptions, relation } = join;\n\n if (joinOptions === false) {\n continue;\n }\n\n const targetTable = relation.table;\n // Build the full path for this join (e.g., \"author:inviter\")\n const fullPath = parentPath ? `${parentPath}:${relation.name}` : relation.name;\n // SQL table alias uses underscores (e.g., \"author_inviter\")\n const joinName = fullPath.replace(/:/g, \"_\");\n\n // Update select\n mappedSelect.push(\n ...mapSelect(joinOptions.select, targetTable, {\n relation: fullPath, // Use full path with colons for column aliases\n tableName: joinName, // Use underscore version for table name\n }),\n );\n\n result = result.leftJoin(`${this.getTableName(targetTable)} as ${joinName}`, (b) =>\n b.on((eb) => {\n const conditions = [];\n for (const [left, right] of relation.on) {\n // Foreign keys always use internal IDs\n // If the relation references an external ID column (any name), translate to \"_internalId\"\n const rightCol = targetTable.columns[right];\n const actualRight = rightCol?.role === \"external-id\" ? \"_internalId\" : right;\n\n conditions.push(\n eb(\n `${parentTableName}.${parentTable.columns[left].name}`,\n \"=\",\n eb.ref(`${joinName}.${targetTable.columns[actualRight].name}`),\n ),\n );\n }\n\n if (joinOptions.where) {\n conditions.push(this.buildWhereClause(joinOptions.where, eb, targetTable));\n }\n\n return eb.and(conditions);\n }),\n );\n\n // Recursively process nested joins with the full path\n if (joinOptions.join && joinOptions.join.length > 0) {\n result = this.processJoins(\n result,\n joinOptions.join,\n targetTable,\n joinName,\n mappedSelect,\n fullPath,\n );\n }\n }\n\n return result;\n }\n\n /**\n * Compile a COUNT query.\n */\n compileCount(table: AnyTable, options: CountCompilerOptions): CompiledQuery {\n let query = this.db\n .selectFrom(this.getTableName(table))\n .select(this.db.fn.countAll().as(\"count\"));\n\n if (options.where) {\n query = query.where((b) => this.buildWhereClause(options.where!, b, table));\n }\n\n return query.compile();\n }\n\n /**\n * Compile a FIND MANY query.\n */\n compileFindMany(table: AnyTable, options: FindManyCompilerOptions): CompiledQuery {\n let query = this.db.selectFrom(this.getTableName(table));\n\n // Apply WHERE clause\n const whereQuery = options.where;\n if (whereQuery) {\n query = query.where((eb) => this.buildWhereClause(whereQuery, eb, table));\n }\n\n // Apply OFFSET\n if (options.offset !== undefined) {\n query = this.applyOffset(query, options.offset);\n }\n\n // Apply LIMIT\n if (options.limit !== undefined) {\n query = this.applyLimit(query, options.limit);\n }\n\n // Apply ORDER BY\n if (options.orderBy) {\n for (const [col, mode] of options.orderBy) {\n query = query.orderBy(fullSQLName(col, this.mapper), mode);\n }\n }\n\n // Build SELECT with joins\n const selectBuilder = extendSelect(options.select);\n const mappedSelect: string[] = [];\n\n // Process joins if provided\n if (options.join && options.join.length > 0) {\n query = this.processJoins(query, options.join, table, this.getTableName(table), mappedSelect);\n }\n\n const compiledSelect = selectBuilder.compile();\n mappedSelect.push(\n ...mapSelect(compiledSelect.result, table, { tableName: this.getTableName(table) }),\n );\n\n return query.select(mappedSelect).compile();\n }\n\n /**\n * Compile a CREATE (INSERT) query.\n */\n compileCreate(table: AnyTable, values: Record<string, unknown>): CompiledQuery {\n // Encode application values to database format (resolves FragnoId, generates defaults, serializes)\n const encodedValues = this.encoder.encodeForDatabase({\n values,\n table,\n generateDefaults: true,\n });\n\n let insert: AnyInsertQueryBuilder = this.db\n .insertInto(this.getTableName(table))\n .values(encodedValues);\n\n // Apply RETURNING if supported\n if (this.driverConfig.supportsReturning) {\n const columns = mapSelect(true, table, { tableName: this.getTableName(table) });\n insert = this.applyReturning(insert, columns);\n }\n\n return insert.compile();\n }\n\n /**\n * Compile an UPDATE query.\n */\n compileUpdate(table: AnyTable, options: UpdateCompilerOptions): CompiledQuery {\n const encoded = this.encoder.encodeForDatabase({\n values: options.set,\n table,\n generateDefaults: false,\n });\n\n // Add version increment (must be added after encoding, as a raw SQL expression)\n const versionCol = table.getVersionColumn();\n encoded[versionCol.name] = sql.raw(`COALESCE(${versionCol.name}, 0) + 1`);\n\n let query = this.db.updateTable(this.getTableName(table)).set(encoded);\n\n if (options.where) {\n query = query.where((eb) => this.buildWhereClause(options.where!, eb, table));\n }\n\n // Apply RETURNING if requested and supported\n // Use sql template tag for literal value (not a column name)\n if (options.returning && this.driverConfig.supportsReturning) {\n return query.returning(sql<number>`1`.as(\"_returned\")).compile();\n }\n\n return query.compile();\n }\n\n /**\n * Compile a DELETE query.\n */\n compileDelete(table: AnyTable, options: DeleteCompilerOptions): CompiledQuery {\n let query = this.db.deleteFrom(this.getTableName(table));\n\n if (options.where) {\n query = query.where((eb) => this.buildWhereClause(options.where!, eb, table));\n }\n\n // Apply RETURNING if requested and supported\n // Use sql template tag for literal value (not a column name)\n if (options.returning && this.driverConfig.supportsReturning) {\n return query.returning(sql<number>`1`.as(\"_returned\")).compile();\n }\n\n return query.compile();\n }\n\n /**\n * Compile a CHECK query (SELECT 1 to verify a row exists).\n */\n compileCheck(table: AnyTable, where: Condition): CompiledQuery {\n const query = this.db\n .selectFrom(this.getTableName(table))\n .select(sql<number>`1`.as(\"exists\"))\n .where((eb) => this.buildWhereClause(where, eb, table))\n .limit(1);\n\n return query.compile();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sql-query-compiler.js","names":["mappedSelect: string[]","insert: AnyInsertQueryBuilder"],"sources":["../../../../src/adapters/generic-sql/query/sql-query-compiler.ts"],"sourcesContent":["import type {\n CompiledQuery,\n Kysely,\n ExpressionBuilder,\n ExpressionWrapper,\n SelectQueryBuilder,\n InsertQueryBuilder,\n} from \"kysely\";\nimport { sql } from \"kysely\";\nimport type { SqlBool } from \"kysely\";\nimport type { AnyColumn, AnyTable } from \"../../../schema/create\";\nimport type { Condition } from \"../../../query/condition-builder\";\nimport type { DriverConfig, SupportedDatabase } from \"../driver-config\";\nimport type { SQLiteStorageMode } from \"../sqlite-storage\";\nimport type { NamingResolver } from \"../../../naming/sql-naming\";\nimport { buildWhere, fullSQLName } from \"./where-builder\";\nimport { mapSelect, extendSelect } from \"./select-builder\";\nimport type { CompiledJoin } from \"../../../query/orm/orm\";\nimport { UnitOfWorkEncoder } from \"../uow-encoder\";\n\n/**\n * Type helpers for Kysely query builders.\n *\n * These use `any` for database schema types because at this abstraction layer,\n * we cannot know the specific database schema - we work with generic query\n * compilation that needs to work across any schema.\n */\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyKysely = Kysely<any>;\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyExpressionBuilder = ExpressionBuilder<any, any>;\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyExpressionWrapper = ExpressionWrapper<any, any, SqlBool>;\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnySelectQueryBuilder<O = any> = SelectQueryBuilder<any, any, O>;\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyInsertQueryBuilder<O = any> = InsertQueryBuilder<any, any, O>;\n\n/**\n * Options for compiling a find operation\n */\nexport interface FindManyCompilerOptions {\n select: true | string[];\n where?: Condition;\n orderBy?: [AnyColumn, \"asc\" | \"desc\"][];\n limit?: number;\n offset?: number;\n join?: CompiledJoin[];\n}\n\n/**\n * Options for compiling a count operation\n */\nexport interface CountCompilerOptions {\n where?: Condition;\n}\n\n/**\n * Options for compiling an update operation\n */\nexport interface UpdateCompilerOptions {\n where?: Condition;\n set: Record<string, unknown>;\n /**\n * Whether to add RETURNING clause to the UPDATE query.\n * Used for version conflict detection when driver supports RETURNING but not affected rows.\n */\n returning?: boolean;\n}\n\n/**\n * Options for compiling a delete operation\n */\nexport interface DeleteCompilerOptions {\n where?: Condition;\n /**\n * Whether to add RETURNING clause to the DELETE query.\n * Used for version conflict detection when driver supports RETURNING but not affected rows.\n */\n returning?: boolean;\n}\n\n/**\n * Abstract base class for SQL query compilation.\n *\n * Similar to SQLGenerator for migrations, this class provides a framework\n * for compiling runtime queries with dialect-specific behavior.\n *\n * Each database dialect extends this class and implements the abstract methods\n * to handle database-specific SQL generation (like .limit() vs .top()).\n */\nexport abstract class SQLQueryCompiler {\n protected readonly db: AnyKysely;\n protected readonly driverConfig: DriverConfig;\n protected readonly database: SupportedDatabase;\n protected readonly resolver?: NamingResolver;\n protected readonly encoder: UnitOfWorkEncoder;\n protected readonly sqliteStorageMode?: SQLiteStorageMode;\n\n constructor(\n db: AnyKysely,\n driverConfig: DriverConfig,\n sqliteStorageMode?: SQLiteStorageMode,\n resolver?: NamingResolver,\n ) {\n this.db = db;\n this.driverConfig = driverConfig;\n this.database = driverConfig.databaseType;\n this.resolver = resolver;\n this.sqliteStorageMode = sqliteStorageMode;\n this.encoder = new UnitOfWorkEncoder(driverConfig, db, sqliteStorageMode, resolver);\n }\n\n /**\n * Apply LIMIT clause to a query.\n * Different databases use different syntax (.limit() vs .top()).\n */\n protected abstract applyLimit<T>(query: T & { limit(limit: number): T }, limit: number): T;\n\n /**\n * Apply OFFSET clause to a query.\n * Some databases may not support offset.\n */\n protected abstract applyOffset<T>(query: T & { offset(offset: number): T }, offset: number): T;\n\n /**\n * Apply RETURNING clause to an insert/update query.\n * Returns the query with RETURNING if supported, otherwise returns as-is.\n */\n protected abstract applyReturning<T>(\n query: T & { returning(columns: string[]): T },\n columns: string[],\n ): T;\n\n /**\n * Get the physical table name, applying namespace mapping if provided.\n */\n protected getTableName(table: AnyTable): string {\n return this.resolver ? this.resolver.getTableName(table.name) : table.name;\n }\n\n /**\n * Build WHERE clause from a condition tree.\n */\n protected buildWhereClause(condition: Condition, eb: AnyExpressionBuilder, table: AnyTable) {\n return buildWhere(\n condition,\n eb,\n this.driverConfig,\n this.sqliteStorageMode,\n this.resolver,\n table,\n );\n }\n\n /**\n * Process joins recursively to support nested joins.\n */\n protected processJoins<O>(\n query: AnySelectQueryBuilder<O>,\n joins: CompiledJoin[],\n parentTable: AnyTable,\n parentTableName: string,\n mappedSelect: string[],\n parentPath: string = \"\",\n ): AnySelectQueryBuilder<O> {\n let result = query;\n\n for (const join of joins) {\n const { options: joinOptions, relation } = join;\n\n if (joinOptions === false) {\n continue;\n }\n\n const targetTable = relation.table;\n // Build the full path for this join (e.g., \"author:inviter\")\n const fullPath = parentPath ? `${parentPath}:${relation.name}` : relation.name;\n // SQL table alias uses underscores (e.g., \"author_inviter\")\n const joinName = fullPath.replace(/:/g, \"_\");\n\n // Update select\n mappedSelect.push(\n ...mapSelect(joinOptions.select, targetTable, this.resolver, {\n relation: fullPath, // Use full path with colons for column aliases\n tableName: joinName, // Use underscore version for table name\n }),\n );\n\n result = result.leftJoin(`${this.getTableName(targetTable)} as ${joinName}`, (b) =>\n b.on((eb) => {\n const conditions = [];\n for (const [left, right] of relation.on) {\n // Foreign keys always use internal IDs\n // If the relation references an external ID column (any name), translate to \"_internalId\"\n const rightCol = targetTable.columns[right];\n const actualRight = rightCol?.role === \"external-id\" ? \"_internalId\" : right;\n\n conditions.push(\n eb(\n `${parentTableName}.${\n this.resolver\n ? this.resolver.getColumnName(parentTable.name, parentTable.columns[left].name)\n : parentTable.columns[left].name\n }`,\n \"=\",\n eb.ref(\n `${joinName}.${\n this.resolver\n ? this.resolver.getColumnName(\n targetTable.name,\n targetTable.columns[actualRight].name,\n )\n : targetTable.columns[actualRight].name\n }`,\n ),\n ),\n );\n }\n\n if (joinOptions.where) {\n conditions.push(this.buildWhereClause(joinOptions.where, eb, targetTable));\n }\n\n return eb.and(conditions);\n }),\n );\n\n // Recursively process nested joins with the full path\n if (joinOptions.join && joinOptions.join.length > 0) {\n result = this.processJoins(\n result,\n joinOptions.join,\n targetTable,\n joinName,\n mappedSelect,\n fullPath,\n );\n }\n }\n\n return result;\n }\n\n /**\n * Compile a COUNT query.\n */\n compileCount(table: AnyTable, options: CountCompilerOptions): CompiledQuery {\n let query = this.db\n .selectFrom(this.getTableName(table))\n .select(this.db.fn.countAll().as(\"count\"));\n\n if (options.where) {\n query = query.where((b) => this.buildWhereClause(options.where!, b, table));\n }\n\n return query.compile();\n }\n\n /**\n * Compile a FIND MANY query.\n */\n compileFindMany(table: AnyTable, options: FindManyCompilerOptions): CompiledQuery {\n let query = this.db.selectFrom(this.getTableName(table));\n\n // Apply WHERE clause\n const whereQuery = options.where;\n if (whereQuery) {\n query = query.where((eb) => this.buildWhereClause(whereQuery, eb, table));\n }\n\n // Apply OFFSET\n if (options.offset !== undefined) {\n query = this.applyOffset(query, options.offset);\n }\n\n // Apply LIMIT\n if (options.limit !== undefined) {\n query = this.applyLimit(query, options.limit);\n }\n\n // Apply ORDER BY\n if (options.orderBy) {\n for (const [col, mode] of options.orderBy) {\n query = query.orderBy(fullSQLName(col, this.resolver), mode);\n }\n }\n\n // Build SELECT with joins\n const selectBuilder = extendSelect(options.select);\n const mappedSelect: string[] = [];\n\n // Process joins if provided\n if (options.join && options.join.length > 0) {\n query = this.processJoins(query, options.join, table, this.getTableName(table), mappedSelect);\n }\n\n const compiledSelect = selectBuilder.compile();\n mappedSelect.push(\n ...mapSelect(compiledSelect.result, table, this.resolver, {\n tableName: this.getTableName(table),\n }),\n );\n\n return query.select(mappedSelect).compile();\n }\n\n /**\n * Compile a CREATE (INSERT) query.\n */\n compileCreate(table: AnyTable, values: Record<string, unknown>): CompiledQuery {\n // Encode application values to database format (resolves FragnoId, generates defaults, serializes)\n const encodedValues = this.encoder.encodeForDatabase({\n values,\n table,\n generateDefaults: true,\n });\n\n let insert: AnyInsertQueryBuilder = this.db\n .insertInto(this.getTableName(table))\n .values(encodedValues);\n\n // Apply RETURNING if supported\n if (this.driverConfig.supportsReturning) {\n const columns = mapSelect(true, table, this.resolver, {\n tableName: this.getTableName(table),\n });\n insert = this.applyReturning(insert, columns);\n }\n\n return insert.compile();\n }\n\n /**\n * Compile an UPDATE query.\n */\n compileUpdate(table: AnyTable, options: UpdateCompilerOptions): CompiledQuery {\n const encoded = this.encoder.encodeForDatabase({\n values: options.set,\n table,\n generateDefaults: false,\n });\n\n // Add version increment (must be added after encoding, as a raw SQL expression)\n const versionCol = table.getVersionColumn();\n const versionColumnName = this.resolver\n ? this.resolver.getColumnName(table.name, versionCol.name)\n : versionCol.name;\n encoded[versionColumnName] = sql`coalesce(${sql.ref(versionColumnName)}, 0) + 1`;\n\n let query = this.db.updateTable(this.getTableName(table)).set(encoded);\n\n if (options.where) {\n query = query.where((eb) => this.buildWhereClause(options.where!, eb, table));\n }\n\n // Apply RETURNING if requested and supported\n // Use sql template tag for literal value (not a column name)\n if (options.returning && this.driverConfig.supportsReturning) {\n return query.returning(sql<number>`1`.as(\"_returned\")).compile();\n }\n\n return query.compile();\n }\n\n /**\n * Compile a DELETE query.\n */\n compileDelete(table: AnyTable, options: DeleteCompilerOptions): CompiledQuery {\n let query = this.db.deleteFrom(this.getTableName(table));\n\n if (options.where) {\n query = query.where((eb) => this.buildWhereClause(options.where!, eb, table));\n }\n\n // Apply RETURNING if requested and supported\n // Use sql template tag for literal value (not a column name)\n if (options.returning && this.driverConfig.supportsReturning) {\n return query.returning(sql<number>`1`.as(\"_returned\")).compile();\n }\n\n return query.compile();\n }\n\n /**\n * Compile a CHECK query (SELECT 1 to verify a row exists).\n */\n compileCheck(table: AnyTable, where: Condition): CompiledQuery {\n const query = this.db\n .selectFrom(this.getTableName(table))\n .select(sql<number>`1`.as(\"exists\"))\n .where((eb) => this.buildWhereClause(where, eb, table))\n .limit(1);\n\n return query.compile();\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Column, FragnoId, FragnoReference } from "../../../schema/create.js";
|
|
2
|
+
import { sqliteStorageDefault } from "../sqlite-storage.js";
|
|
2
3
|
import { createSQLSerializer } from "../../../query/serialize/create-sql-serializer.js";
|
|
3
4
|
import { ReferenceSubquery, resolveFragnoIdValue } from "../../../query/value-encoding.js";
|
|
5
|
+
import { isDbNow } from "../../../query/db-now.js";
|
|
4
6
|
import { sql } from "kysely";
|
|
5
7
|
|
|
6
8
|
//#region src/adapters/generic-sql/query/where-builder.ts
|
|
@@ -8,12 +10,12 @@ import { sql } from "kysely";
|
|
|
8
10
|
* Returns the fully qualified SQL name for a column (table.column).
|
|
9
11
|
*
|
|
10
12
|
* @param column - The column to get the full name for
|
|
11
|
-
* @param
|
|
13
|
+
* @param resolver - Optional naming resolver for namespace prefixing
|
|
12
14
|
* @returns The fully qualified SQL name in the format "tableName.columnName"
|
|
13
15
|
* @internal
|
|
14
16
|
*/
|
|
15
|
-
function fullSQLName(column,
|
|
16
|
-
return `${
|
|
17
|
+
function fullSQLName(column, resolver) {
|
|
18
|
+
return `${resolver ? resolver.getTableName(column.tableName) : column.tableName}.${resolver ? resolver.getColumnName(column.tableName, column.name) : column.name}`;
|
|
17
19
|
}
|
|
18
20
|
/**
|
|
19
21
|
* Builds a WHERE clause expression from a Condition tree.
|
|
@@ -25,35 +27,41 @@ function fullSQLName(column, mapper) {
|
|
|
25
27
|
* @param condition - The condition tree to build the WHERE clause from
|
|
26
28
|
* @param eb - Kysely expression builder for constructing SQL expressions
|
|
27
29
|
* @param database - The database type (affects SQL generation)
|
|
28
|
-
* @param
|
|
30
|
+
* @param resolver - Optional naming resolver for namespace prefixing
|
|
29
31
|
* @param table - The table being queried (used for resolving reference columns)
|
|
30
32
|
* @returns A Kysely expression wrapper representing the WHERE clause
|
|
31
33
|
* @internal
|
|
32
34
|
*/
|
|
33
|
-
function buildWhere(condition, eb, driverConfig,
|
|
34
|
-
const serializer = createSQLSerializer(driverConfig);
|
|
35
|
+
function buildWhere(condition, eb, driverConfig, sqliteStorageMode, resolver, table) {
|
|
36
|
+
const serializer = createSQLSerializer(driverConfig, sqliteStorageMode);
|
|
35
37
|
if (condition.type === "compare") {
|
|
36
38
|
const left = condition.a;
|
|
37
39
|
const op = condition.operator;
|
|
38
40
|
let val = condition.b;
|
|
39
|
-
if (!(val instanceof Column)) if (
|
|
40
|
-
const
|
|
41
|
+
if (!(val instanceof Column)) if (isDbNow(val)) if (driverConfig.databaseType === "sqlite") {
|
|
42
|
+
const storageMode = sqliteStorageMode ?? sqliteStorageDefault;
|
|
43
|
+
const storage = left.type === "date" ? storageMode.dateStorage : storageMode.timestampStorage;
|
|
44
|
+
if ((left.type === "timestamp" || left.type === "date") && storage === "epoch-ms") val = sql`(cast((julianday('now') - 2440587.5)*86400000 as integer))`;
|
|
45
|
+
else val = sql`CURRENT_TIMESTAMP`;
|
|
46
|
+
} else val = sql`CURRENT_TIMESTAMP`;
|
|
47
|
+
else if (left.role === "reference" && table) if (typeof val === "string") {
|
|
48
|
+
const relation = Object.values(table.relations).find((rel) => rel.on.some(([localCol]) => localCol === left.name));
|
|
41
49
|
if (relation) {
|
|
42
50
|
const refTable = relation.table;
|
|
43
51
|
const internalIdCol = refTable.getInternalIdColumn();
|
|
44
52
|
const idCol = refTable.getIdColumn();
|
|
45
|
-
const physicalTableName =
|
|
46
|
-
val = eb.selectFrom(physicalTableName).select(internalIdCol.name).where(idCol.name, "=", val).limit(1);
|
|
53
|
+
const physicalTableName = resolver ? resolver.getTableName(refTable.name) : refTable.name;
|
|
54
|
+
val = eb.selectFrom(physicalTableName).select(resolver ? resolver.getColumnName(refTable.name, internalIdCol.name) : internalIdCol.name).where(resolver ? resolver.getColumnName(refTable.name, idCol.name) : idCol.name, "=", val).limit(1);
|
|
47
55
|
}
|
|
48
56
|
} else if (val instanceof FragnoId && val.internalId !== void 0) val = val.internalId;
|
|
49
57
|
else if (val instanceof FragnoId && val.internalId === void 0) {
|
|
50
|
-
const relation = Object.values(table.relations).find((rel) => rel.on.some(([localCol]) => localCol === left.
|
|
58
|
+
const relation = Object.values(table.relations).find((rel) => rel.on.some(([localCol]) => localCol === left.name));
|
|
51
59
|
if (relation) {
|
|
52
60
|
const refTable = relation.table;
|
|
53
61
|
const internalIdCol = refTable.getInternalIdColumn();
|
|
54
62
|
const idCol = refTable.getIdColumn();
|
|
55
|
-
const physicalTableName =
|
|
56
|
-
val = eb.selectFrom(physicalTableName).select(internalIdCol.name).where(idCol.name, "=", val.externalId).limit(1);
|
|
63
|
+
const physicalTableName = resolver ? resolver.getTableName(refTable.name) : refTable.name;
|
|
64
|
+
val = eb.selectFrom(physicalTableName).select(resolver ? resolver.getColumnName(refTable.name, internalIdCol.name) : internalIdCol.name).where(resolver ? resolver.getColumnName(refTable.name, idCol.name) : idCol.name, "=", val.externalId).limit(1);
|
|
57
65
|
}
|
|
58
66
|
} else if (val instanceof FragnoReference) val = val.internalId;
|
|
59
67
|
else {
|
|
@@ -69,57 +77,59 @@ function buildWhere(condition, eb, driverConfig, mapper, table) {
|
|
|
69
77
|
switch (op) {
|
|
70
78
|
case "contains":
|
|
71
79
|
v = "like";
|
|
72
|
-
rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLName(val,
|
|
80
|
+
rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLName(val, resolver))}, '%')` : `%${val}%`;
|
|
73
81
|
break;
|
|
74
82
|
case "not contains":
|
|
75
83
|
v = "not like";
|
|
76
|
-
rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLName(val,
|
|
84
|
+
rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLName(val, resolver))}, '%')` : `%${val}%`;
|
|
77
85
|
break;
|
|
78
86
|
case "starts with":
|
|
79
87
|
v = "like";
|
|
80
|
-
rhs = val instanceof Column ? sql`concat(${eb.ref(fullSQLName(val,
|
|
88
|
+
rhs = val instanceof Column ? sql`concat(${eb.ref(fullSQLName(val, resolver))}, '%')` : `${val}%`;
|
|
81
89
|
break;
|
|
82
90
|
case "not starts with":
|
|
83
91
|
v = "not like";
|
|
84
|
-
rhs = val instanceof Column ? sql`concat(${eb.ref(fullSQLName(val,
|
|
92
|
+
rhs = val instanceof Column ? sql`concat(${eb.ref(fullSQLName(val, resolver))}, '%')` : `${val}%`;
|
|
85
93
|
break;
|
|
86
94
|
case "ends with":
|
|
87
95
|
v = "like";
|
|
88
|
-
rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLName(val,
|
|
96
|
+
rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLName(val, resolver))})` : `%${val}`;
|
|
89
97
|
break;
|
|
90
98
|
case "not ends with":
|
|
91
99
|
v = "not like";
|
|
92
|
-
rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLName(val,
|
|
100
|
+
rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLName(val, resolver))})` : `%${val}`;
|
|
93
101
|
break;
|
|
94
102
|
default:
|
|
95
103
|
v = op;
|
|
96
|
-
rhs = val instanceof Column ? eb.ref(fullSQLName(val,
|
|
104
|
+
rhs = val instanceof Column ? eb.ref(fullSQLName(val, resolver)) : val;
|
|
97
105
|
}
|
|
98
|
-
return eb(fullSQLName(left,
|
|
106
|
+
return eb(fullSQLName(left, resolver), v, rhs);
|
|
99
107
|
}
|
|
100
|
-
if (condition.type === "and") return eb.and(condition.items.map((v) => buildWhere(v, eb, driverConfig,
|
|
101
|
-
if (condition.type === "not") return eb.not(buildWhere(condition.item, eb, driverConfig,
|
|
102
|
-
return eb.or(condition.items.map((v) => buildWhere(v, eb, driverConfig,
|
|
108
|
+
if (condition.type === "and") return eb.and(condition.items.map((v) => buildWhere(v, eb, driverConfig, sqliteStorageMode, resolver, table)));
|
|
109
|
+
if (condition.type === "not") return eb.not(buildWhere(condition.item, eb, driverConfig, sqliteStorageMode, resolver, table));
|
|
110
|
+
return eb.or(condition.items.map((v) => buildWhere(v, eb, driverConfig, sqliteStorageMode, resolver, table)));
|
|
103
111
|
}
|
|
104
112
|
/**
|
|
105
113
|
* Process reference subqueries in encoded values, converting them to Kysely SQL subqueries
|
|
106
114
|
*
|
|
107
115
|
* @param values - The encoded values that may contain ReferenceSubquery objects
|
|
108
116
|
* @param kysely - The Kysely database instance for building subqueries
|
|
109
|
-
* @param
|
|
117
|
+
* @param resolver - Optional naming resolver for namespace prefixing
|
|
110
118
|
* @returns Processed values with subqueries in place of ReferenceSubquery markers
|
|
111
119
|
* @internal
|
|
112
120
|
*/
|
|
113
|
-
function processReferenceSubqueries(values, kysely,
|
|
121
|
+
function processReferenceSubqueries(values, kysely, resolver) {
|
|
114
122
|
const processed = {};
|
|
115
|
-
const getTableName = (table) =>
|
|
123
|
+
const getTableName = (table) => resolver ? resolver.getTableName(table.name) : table.name;
|
|
116
124
|
for (const [key, value] of Object.entries(values)) if (value instanceof ReferenceSubquery) {
|
|
117
125
|
const refTable = value.referencedTable;
|
|
118
126
|
const externalId = value.externalIdValue;
|
|
119
127
|
const tableName = getTableName(refTable);
|
|
120
128
|
const internalIdCol = refTable.getInternalIdColumn().name;
|
|
121
129
|
const idCol = refTable.getIdColumn().name;
|
|
122
|
-
|
|
130
|
+
const internalIdColumnName = resolver ? resolver.getColumnName(refTable.name, internalIdCol) : internalIdCol;
|
|
131
|
+
const idColumnName = resolver ? resolver.getColumnName(refTable.name, idCol) : idCol;
|
|
132
|
+
processed[key] = kysely.selectFrom(tableName).select(internalIdColumnName).where(idColumnName, "=", externalId).limit(1);
|
|
123
133
|
} else processed[key] = value;
|
|
124
134
|
return processed;
|
|
125
135
|
}
|