@fragno-dev/db 0.1.14 → 0.2.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 +242 -139
- package/CHANGELOG.md +47 -0
- package/README.md +123 -8
- package/dist/adapters/adapters.d.ts +19 -5
- package/dist/adapters/adapters.d.ts.map +1 -1
- package/dist/adapters/adapters.js.map +1 -1
- package/dist/adapters/drizzle/drizzle-adapter.d.ts +6 -19
- package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -1
- package/dist/adapters/drizzle/drizzle-adapter.js +7 -47
- package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -1
- package/dist/adapters/drizzle/generate.d.ts +7 -1
- package/dist/adapters/drizzle/generate.d.ts.map +1 -1
- package/dist/adapters/drizzle/generate.js +46 -45
- package/dist/adapters/drizzle/generate.js.map +1 -1
- package/dist/adapters/generic-sql/driver-config.d.ts +74 -0
- package/dist/adapters/generic-sql/driver-config.d.ts.map +1 -0
- package/dist/adapters/generic-sql/driver-config.js +94 -0
- package/dist/adapters/generic-sql/driver-config.js.map +1 -0
- package/dist/adapters/generic-sql/generic-sql-adapter.d.ts +43 -0
- package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -0
- package/dist/adapters/generic-sql/generic-sql-adapter.js +87 -0
- package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -0
- package/dist/adapters/generic-sql/generic-sql-uow-executor.js +67 -0
- package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -0
- package/dist/adapters/generic-sql/migration/cold-kysely.js +33 -0
- package/dist/adapters/generic-sql/migration/cold-kysely.js.map +1 -0
- package/dist/adapters/generic-sql/migration/dialect/mysql.js +60 -0
- package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -0
- package/dist/adapters/generic-sql/migration/dialect/postgres.js +59 -0
- package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -0
- package/dist/adapters/generic-sql/migration/dialect/sqlite.js +96 -0
- package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -0
- package/dist/adapters/generic-sql/migration/executor.d.ts +15 -0
- package/dist/adapters/generic-sql/migration/executor.d.ts.map +1 -0
- package/dist/adapters/generic-sql/migration/executor.js +18 -0
- package/dist/adapters/generic-sql/migration/executor.js.map +1 -0
- package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts +66 -0
- package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -0
- package/dist/adapters/generic-sql/migration/prepared-migrations.js +68 -0
- package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -0
- package/dist/adapters/generic-sql/migration/sql-generator.js +212 -0
- package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -0
- package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +32 -0
- package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -0
- package/dist/adapters/generic-sql/query/cursor-utils.js +37 -0
- package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -0
- package/dist/adapters/generic-sql/query/dialect/mysql.js +33 -0
- package/dist/adapters/generic-sql/query/dialect/mysql.js.map +1 -0
- package/dist/adapters/generic-sql/query/dialect/postgres.js +32 -0
- package/dist/adapters/generic-sql/query/dialect/postgres.js.map +1 -0
- package/dist/adapters/generic-sql/query/dialect/sqlite.js +32 -0
- package/dist/adapters/generic-sql/query/dialect/sqlite.js.map +1 -0
- package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +152 -0
- package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -0
- package/dist/adapters/generic-sql/query/select-builder.js +69 -0
- package/dist/adapters/generic-sql/query/select-builder.js.map +1 -0
- package/dist/adapters/generic-sql/query/sql-query-compiler.js +145 -0
- package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -0
- package/dist/adapters/generic-sql/query/where-builder.js +129 -0
- package/dist/adapters/generic-sql/query/where-builder.js.map +1 -0
- package/dist/adapters/generic-sql/result-interpreter.js +74 -0
- package/dist/adapters/generic-sql/result-interpreter.js.map +1 -0
- package/dist/adapters/generic-sql/uow-decoder.js +105 -0
- package/dist/adapters/generic-sql/uow-decoder.js.map +1 -0
- package/dist/adapters/generic-sql/uow-encoder.js +93 -0
- package/dist/adapters/generic-sql/uow-encoder.js.map +1 -0
- package/dist/adapters/kysely/kysely-adapter.d.ts +5 -16
- package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -1
- package/dist/adapters/kysely/kysely-adapter.js +6 -159
- package/dist/adapters/kysely/kysely-adapter.js.map +1 -1
- package/dist/adapters/{drizzle/drizzle-query.js → shared/from-unit-of-work-compiler.js} +48 -62
- package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -0
- package/dist/adapters/{kysely/kysely-shared.d.ts → shared/table-name-mapper.d.ts} +3 -2
- package/dist/adapters/shared/table-name-mapper.d.ts.map +1 -0
- package/dist/adapters/shared/table-name-mapper.js +43 -0
- package/dist/adapters/shared/table-name-mapper.js.map +1 -0
- package/dist/adapters/shared/uow-operation-compiler.js +105 -0
- package/dist/adapters/shared/uow-operation-compiler.js.map +1 -0
- package/dist/db-fragment-definition-builder.d.ts +186 -0
- package/dist/db-fragment-definition-builder.d.ts.map +1 -0
- package/dist/db-fragment-definition-builder.js +207 -0
- package/dist/db-fragment-definition-builder.js.map +1 -0
- package/dist/fragments/internal-fragment.d.ts +53 -0
- package/dist/fragments/internal-fragment.d.ts.map +1 -0
- package/dist/fragments/internal-fragment.js +111 -0
- package/dist/fragments/internal-fragment.js.map +1 -0
- package/dist/hooks/hooks.d.ts +51 -0
- package/dist/hooks/hooks.d.ts.map +1 -0
- package/dist/hooks/hooks.js +88 -0
- package/dist/hooks/hooks.js.map +1 -0
- package/dist/migration-engine/generation-engine.d.ts +0 -2
- package/dist/migration-engine/generation-engine.d.ts.map +1 -1
- package/dist/migration-engine/generation-engine.js +38 -56
- package/dist/migration-engine/generation-engine.js.map +1 -1
- package/dist/mod.d.ts +35 -23
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +48 -45
- package/dist/mod.js.map +1 -1
- package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js +165 -0
- package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js.map +1 -0
- package/dist/packages/fragno/dist/api/bind-services.js +20 -0
- package/dist/packages/fragno/dist/api/bind-services.js.map +1 -0
- package/dist/packages/fragno/dist/api/error.js +48 -0
- package/dist/packages/fragno/dist/api/error.js.map +1 -0
- package/dist/packages/fragno/dist/api/fragment-definition-builder.js +320 -0
- package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +1 -0
- package/dist/packages/fragno/dist/api/fragment-instantiator.js +525 -0
- package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +1 -0
- package/dist/packages/fragno/dist/api/fragno-response.js +73 -0
- package/dist/packages/fragno/dist/api/fragno-response.js.map +1 -0
- package/dist/packages/fragno/dist/api/internal/response-stream.js +81 -0
- package/dist/packages/fragno/dist/api/internal/response-stream.js.map +1 -0
- package/dist/packages/fragno/dist/api/internal/route.js +10 -0
- package/dist/packages/fragno/dist/api/internal/route.js.map +1 -0
- package/dist/packages/fragno/dist/api/mutable-request-state.js +97 -0
- package/dist/packages/fragno/dist/api/mutable-request-state.js.map +1 -0
- package/dist/packages/fragno/dist/api/request-context-storage.js +43 -0
- package/dist/packages/fragno/dist/api/request-context-storage.js.map +1 -0
- package/dist/packages/fragno/dist/api/request-input-context.js +118 -0
- package/dist/packages/fragno/dist/api/request-input-context.js.map +1 -0
- package/dist/packages/fragno/dist/api/request-middleware.js +83 -0
- package/dist/packages/fragno/dist/api/request-middleware.js.map +1 -0
- package/dist/packages/fragno/dist/api/request-output-context.js +119 -0
- package/dist/packages/fragno/dist/api/request-output-context.js.map +1 -0
- package/dist/packages/fragno/dist/api/route.js +17 -0
- package/dist/packages/fragno/dist/api/route.js.map +1 -0
- package/dist/packages/fragno/dist/internal/symbols.js +10 -0
- package/dist/packages/fragno/dist/internal/symbols.js.map +1 -0
- package/dist/query/column-defaults.js +27 -0
- package/dist/query/column-defaults.js.map +1 -0
- package/dist/query/cursor.d.ts +14 -6
- package/dist/query/cursor.d.ts.map +1 -1
- package/dist/query/cursor.js +16 -7
- package/dist/query/cursor.js.map +1 -1
- package/dist/query/orm/orm.d.ts +1 -1
- package/dist/query/orm/orm.js.map +1 -1
- package/dist/query/serialize/create-sql-serializer.js +30 -0
- package/dist/query/serialize/create-sql-serializer.js.map +1 -0
- package/dist/query/serialize/dialect/mysql-serializer.js +87 -0
- package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -0
- package/dist/query/serialize/dialect/postgres-serializer.js +80 -0
- package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -0
- package/dist/query/serialize/dialect/sqlite-serializer.js +93 -0
- package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -0
- package/dist/query/serialize/sql-serializer.js +67 -0
- package/dist/query/serialize/sql-serializer.js.map +1 -0
- package/dist/query/{query.d.ts → simple-query-interface.d.ts} +6 -6
- package/dist/query/simple-query-interface.d.ts.map +1 -0
- package/dist/query/unit-of-work/execute-unit-of-work.d.ts +133 -0
- package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -0
- package/dist/query/unit-of-work/execute-unit-of-work.js +197 -0
- package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -0
- package/dist/query/unit-of-work/retry-policy.d.ts +88 -0
- package/dist/query/unit-of-work/retry-policy.d.ts.map +1 -0
- package/dist/query/unit-of-work/retry-policy.js +61 -0
- package/dist/query/unit-of-work/retry-policy.js.map +1 -0
- package/dist/query/{unit-of-work.d.ts → unit-of-work/unit-of-work.d.ts} +145 -58
- package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -0
- package/dist/query/{unit-of-work.js → unit-of-work/unit-of-work.js} +435 -198
- package/dist/query/unit-of-work/unit-of-work.js.map +1 -0
- package/dist/query/value-decoding.js +71 -0
- package/dist/query/value-decoding.js.map +1 -0
- package/dist/query/value-encoding.js +124 -0
- package/dist/query/value-encoding.js.map +1 -0
- package/dist/schema/create.d.ts +3 -0
- package/dist/schema/create.d.ts.map +1 -1
- package/dist/schema/create.js +4 -0
- package/dist/schema/create.js.map +1 -1
- package/dist/schema/type-conversion/create-sql-type-mapper.js +29 -0
- package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -0
- package/dist/schema/type-conversion/dialect/mysql.js +57 -0
- package/dist/schema/type-conversion/dialect/mysql.js.map +1 -0
- package/dist/schema/type-conversion/dialect/postgres.js +56 -0
- package/dist/schema/type-conversion/dialect/postgres.js.map +1 -0
- package/dist/schema/type-conversion/dialect/sqlite.js +52 -0
- package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -0
- package/dist/schema/type-conversion/type-mapping.js +63 -0
- package/dist/schema/type-conversion/type-mapping.js.map +1 -0
- package/dist/sql-driver/connection/connection-provider.d.ts +13 -0
- package/dist/sql-driver/connection/connection-provider.d.ts.map +1 -0
- package/dist/sql-driver/connection/connection-provider.js +19 -0
- package/dist/sql-driver/connection/connection-provider.js.map +1 -0
- package/dist/sql-driver/connection/single-connection-provider.js +23 -0
- package/dist/sql-driver/connection/single-connection-provider.js.map +1 -0
- package/dist/sql-driver/dialect-adapter/dialect-adapter.d.ts +7 -0
- package/dist/sql-driver/dialect-adapter/dialect-adapter.d.ts.map +1 -0
- package/dist/sql-driver/dialects/dialects.d.ts +2 -0
- package/dist/sql-driver/dialects/dialects.js +3 -0
- package/dist/sql-driver/dialects/durable-object-dialect.d.ts +72 -0
- package/dist/sql-driver/dialects/durable-object-dialect.d.ts.map +1 -0
- package/dist/sql-driver/dialects/durable-object-dialect.js +130 -0
- package/dist/sql-driver/dialects/durable-object-dialect.js.map +1 -0
- package/dist/sql-driver/driver/runtime-driver.d.ts +23 -0
- package/dist/sql-driver/driver/runtime-driver.d.ts.map +1 -0
- package/dist/sql-driver/driver/runtime-driver.js +56 -0
- package/dist/sql-driver/driver/runtime-driver.js.map +1 -0
- package/dist/sql-driver/query-executor/default-query-executor.js +26 -0
- package/dist/sql-driver/query-executor/default-query-executor.js.map +1 -0
- package/dist/sql-driver/query-executor/plugin.d.ts +17 -0
- package/dist/sql-driver/query-executor/plugin.d.ts.map +1 -0
- package/dist/sql-driver/query-executor/query-executor-base.js +25 -0
- package/dist/sql-driver/query-executor/query-executor-base.js.map +1 -0
- package/dist/sql-driver/query-executor/query-executor.d.ts +36 -0
- package/dist/sql-driver/query-executor/query-executor.d.ts.map +1 -0
- package/dist/sql-driver/sql-driver-adapter.d.ts +29 -0
- package/dist/sql-driver/sql-driver-adapter.d.ts.map +1 -0
- package/dist/sql-driver/sql-driver-adapter.js +68 -0
- package/dist/sql-driver/sql-driver-adapter.js.map +1 -0
- package/dist/sql-driver/sql-driver.d.ts +38 -0
- package/dist/sql-driver/sql-driver.d.ts.map +1 -0
- package/dist/sql-driver/sql-driver.js +1 -0
- package/dist/sql-driver/sql.js +50 -0
- package/dist/sql-driver/sql.js.map +1 -0
- package/dist/with-database.d.ts +32 -0
- package/dist/with-database.d.ts.map +1 -0
- package/dist/with-database.js +34 -0
- package/dist/with-database.js.map +1 -0
- package/package.json +43 -9
- package/src/adapters/adapters.ts +23 -4
- package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +140 -185
- package/src/adapters/drizzle/{drizzle-adapter-sqlite.test.ts → drizzle-adapter-sqlite3.test.ts} +187 -55
- package/src/adapters/drizzle/drizzle-adapter.ts +14 -93
- package/src/adapters/drizzle/generate.test.ts +102 -269
- package/src/adapters/drizzle/generate.ts +89 -63
- package/src/adapters/drizzle/migrate-drizzle.test.ts +19 -0
- package/src/adapters/drizzle/shared.ts +0 -34
- package/src/adapters/drizzle/test-utils.ts +36 -5
- package/src/adapters/generic-sql/README.md +14 -0
- package/src/adapters/generic-sql/driver-config.ts +144 -0
- package/src/adapters/generic-sql/generic-sql-adapter.test.ts +50 -0
- package/src/adapters/generic-sql/generic-sql-adapter.ts +146 -0
- package/src/adapters/generic-sql/generic-sql-uow-executor.ts +130 -0
- package/src/adapters/generic-sql/migration/cold-kysely.ts +55 -0
- package/src/adapters/{kysely/migration/execute-mysql.test.ts → generic-sql/migration/dialect/mysql.test.ts} +342 -484
- package/src/adapters/generic-sql/migration/dialect/mysql.ts +104 -0
- package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +1008 -0
- package/src/adapters/generic-sql/migration/dialect/postgres.ts +113 -0
- package/src/adapters/{kysely/migration/execute-sqlite.test.ts → generic-sql/migration/dialect/sqlite.test.ts} +307 -510
- package/src/adapters/generic-sql/migration/dialect/sqlite.ts +189 -0
- package/src/adapters/generic-sql/migration/executor.ts +33 -0
- package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +661 -0
- package/src/adapters/generic-sql/migration/prepared-migrations.ts +214 -0
- package/src/adapters/generic-sql/migration/sql-generator.ts +413 -0
- package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +36 -0
- package/src/adapters/generic-sql/query/cursor-utils.ts +56 -0
- package/src/adapters/generic-sql/query/dialect/mysql.ts +34 -0
- package/src/adapters/generic-sql/query/dialect/postgres.ts +32 -0
- package/src/adapters/generic-sql/query/dialect/sqlite.ts +32 -0
- package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +1568 -0
- package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +314 -0
- package/src/adapters/generic-sql/query/select-builder.test.ts +256 -0
- package/src/adapters/generic-sql/query/select-builder.ts +137 -0
- package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +195 -0
- package/src/adapters/generic-sql/query/sql-query-compiler.ts +367 -0
- package/src/adapters/generic-sql/query/where-builder.test.ts +744 -0
- package/src/adapters/generic-sql/query/where-builder.ts +211 -0
- package/src/adapters/generic-sql/result-interpreter.ts +102 -0
- package/src/adapters/generic-sql/test/generic-drizzle-adapter-sqlite3.test.ts +899 -0
- package/src/adapters/generic-sql/uow-decoder.test.ts +399 -0
- package/src/adapters/generic-sql/uow-decoder.ts +152 -0
- package/src/adapters/generic-sql/uow-encoder.test.ts +183 -0
- package/src/adapters/generic-sql/uow-encoder.ts +131 -0
- package/src/adapters/kysely/kysely-adapter-pglite.test.ts +90 -96
- package/src/adapters/kysely/kysely-adapter-sqlocal.test.ts +215 -0
- package/src/adapters/kysely/kysely-adapter.ts +10 -242
- package/src/adapters/{drizzle/drizzle-query.ts → shared/from-unit-of-work-compiler.ts} +111 -106
- package/src/adapters/shared/table-name-mapper.ts +50 -0
- package/src/adapters/shared/uow-operation-compiler.ts +211 -0
- package/src/db-fragment-definition-builder.test.ts +887 -0
- package/src/db-fragment-definition-builder.ts +737 -0
- package/src/db-fragment-instantiator.test.ts +543 -0
- package/src/db-fragment-integration.test.ts +406 -0
- package/src/fragments/internal-fragment.test.ts +549 -0
- package/src/fragments/internal-fragment.ts +249 -0
- package/src/hooks/hooks.test.ts +575 -0
- package/src/hooks/hooks.ts +179 -0
- package/src/migration-engine/generation-engine.test.ts +60 -27
- package/src/migration-engine/generation-engine.ts +99 -92
- package/src/mod.ts +139 -78
- package/src/query/column-defaults.ts +49 -0
- package/src/query/cursor.test.ts +147 -3
- package/src/query/cursor.ts +25 -8
- package/src/query/orm/orm.ts +1 -1
- package/src/query/query-type.test.ts +9 -9
- package/src/query/serialize/create-sql-serializer.ts +34 -0
- package/src/query/serialize/dialect/mysql-serializer.ts +142 -0
- package/src/query/serialize/dialect/postgres-serializer.ts +129 -0
- package/src/query/serialize/dialect/sqlite-serializer.test.ts +251 -0
- package/src/query/serialize/dialect/sqlite-serializer.ts +156 -0
- package/src/query/serialize/sql-serializer.ts +143 -0
- package/src/query/{query.ts → simple-query-interface.ts} +4 -4
- package/src/query/unit-of-work/execute-unit-of-work.test.ts +1310 -0
- package/src/query/unit-of-work/execute-unit-of-work.ts +504 -0
- package/src/query/unit-of-work/retry-policy.test.ts +217 -0
- package/src/query/unit-of-work/retry-policy.ts +141 -0
- package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +831 -0
- package/src/query/{unit-of-work-types.test.ts → unit-of-work/unit-of-work-types.test.ts} +7 -5
- package/src/query/unit-of-work/unit-of-work.test.ts +1716 -0
- package/src/query/{unit-of-work.ts → unit-of-work/unit-of-work.ts} +716 -420
- package/src/query/{result-transform.test.ts → value-decoding.test.ts} +45 -298
- package/src/query/value-decoding.ts +113 -0
- package/src/query/value-encoding.test.ts +390 -0
- package/src/query/value-encoding.ts +168 -0
- package/src/schema/create.test.ts +5 -1
- package/src/schema/create.ts +5 -0
- package/src/schema/serialize.test.ts +165 -407
- package/src/schema/type-conversion/create-sql-type-mapper.ts +28 -0
- package/src/schema/type-conversion/dialect/mysql.ts +64 -0
- package/src/schema/type-conversion/dialect/postgres.ts +62 -0
- package/src/schema/type-conversion/dialect/sqlite.ts +63 -0
- package/src/schema/type-conversion/type-mapping.test.ts +137 -0
- package/src/schema/type-conversion/type-mapping.ts +153 -0
- package/src/shared/connection-pool.ts +5 -5
- package/src/sql-driver/better-sqlite3.test.ts +126 -0
- package/src/sql-driver/connection/connection-provider.ts +27 -0
- package/src/sql-driver/connection/single-connection-provider.ts +42 -0
- package/src/sql-driver/dialect-adapter/dialect-adapter.ts +9 -0
- package/src/sql-driver/dialect-adapter/sqlite-dialect-adapter.ts +7 -0
- package/src/sql-driver/dialects/dialects.ts +1 -0
- package/src/sql-driver/dialects/durable-object-dialect.ts +260 -0
- package/src/sql-driver/driver/runtime-driver.ts +91 -0
- package/src/sql-driver/query-executor/default-query-executor.ts +38 -0
- package/src/sql-driver/query-executor/plugin.ts +22 -0
- package/src/sql-driver/query-executor/query-executor-base.ts +53 -0
- package/src/sql-driver/query-executor/query-executor.ts +44 -0
- package/src/sql-driver/sql-driver-adapter.ts +96 -0
- package/src/sql-driver/sql-driver.ts +53 -0
- package/src/sql-driver/sql.ts +57 -0
- package/src/sql-driver/sqlocal.test.ts +117 -0
- package/src/with-database.ts +152 -0
- package/tsdown.config.ts +8 -2
- package/dist/adapters/drizzle/drizzle-connection-pool.js +0 -40
- package/dist/adapters/drizzle/drizzle-connection-pool.js.map +0 -1
- package/dist/adapters/drizzle/drizzle-query.d.ts +0 -23
- package/dist/adapters/drizzle/drizzle-query.d.ts.map +0 -1
- package/dist/adapters/drizzle/drizzle-query.js.map +0 -1
- package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts +0 -10
- package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts.map +0 -1
- package/dist/adapters/drizzle/drizzle-uow-compiler.js +0 -315
- package/dist/adapters/drizzle/drizzle-uow-compiler.js.map +0 -1
- package/dist/adapters/drizzle/drizzle-uow-decoder.js +0 -116
- package/dist/adapters/drizzle/drizzle-uow-decoder.js.map +0 -1
- package/dist/adapters/drizzle/drizzle-uow-executor.js +0 -149
- package/dist/adapters/drizzle/drizzle-uow-executor.js.map +0 -1
- package/dist/adapters/drizzle/join-column-utils.js +0 -28
- package/dist/adapters/drizzle/join-column-utils.js.map +0 -1
- package/dist/adapters/drizzle/shared.d.ts +0 -14
- package/dist/adapters/drizzle/shared.d.ts.map +0 -1
- package/dist/adapters/drizzle/shared.js +0 -35
- package/dist/adapters/drizzle/shared.js.map +0 -1
- package/dist/adapters/kysely/kysely-connection-pool.js +0 -41
- package/dist/adapters/kysely/kysely-connection-pool.js.map +0 -1
- package/dist/adapters/kysely/kysely-query-builder.js +0 -321
- package/dist/adapters/kysely/kysely-query-builder.js.map +0 -1
- package/dist/adapters/kysely/kysely-query-compiler.js +0 -66
- package/dist/adapters/kysely/kysely-query-compiler.js.map +0 -1
- package/dist/adapters/kysely/kysely-query.d.ts +0 -22
- package/dist/adapters/kysely/kysely-query.d.ts.map +0 -1
- package/dist/adapters/kysely/kysely-query.js +0 -223
- package/dist/adapters/kysely/kysely-query.js.map +0 -1
- package/dist/adapters/kysely/kysely-shared.d.ts.map +0 -1
- package/dist/adapters/kysely/kysely-shared.js +0 -18
- package/dist/adapters/kysely/kysely-shared.js.map +0 -1
- package/dist/adapters/kysely/kysely-uow-compiler.js +0 -170
- package/dist/adapters/kysely/kysely-uow-compiler.js.map +0 -1
- package/dist/adapters/kysely/kysely-uow-executor.js +0 -89
- package/dist/adapters/kysely/kysely-uow-executor.js.map +0 -1
- package/dist/adapters/kysely/migration/execute-base.js +0 -128
- package/dist/adapters/kysely/migration/execute-base.js.map +0 -1
- package/dist/adapters/kysely/migration/execute-factory.js +0 -34
- package/dist/adapters/kysely/migration/execute-factory.js.map +0 -1
- package/dist/adapters/kysely/migration/execute-mssql.js +0 -112
- package/dist/adapters/kysely/migration/execute-mssql.js.map +0 -1
- package/dist/adapters/kysely/migration/execute-mysql.js +0 -93
- package/dist/adapters/kysely/migration/execute-mysql.js.map +0 -1
- package/dist/adapters/kysely/migration/execute-postgres.js +0 -104
- package/dist/adapters/kysely/migration/execute-postgres.js.map +0 -1
- package/dist/adapters/kysely/migration/execute-sqlite.js +0 -123
- package/dist/adapters/kysely/migration/execute-sqlite.js.map +0 -1
- package/dist/adapters/kysely/migration/execute.js +0 -34
- package/dist/adapters/kysely/migration/execute.js.map +0 -1
- package/dist/bind-services.d.ts +0 -7
- package/dist/bind-services.d.ts.map +0 -1
- package/dist/bind-services.js +0 -14
- package/dist/bind-services.js.map +0 -1
- package/dist/fragment.d.ts +0 -173
- package/dist/fragment.d.ts.map +0 -1
- package/dist/fragment.js +0 -191
- package/dist/fragment.js.map +0 -1
- package/dist/migration-engine/create.d.ts +0 -37
- package/dist/migration-engine/create.d.ts.map +0 -1
- package/dist/migration-engine/create.js +0 -58
- package/dist/migration-engine/create.js.map +0 -1
- package/dist/migration-engine/shared.d.ts +0 -112
- package/dist/migration-engine/shared.d.ts.map +0 -1
- package/dist/query/query.d.ts.map +0 -1
- package/dist/query/result-transform.js +0 -168
- package/dist/query/result-transform.js.map +0 -1
- package/dist/query/unit-of-work.d.ts.map +0 -1
- package/dist/query/unit-of-work.js.map +0 -1
- package/dist/schema/serialize.js +0 -106
- package/dist/schema/serialize.js.map +0 -1
- package/dist/shared/settings-schema.js +0 -36
- package/dist/shared/settings-schema.js.map +0 -1
- package/src/adapters/drizzle/drizzle-adapter.test.ts +0 -170
- package/src/adapters/drizzle/drizzle-connection-pool.ts +0 -66
- package/src/adapters/drizzle/drizzle-query.test.ts +0 -499
- package/src/adapters/drizzle/drizzle-uow-compiler.test.ts +0 -1383
- package/src/adapters/drizzle/drizzle-uow-compiler.ts +0 -636
- package/src/adapters/drizzle/drizzle-uow-decoder.ts +0 -218
- package/src/adapters/drizzle/drizzle-uow-executor.ts +0 -276
- package/src/adapters/drizzle/join-column-utils.test.ts +0 -79
- package/src/adapters/drizzle/join-column-utils.ts +0 -39
- package/src/adapters/kysely/kysely-connection-pool.ts +0 -70
- package/src/adapters/kysely/kysely-query-builder.test.ts +0 -1344
- package/src/adapters/kysely/kysely-query-builder.ts +0 -666
- package/src/adapters/kysely/kysely-query-compiler.ts +0 -132
- package/src/adapters/kysely/kysely-query.test.ts +0 -498
- package/src/adapters/kysely/kysely-query.ts +0 -390
- package/src/adapters/kysely/kysely-shared.ts +0 -23
- package/src/adapters/kysely/kysely-uow-compiler.test.ts +0 -998
- package/src/adapters/kysely/kysely-uow-compiler.ts +0 -318
- package/src/adapters/kysely/kysely-uow-executor.ts +0 -145
- package/src/adapters/kysely/kysely-uow-joins.test.ts +0 -811
- package/src/adapters/kysely/migration/execute-base.ts +0 -256
- package/src/adapters/kysely/migration/execute-factory.ts +0 -53
- package/src/adapters/kysely/migration/execute-mssql.ts +0 -250
- package/src/adapters/kysely/migration/execute-mysql.ts +0 -211
- package/src/adapters/kysely/migration/execute-postgres.test.ts +0 -2657
- package/src/adapters/kysely/migration/execute-postgres.ts +0 -234
- package/src/adapters/kysely/migration/execute-sqlite.ts +0 -247
- package/src/adapters/kysely/migration/execute.ts +0 -50
- package/src/adapters/kysely/migration/kysely-migrator.test.ts +0 -261
- package/src/bind-services.test.ts +0 -214
- package/src/bind-services.ts +0 -37
- package/src/db-fragment.test.ts +0 -800
- package/src/fragment.ts +0 -727
- package/src/query/result-transform.ts +0 -271
- package/src/query/unit-of-work-multi-schema.test.ts +0 -64
- package/src/query/unit-of-work.test.ts +0 -943
- package/src/schema/serialize.ts +0 -396
- package/src/shared/settings-schema.ts +0 -61
- package/src/uow-context-integration.test.ts +0 -102
- package/src/uow-context.test.ts +0 -182
- /package/dist/query/{query.js → simple-query-interface.js} +0 -0
|
@@ -1,2657 +0,0 @@
|
|
|
1
|
-
import { Kysely, PostgresDialect } from "kysely";
|
|
2
|
-
import { describe, expect, it, beforeAll } from "vitest";
|
|
3
|
-
import { execute } from "./execute";
|
|
4
|
-
import type { MigrationOperation } from "../../../migration-engine/shared";
|
|
5
|
-
import type { KyselyConfig } from "../kysely-adapter";
|
|
6
|
-
|
|
7
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
|
-
type KyselyAny = Kysely<any>;
|
|
9
|
-
|
|
10
|
-
function assertSingleResult<T>(result: T | T[]): asserts result is T {
|
|
11
|
-
if (Array.isArray(result)) {
|
|
12
|
-
throw new Error("Expected single result, got array");
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
describe("execute() - PostgreSQL", () => {
|
|
17
|
-
let db: KyselyAny;
|
|
18
|
-
let config: KyselyConfig;
|
|
19
|
-
|
|
20
|
-
beforeAll(async () => {
|
|
21
|
-
// Create a Kysely instance with a PostgresDialect, but not actually connected to a database
|
|
22
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
-
db = new Kysely({ dialect: new PostgresDialect({} as any) });
|
|
24
|
-
config = { db, provider: "postgresql" };
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
describe("create-table", () => {
|
|
28
|
-
it("should generate SQL for simple table with columns", () => {
|
|
29
|
-
const operation: MigrationOperation = {
|
|
30
|
-
type: "create-table",
|
|
31
|
-
name: "users",
|
|
32
|
-
columns: [
|
|
33
|
-
{
|
|
34
|
-
name: "id",
|
|
35
|
-
type: "integer",
|
|
36
|
-
isNullable: false,
|
|
37
|
-
role: "external-id",
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
name: "name",
|
|
41
|
-
type: "string",
|
|
42
|
-
isNullable: false,
|
|
43
|
-
role: "regular",
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
name: "email",
|
|
47
|
-
type: "string",
|
|
48
|
-
isNullable: false,
|
|
49
|
-
role: "regular",
|
|
50
|
-
},
|
|
51
|
-
],
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const result = execute(operation, config, () => {
|
|
55
|
-
throw new Error("No custom operations");
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
assertSingleResult(result);
|
|
59
|
-
|
|
60
|
-
const compiled = result.compile();
|
|
61
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
62
|
-
`"create table "users" ("id" integer not null unique, "name" text not null, "email" text not null)"`,
|
|
63
|
-
);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it("should generate SQL for able with id column with default undefined", () => {
|
|
67
|
-
const operation: MigrationOperation = {
|
|
68
|
-
type: "create-table",
|
|
69
|
-
name: "users",
|
|
70
|
-
columns: [
|
|
71
|
-
{
|
|
72
|
-
name: "id",
|
|
73
|
-
type: "varchar(30)",
|
|
74
|
-
isNullable: false,
|
|
75
|
-
role: "external-id",
|
|
76
|
-
default: { runtime: "cuid" },
|
|
77
|
-
},
|
|
78
|
-
],
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const result = execute(operation, config, () => {
|
|
82
|
-
throw new Error("No custom operations");
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
assertSingleResult(result);
|
|
86
|
-
|
|
87
|
-
const compiled = result.compile();
|
|
88
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
89
|
-
`"create table "users" ("id" varchar(30) not null unique)"`,
|
|
90
|
-
);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it("should generate SQL for table with various column types", () => {
|
|
94
|
-
const operation: MigrationOperation = {
|
|
95
|
-
type: "create-table",
|
|
96
|
-
name: "test_types",
|
|
97
|
-
columns: [
|
|
98
|
-
{ name: "col_int", type: "integer", isNullable: false, role: "external-id" },
|
|
99
|
-
{ name: "col_bigint", type: "bigint", isNullable: false, role: "regular" },
|
|
100
|
-
{ name: "col_decimal", type: "decimal", isNullable: false, role: "regular" },
|
|
101
|
-
{ name: "col_bool", type: "bool", isNullable: false, role: "regular" },
|
|
102
|
-
{ name: "col_date", type: "date", isNullable: false, role: "regular" },
|
|
103
|
-
{ name: "col_timestamp", type: "timestamp", isNullable: false, role: "regular" },
|
|
104
|
-
{ name: "col_json", type: "json", isNullable: false, role: "regular" },
|
|
105
|
-
{ name: "col_binary", type: "binary", isNullable: false, role: "regular" },
|
|
106
|
-
{ name: "col_varchar", type: "varchar(255)", isNullable: false, role: "regular" },
|
|
107
|
-
],
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
const result = execute(operation, config, () => {
|
|
111
|
-
throw new Error("No custom operations");
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
assertSingleResult(result);
|
|
115
|
-
|
|
116
|
-
const compiled = result.compile();
|
|
117
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
118
|
-
`"create table "test_types" ("col_int" integer not null unique, "col_bigint" bigint not null, "col_decimal" decimal not null, "col_bool" boolean not null, "col_date" date not null, "col_timestamp" timestamp not null, "col_json" json not null, "col_binary" bytea not null, "col_varchar" varchar(255) not null)"`,
|
|
119
|
-
);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it("should generate SQL for table with nullable columns", () => {
|
|
123
|
-
const operation: MigrationOperation = {
|
|
124
|
-
type: "create-table",
|
|
125
|
-
name: "nullable_test",
|
|
126
|
-
columns: [
|
|
127
|
-
{ name: "id", type: "integer", isNullable: false, role: "external-id" },
|
|
128
|
-
{ name: "optional_name", type: "string", isNullable: true, role: "regular" },
|
|
129
|
-
{ name: "optional_age", type: "integer", isNullable: true, role: "regular" },
|
|
130
|
-
],
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
const result = execute(operation, config, () => {
|
|
134
|
-
throw new Error("No custom operations");
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
assertSingleResult(result);
|
|
138
|
-
|
|
139
|
-
const compiled = result.compile();
|
|
140
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
141
|
-
`"create table "nullable_test" ("id" integer not null unique, "optional_name" text, "optional_age" integer)"`,
|
|
142
|
-
);
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it("should generate SQL for table with default values", () => {
|
|
146
|
-
const operation: MigrationOperation = {
|
|
147
|
-
type: "create-table",
|
|
148
|
-
name: "defaults_test",
|
|
149
|
-
columns: [
|
|
150
|
-
{ name: "id", type: "integer", isNullable: false, role: "external-id" },
|
|
151
|
-
{
|
|
152
|
-
name: "status",
|
|
153
|
-
type: "string",
|
|
154
|
-
isNullable: false,
|
|
155
|
-
role: "regular",
|
|
156
|
-
default: { value: "pending" },
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
name: "count",
|
|
160
|
-
type: "integer",
|
|
161
|
-
isNullable: false,
|
|
162
|
-
role: "regular",
|
|
163
|
-
default: { value: 0 },
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
name: "is_active",
|
|
167
|
-
type: "bool",
|
|
168
|
-
isNullable: false,
|
|
169
|
-
role: "regular",
|
|
170
|
-
default: { value: true },
|
|
171
|
-
},
|
|
172
|
-
],
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
const result = execute(operation, config, () => {
|
|
176
|
-
throw new Error("No custom operations");
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
assertSingleResult(result);
|
|
180
|
-
|
|
181
|
-
const compiled = result.compile();
|
|
182
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
183
|
-
`"create table "defaults_test" ("id" integer not null unique, "status" text default 'pending' not null, "count" integer default 0 not null, "is_active" boolean default true not null)"`,
|
|
184
|
-
);
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
it("should generate SQL for table with timestamp default to CURRENT_TIMESTAMP", () => {
|
|
188
|
-
const operation: MigrationOperation = {
|
|
189
|
-
type: "create-table",
|
|
190
|
-
name: "timestamps_test",
|
|
191
|
-
columns: [
|
|
192
|
-
{ name: "id", type: "integer", isNullable: false, role: "external-id" },
|
|
193
|
-
{
|
|
194
|
-
name: "created_at",
|
|
195
|
-
type: "timestamp",
|
|
196
|
-
isNullable: false,
|
|
197
|
-
role: "regular",
|
|
198
|
-
default: { dbSpecial: "now" },
|
|
199
|
-
},
|
|
200
|
-
],
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
const result = execute(operation, config, () => {
|
|
204
|
-
throw new Error("No custom operations");
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
assertSingleResult(result);
|
|
208
|
-
|
|
209
|
-
const compiled = result.compile();
|
|
210
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
211
|
-
`"create table "timestamps_test" ("id" integer not null unique, "created_at" timestamp default CURRENT_TIMESTAMP not null)"`,
|
|
212
|
-
);
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
it("should generate SQL for table with reference column", () => {
|
|
216
|
-
const operation: MigrationOperation = {
|
|
217
|
-
type: "create-table",
|
|
218
|
-
name: "posts",
|
|
219
|
-
columns: [
|
|
220
|
-
{ name: "id", type: "integer", isNullable: false, role: "external-id" },
|
|
221
|
-
{ name: "user_id", type: "integer", isNullable: false, role: "reference" },
|
|
222
|
-
{ name: "title", type: "string", isNullable: false, role: "regular" },
|
|
223
|
-
],
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
const result = execute(operation, config, () => {
|
|
227
|
-
throw new Error("No custom operations");
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
assertSingleResult(result);
|
|
231
|
-
|
|
232
|
-
const compiled = result.compile();
|
|
233
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
234
|
-
`"create table "posts" ("id" integer not null unique, "user_id" integer not null, "title" text not null)"`,
|
|
235
|
-
);
|
|
236
|
-
});
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
describe("rename-table", () => {
|
|
240
|
-
it("should generate SQL for PostgreSQL rename", () => {
|
|
241
|
-
const operation: MigrationOperation = {
|
|
242
|
-
type: "rename-table",
|
|
243
|
-
from: "old_name",
|
|
244
|
-
to: "new_name",
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
const result = execute(operation, config, () => {
|
|
248
|
-
throw new Error("No custom operations");
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
assertSingleResult(result);
|
|
252
|
-
|
|
253
|
-
const compiled = result.compile();
|
|
254
|
-
expect(compiled.sql).toMatchInlineSnapshot(`"alter table "old_name" rename to "new_name""`);
|
|
255
|
-
});
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
describe("drop-table", () => {
|
|
259
|
-
it("should generate SQL to drop table", () => {
|
|
260
|
-
const operation: MigrationOperation = {
|
|
261
|
-
type: "drop-table",
|
|
262
|
-
name: "to_drop",
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
const result = execute(operation, config, () => {
|
|
266
|
-
throw new Error("No custom operations");
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
assertSingleResult(result);
|
|
270
|
-
|
|
271
|
-
const compiled = result.compile();
|
|
272
|
-
expect(compiled.sql).toMatchInlineSnapshot(`"drop table "to_drop""`);
|
|
273
|
-
});
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
describe("alter-table - create-column", () => {
|
|
277
|
-
it("should generate SQL to add a new column", () => {
|
|
278
|
-
const operation: MigrationOperation = {
|
|
279
|
-
type: "alter-table",
|
|
280
|
-
name: "test_table",
|
|
281
|
-
value: [
|
|
282
|
-
{
|
|
283
|
-
type: "create-column",
|
|
284
|
-
value: {
|
|
285
|
-
name: "new_column",
|
|
286
|
-
type: "string",
|
|
287
|
-
isNullable: true,
|
|
288
|
-
role: "regular",
|
|
289
|
-
},
|
|
290
|
-
},
|
|
291
|
-
],
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
const results = execute(operation, config, () => {
|
|
295
|
-
throw new Error("No custom operations");
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
if (!Array.isArray(results)) {
|
|
299
|
-
throw new Error("Expected array of results");
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
expect(results).toHaveLength(1);
|
|
303
|
-
const compiled = results[0].compile();
|
|
304
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
305
|
-
`"alter table "test_table" add column "new_column" text"`,
|
|
306
|
-
);
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
it("should generate SQL for multiple columns", () => {
|
|
310
|
-
const operation: MigrationOperation = {
|
|
311
|
-
type: "alter-table",
|
|
312
|
-
name: "test_table",
|
|
313
|
-
value: [
|
|
314
|
-
{
|
|
315
|
-
type: "create-column",
|
|
316
|
-
value: {
|
|
317
|
-
name: "col1",
|
|
318
|
-
type: "string",
|
|
319
|
-
isNullable: true,
|
|
320
|
-
role: "regular",
|
|
321
|
-
},
|
|
322
|
-
},
|
|
323
|
-
{
|
|
324
|
-
type: "create-column",
|
|
325
|
-
value: {
|
|
326
|
-
name: "col2",
|
|
327
|
-
type: "integer",
|
|
328
|
-
isNullable: false,
|
|
329
|
-
role: "regular",
|
|
330
|
-
default: { value: 0 },
|
|
331
|
-
},
|
|
332
|
-
},
|
|
333
|
-
],
|
|
334
|
-
};
|
|
335
|
-
|
|
336
|
-
const results = execute(operation, config, () => {
|
|
337
|
-
throw new Error("No custom operations");
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
if (!Array.isArray(results)) {
|
|
341
|
-
throw new Error("Expected array of results");
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
expect(results).toHaveLength(2);
|
|
345
|
-
expect(results[0].compile().sql).toMatchInlineSnapshot(
|
|
346
|
-
`"alter table "test_table" add column "col1" text"`,
|
|
347
|
-
);
|
|
348
|
-
expect(results[1].compile().sql).toMatchInlineSnapshot(
|
|
349
|
-
`"alter table "test_table" add column "col2" integer default 0 not null"`,
|
|
350
|
-
);
|
|
351
|
-
});
|
|
352
|
-
});
|
|
353
|
-
|
|
354
|
-
describe("alter-table - rename-column", () => {
|
|
355
|
-
it("should generate SQL to rename a column", () => {
|
|
356
|
-
const operation: MigrationOperation = {
|
|
357
|
-
type: "alter-table",
|
|
358
|
-
name: "test_table",
|
|
359
|
-
value: [
|
|
360
|
-
{
|
|
361
|
-
type: "rename-column",
|
|
362
|
-
from: "old_name",
|
|
363
|
-
to: "new_name",
|
|
364
|
-
},
|
|
365
|
-
],
|
|
366
|
-
};
|
|
367
|
-
|
|
368
|
-
const results = execute(operation, config, () => {
|
|
369
|
-
throw new Error("No custom operations");
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
if (!Array.isArray(results)) {
|
|
373
|
-
throw new Error("Expected array of results");
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
expect(results).toHaveLength(1);
|
|
377
|
-
const compiled = results[0].compile();
|
|
378
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
379
|
-
`"alter table "test_table" rename column "old_name" to "new_name""`,
|
|
380
|
-
);
|
|
381
|
-
});
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
describe("alter-table - drop-column", () => {
|
|
385
|
-
it("should generate SQL to drop a column", () => {
|
|
386
|
-
const operation: MigrationOperation = {
|
|
387
|
-
type: "alter-table",
|
|
388
|
-
name: "test_table",
|
|
389
|
-
value: [
|
|
390
|
-
{
|
|
391
|
-
type: "drop-column",
|
|
392
|
-
name: "to_drop",
|
|
393
|
-
},
|
|
394
|
-
],
|
|
395
|
-
};
|
|
396
|
-
|
|
397
|
-
const results = execute(operation, config, () => {
|
|
398
|
-
throw new Error("No custom operations");
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
if (!Array.isArray(results)) {
|
|
402
|
-
throw new Error("Expected array of results");
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
expect(results).toHaveLength(1);
|
|
406
|
-
const compiled = results[0].compile();
|
|
407
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
408
|
-
`"alter table "test_table" drop column "to_drop""`,
|
|
409
|
-
);
|
|
410
|
-
});
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
describe("alter-table - update-column", () => {
|
|
414
|
-
it("should generate SQL to update column data type (PostgreSQL uses USING clause)", () => {
|
|
415
|
-
const operation: MigrationOperation = {
|
|
416
|
-
type: "alter-table",
|
|
417
|
-
name: "test_table",
|
|
418
|
-
value: [
|
|
419
|
-
{
|
|
420
|
-
type: "update-column",
|
|
421
|
-
name: "test_col",
|
|
422
|
-
value: {
|
|
423
|
-
name: "test_col",
|
|
424
|
-
type: "integer",
|
|
425
|
-
isNullable: true,
|
|
426
|
-
role: "regular",
|
|
427
|
-
},
|
|
428
|
-
updateDataType: true,
|
|
429
|
-
updateNullable: false,
|
|
430
|
-
updateDefault: false,
|
|
431
|
-
},
|
|
432
|
-
],
|
|
433
|
-
};
|
|
434
|
-
|
|
435
|
-
const results = execute(operation, config, () => {
|
|
436
|
-
throw new Error("No custom operations");
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
if (!Array.isArray(results)) {
|
|
440
|
-
throw new Error("Expected array of results");
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
expect(results).toHaveLength(1);
|
|
444
|
-
const compiled = results[0].compile();
|
|
445
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
446
|
-
`"ALTER TABLE "test_table" ALTER COLUMN "test_col" TYPE integer USING ("test_col"::integer)"`,
|
|
447
|
-
);
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
it("should generate SQL to set column NOT NULL", () => {
|
|
451
|
-
const operation: MigrationOperation = {
|
|
452
|
-
type: "alter-table",
|
|
453
|
-
name: "test_table",
|
|
454
|
-
value: [
|
|
455
|
-
{
|
|
456
|
-
type: "update-column",
|
|
457
|
-
name: "test_col",
|
|
458
|
-
value: {
|
|
459
|
-
name: "test_col",
|
|
460
|
-
type: "string",
|
|
461
|
-
isNullable: false,
|
|
462
|
-
role: "regular",
|
|
463
|
-
},
|
|
464
|
-
updateDataType: false,
|
|
465
|
-
updateNullable: true,
|
|
466
|
-
updateDefault: false,
|
|
467
|
-
},
|
|
468
|
-
],
|
|
469
|
-
};
|
|
470
|
-
|
|
471
|
-
const results = execute(operation, config, () => {
|
|
472
|
-
throw new Error("No custom operations");
|
|
473
|
-
});
|
|
474
|
-
|
|
475
|
-
if (!Array.isArray(results)) {
|
|
476
|
-
throw new Error("Expected array of results");
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
expect(results).toHaveLength(1);
|
|
480
|
-
const compiled = results[0].compile();
|
|
481
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
482
|
-
`"alter table "test_table" alter column "test_col" set not null"`,
|
|
483
|
-
);
|
|
484
|
-
});
|
|
485
|
-
|
|
486
|
-
it("should generate SQL to drop NOT NULL constraint", () => {
|
|
487
|
-
const operation: MigrationOperation = {
|
|
488
|
-
type: "alter-table",
|
|
489
|
-
name: "test_table",
|
|
490
|
-
value: [
|
|
491
|
-
{
|
|
492
|
-
type: "update-column",
|
|
493
|
-
name: "test_col",
|
|
494
|
-
value: {
|
|
495
|
-
name: "test_col",
|
|
496
|
-
type: "string",
|
|
497
|
-
isNullable: true,
|
|
498
|
-
role: "regular",
|
|
499
|
-
},
|
|
500
|
-
updateDataType: false,
|
|
501
|
-
updateNullable: true,
|
|
502
|
-
updateDefault: false,
|
|
503
|
-
},
|
|
504
|
-
],
|
|
505
|
-
};
|
|
506
|
-
|
|
507
|
-
const results = execute(operation, config, () => {
|
|
508
|
-
throw new Error("No custom operations");
|
|
509
|
-
});
|
|
510
|
-
|
|
511
|
-
if (!Array.isArray(results)) {
|
|
512
|
-
throw new Error("Expected array of results");
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
expect(results).toHaveLength(1);
|
|
516
|
-
const compiled = results[0].compile();
|
|
517
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
518
|
-
`"alter table "test_table" alter column "test_col" drop not null"`,
|
|
519
|
-
);
|
|
520
|
-
});
|
|
521
|
-
|
|
522
|
-
it("should generate SQL to set default value", () => {
|
|
523
|
-
const operation: MigrationOperation = {
|
|
524
|
-
type: "alter-table",
|
|
525
|
-
name: "test_table",
|
|
526
|
-
value: [
|
|
527
|
-
{
|
|
528
|
-
type: "update-column",
|
|
529
|
-
name: "test_col",
|
|
530
|
-
value: {
|
|
531
|
-
name: "test_col",
|
|
532
|
-
type: "string",
|
|
533
|
-
isNullable: false,
|
|
534
|
-
role: "regular",
|
|
535
|
-
default: { value: "default_value" },
|
|
536
|
-
},
|
|
537
|
-
updateDataType: false,
|
|
538
|
-
updateNullable: false,
|
|
539
|
-
updateDefault: true,
|
|
540
|
-
},
|
|
541
|
-
],
|
|
542
|
-
};
|
|
543
|
-
|
|
544
|
-
const results = execute(operation, config, () => {
|
|
545
|
-
throw new Error("No custom operations");
|
|
546
|
-
});
|
|
547
|
-
|
|
548
|
-
if (!Array.isArray(results)) {
|
|
549
|
-
throw new Error("Expected array of results");
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
expect(results).toHaveLength(1);
|
|
553
|
-
const compiled = results[0].compile();
|
|
554
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
555
|
-
`"alter table "test_table" alter column "test_col" set default 'default_value'"`,
|
|
556
|
-
);
|
|
557
|
-
});
|
|
558
|
-
|
|
559
|
-
it("should generate SQL to drop default value", () => {
|
|
560
|
-
const operation: MigrationOperation = {
|
|
561
|
-
type: "alter-table",
|
|
562
|
-
name: "test_table",
|
|
563
|
-
value: [
|
|
564
|
-
{
|
|
565
|
-
type: "update-column",
|
|
566
|
-
name: "test_col",
|
|
567
|
-
value: {
|
|
568
|
-
name: "test_col",
|
|
569
|
-
type: "string",
|
|
570
|
-
isNullable: true,
|
|
571
|
-
role: "regular",
|
|
572
|
-
},
|
|
573
|
-
updateDataType: false,
|
|
574
|
-
updateNullable: false,
|
|
575
|
-
updateDefault: true,
|
|
576
|
-
},
|
|
577
|
-
],
|
|
578
|
-
};
|
|
579
|
-
|
|
580
|
-
const results = execute(operation, config, () => {
|
|
581
|
-
throw new Error("No custom operations");
|
|
582
|
-
});
|
|
583
|
-
|
|
584
|
-
if (!Array.isArray(results)) {
|
|
585
|
-
throw new Error("Expected array of results");
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
expect(results).toHaveLength(1);
|
|
589
|
-
const compiled = results[0].compile();
|
|
590
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
591
|
-
`"alter table "test_table" alter column "test_col" drop default"`,
|
|
592
|
-
);
|
|
593
|
-
});
|
|
594
|
-
|
|
595
|
-
it("should generate SQL to update multiple properties at once", () => {
|
|
596
|
-
const operation: MigrationOperation = {
|
|
597
|
-
type: "alter-table",
|
|
598
|
-
name: "test_table",
|
|
599
|
-
value: [
|
|
600
|
-
{
|
|
601
|
-
type: "update-column",
|
|
602
|
-
name: "test_col",
|
|
603
|
-
value: {
|
|
604
|
-
name: "test_col",
|
|
605
|
-
type: "integer",
|
|
606
|
-
isNullable: false,
|
|
607
|
-
role: "regular",
|
|
608
|
-
default: { value: 0 },
|
|
609
|
-
},
|
|
610
|
-
updateDataType: true,
|
|
611
|
-
updateNullable: true,
|
|
612
|
-
updateDefault: true,
|
|
613
|
-
},
|
|
614
|
-
],
|
|
615
|
-
};
|
|
616
|
-
|
|
617
|
-
const results = execute(operation, config, () => {
|
|
618
|
-
throw new Error("No custom operations");
|
|
619
|
-
});
|
|
620
|
-
|
|
621
|
-
if (!Array.isArray(results)) {
|
|
622
|
-
throw new Error("Expected array of results");
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
expect(results).toHaveLength(3);
|
|
626
|
-
expect(results[0].compile().sql).toMatchInlineSnapshot(
|
|
627
|
-
`"ALTER TABLE "test_table" ALTER COLUMN "test_col" TYPE integer USING ("test_col"::integer)"`,
|
|
628
|
-
);
|
|
629
|
-
expect(results[1].compile().sql).toMatchInlineSnapshot(
|
|
630
|
-
`"alter table "test_table" alter column "test_col" set not null"`,
|
|
631
|
-
);
|
|
632
|
-
expect(results[2].compile().sql).toMatchInlineSnapshot(
|
|
633
|
-
`"alter table "test_table" alter column "test_col" set default 0"`,
|
|
634
|
-
);
|
|
635
|
-
});
|
|
636
|
-
|
|
637
|
-
it("should throw error when trying to update ID column", () => {
|
|
638
|
-
const operation: MigrationOperation = {
|
|
639
|
-
type: "alter-table",
|
|
640
|
-
name: "test_table",
|
|
641
|
-
value: [
|
|
642
|
-
{
|
|
643
|
-
type: "update-column",
|
|
644
|
-
name: "id",
|
|
645
|
-
value: {
|
|
646
|
-
name: "id",
|
|
647
|
-
type: "bigint",
|
|
648
|
-
isNullable: false,
|
|
649
|
-
role: "external-id",
|
|
650
|
-
},
|
|
651
|
-
updateDataType: true,
|
|
652
|
-
updateNullable: false,
|
|
653
|
-
updateDefault: false,
|
|
654
|
-
},
|
|
655
|
-
],
|
|
656
|
-
};
|
|
657
|
-
|
|
658
|
-
expect(() => {
|
|
659
|
-
execute(operation, config, () => {
|
|
660
|
-
throw new Error("No custom operations");
|
|
661
|
-
});
|
|
662
|
-
}).toThrow(
|
|
663
|
-
"ID columns cannot be updated. Not every database supports updating primary keys and often requires workarounds.",
|
|
664
|
-
);
|
|
665
|
-
});
|
|
666
|
-
|
|
667
|
-
it("should handle no-op update-column (no flags set)", () => {
|
|
668
|
-
const operation: MigrationOperation = {
|
|
669
|
-
type: "alter-table",
|
|
670
|
-
name: "test_table",
|
|
671
|
-
value: [
|
|
672
|
-
{
|
|
673
|
-
type: "update-column",
|
|
674
|
-
name: "test_col",
|
|
675
|
-
value: {
|
|
676
|
-
name: "test_col",
|
|
677
|
-
type: "string",
|
|
678
|
-
isNullable: true,
|
|
679
|
-
role: "regular",
|
|
680
|
-
},
|
|
681
|
-
updateDataType: false,
|
|
682
|
-
updateNullable: false,
|
|
683
|
-
updateDefault: false,
|
|
684
|
-
},
|
|
685
|
-
],
|
|
686
|
-
};
|
|
687
|
-
|
|
688
|
-
const results = execute(operation, config, () => {
|
|
689
|
-
throw new Error("No custom operations");
|
|
690
|
-
});
|
|
691
|
-
|
|
692
|
-
if (!Array.isArray(results)) {
|
|
693
|
-
throw new Error("Expected array of results");
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
// No-op should return empty array
|
|
697
|
-
expect(results).toHaveLength(0);
|
|
698
|
-
});
|
|
699
|
-
|
|
700
|
-
it("should generate SQL for timestamp default", () => {
|
|
701
|
-
const operation: MigrationOperation = {
|
|
702
|
-
type: "alter-table",
|
|
703
|
-
name: "test_table",
|
|
704
|
-
value: [
|
|
705
|
-
{
|
|
706
|
-
type: "update-column",
|
|
707
|
-
name: "updated_at",
|
|
708
|
-
value: {
|
|
709
|
-
name: "updated_at",
|
|
710
|
-
type: "timestamp",
|
|
711
|
-
isNullable: false,
|
|
712
|
-
role: "regular",
|
|
713
|
-
default: { dbSpecial: "now" },
|
|
714
|
-
},
|
|
715
|
-
updateDataType: false,
|
|
716
|
-
updateNullable: false,
|
|
717
|
-
updateDefault: true,
|
|
718
|
-
},
|
|
719
|
-
],
|
|
720
|
-
};
|
|
721
|
-
|
|
722
|
-
const results = execute(operation, config, () => {
|
|
723
|
-
throw new Error("No custom operations");
|
|
724
|
-
});
|
|
725
|
-
|
|
726
|
-
if (!Array.isArray(results)) {
|
|
727
|
-
throw new Error("Expected array of results");
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
expect(results).toHaveLength(1);
|
|
731
|
-
const compiled = results[0].compile();
|
|
732
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
733
|
-
`"alter table "test_table" alter column "updated_at" set default CURRENT_TIMESTAMP"`,
|
|
734
|
-
);
|
|
735
|
-
});
|
|
736
|
-
});
|
|
737
|
-
|
|
738
|
-
describe("add-foreign-key", () => {
|
|
739
|
-
it("should generate SQL for foreign key constraint", () => {
|
|
740
|
-
const operation: MigrationOperation = {
|
|
741
|
-
type: "add-foreign-key",
|
|
742
|
-
table: "posts",
|
|
743
|
-
value: {
|
|
744
|
-
name: "posts_user_id_fk",
|
|
745
|
-
columns: ["user_id"],
|
|
746
|
-
referencedTable: "users",
|
|
747
|
-
referencedColumns: ["id"],
|
|
748
|
-
},
|
|
749
|
-
};
|
|
750
|
-
|
|
751
|
-
const result = execute(operation, config, () => {
|
|
752
|
-
throw new Error("No custom operations");
|
|
753
|
-
});
|
|
754
|
-
|
|
755
|
-
assertSingleResult(result);
|
|
756
|
-
|
|
757
|
-
const compiled = result.compile();
|
|
758
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
759
|
-
`"alter table "posts" add constraint "posts_user_id_fk" foreign key ("user_id") references "users" ("id") on delete restrict on update restrict"`,
|
|
760
|
-
);
|
|
761
|
-
});
|
|
762
|
-
|
|
763
|
-
it("should generate SQL for composite foreign key", () => {
|
|
764
|
-
const operation: MigrationOperation = {
|
|
765
|
-
type: "add-foreign-key",
|
|
766
|
-
table: "posts",
|
|
767
|
-
value: {
|
|
768
|
-
name: "posts_user_fk",
|
|
769
|
-
columns: ["org_id", "user_id"],
|
|
770
|
-
referencedTable: "users",
|
|
771
|
-
referencedColumns: ["org_id", "user_id"],
|
|
772
|
-
},
|
|
773
|
-
};
|
|
774
|
-
|
|
775
|
-
const result = execute(operation, config, () => {
|
|
776
|
-
throw new Error("No custom operations");
|
|
777
|
-
});
|
|
778
|
-
|
|
779
|
-
assertSingleResult(result);
|
|
780
|
-
|
|
781
|
-
const compiled = result.compile();
|
|
782
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
783
|
-
`"alter table "posts" add constraint "posts_user_fk" foreign key ("org_id", "user_id") references "users" ("org_id", "user_id") on delete restrict on update restrict"`,
|
|
784
|
-
);
|
|
785
|
-
});
|
|
786
|
-
});
|
|
787
|
-
|
|
788
|
-
describe("drop-foreign-key", () => {
|
|
789
|
-
it("should generate SQL to drop foreign key constraint", () => {
|
|
790
|
-
const operation: MigrationOperation = {
|
|
791
|
-
type: "drop-foreign-key",
|
|
792
|
-
table: "posts",
|
|
793
|
-
name: "posts_user_id_fk",
|
|
794
|
-
};
|
|
795
|
-
|
|
796
|
-
const result = execute(operation, config, () => {
|
|
797
|
-
throw new Error("No custom operations");
|
|
798
|
-
});
|
|
799
|
-
|
|
800
|
-
assertSingleResult(result);
|
|
801
|
-
|
|
802
|
-
const compiled = result.compile();
|
|
803
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
804
|
-
`"alter table "posts" drop constraint if exists "posts_user_id_fk""`,
|
|
805
|
-
);
|
|
806
|
-
});
|
|
807
|
-
});
|
|
808
|
-
|
|
809
|
-
describe("add-index", () => {
|
|
810
|
-
it("should generate SQL for regular index", () => {
|
|
811
|
-
const operation: MigrationOperation = {
|
|
812
|
-
type: "add-index",
|
|
813
|
-
table: "test_table",
|
|
814
|
-
columns: ["email"],
|
|
815
|
-
name: "idx_email",
|
|
816
|
-
unique: false,
|
|
817
|
-
};
|
|
818
|
-
|
|
819
|
-
const result = execute(operation, config, () => {
|
|
820
|
-
throw new Error("No custom operations");
|
|
821
|
-
});
|
|
822
|
-
|
|
823
|
-
assertSingleResult(result);
|
|
824
|
-
|
|
825
|
-
const compiled = result.compile();
|
|
826
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
827
|
-
`"create index "idx_email" on "test_table" ("email")"`,
|
|
828
|
-
);
|
|
829
|
-
});
|
|
830
|
-
|
|
831
|
-
it("should generate SQL for unique index", () => {
|
|
832
|
-
const operation: MigrationOperation = {
|
|
833
|
-
type: "add-index",
|
|
834
|
-
table: "test_table",
|
|
835
|
-
columns: ["email"],
|
|
836
|
-
name: "idx_unique_email",
|
|
837
|
-
unique: true,
|
|
838
|
-
};
|
|
839
|
-
|
|
840
|
-
const result = execute(operation, config, () => {
|
|
841
|
-
throw new Error("No custom operations");
|
|
842
|
-
});
|
|
843
|
-
|
|
844
|
-
assertSingleResult(result);
|
|
845
|
-
|
|
846
|
-
const compiled = result.compile();
|
|
847
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
848
|
-
`"create unique index "idx_unique_email" on "test_table" ("email")"`,
|
|
849
|
-
);
|
|
850
|
-
});
|
|
851
|
-
|
|
852
|
-
it("should generate SQL for composite index", () => {
|
|
853
|
-
const operation: MigrationOperation = {
|
|
854
|
-
type: "add-index",
|
|
855
|
-
table: "test_table",
|
|
856
|
-
columns: ["email", "name"],
|
|
857
|
-
name: "idx_email_name",
|
|
858
|
-
unique: false,
|
|
859
|
-
};
|
|
860
|
-
|
|
861
|
-
const result = execute(operation, config, () => {
|
|
862
|
-
throw new Error("No custom operations");
|
|
863
|
-
});
|
|
864
|
-
|
|
865
|
-
assertSingleResult(result);
|
|
866
|
-
|
|
867
|
-
const compiled = result.compile();
|
|
868
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
869
|
-
`"create index "idx_email_name" on "test_table" ("email", "name")"`,
|
|
870
|
-
);
|
|
871
|
-
});
|
|
872
|
-
|
|
873
|
-
it("should generate SQL for unique composite index", () => {
|
|
874
|
-
const operation: MigrationOperation = {
|
|
875
|
-
type: "add-index",
|
|
876
|
-
table: "test_table",
|
|
877
|
-
columns: ["email", "name"],
|
|
878
|
-
name: "idx_unique_email_name",
|
|
879
|
-
unique: true,
|
|
880
|
-
};
|
|
881
|
-
|
|
882
|
-
const result = execute(operation, config, () => {
|
|
883
|
-
throw new Error("No custom operations");
|
|
884
|
-
});
|
|
885
|
-
|
|
886
|
-
assertSingleResult(result);
|
|
887
|
-
|
|
888
|
-
const compiled = result.compile();
|
|
889
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
890
|
-
`"create unique index "idx_unique_email_name" on "test_table" ("email", "name")"`,
|
|
891
|
-
);
|
|
892
|
-
});
|
|
893
|
-
});
|
|
894
|
-
|
|
895
|
-
describe("drop-index", () => {
|
|
896
|
-
it("should generate SQL to drop index", () => {
|
|
897
|
-
const operation: MigrationOperation = {
|
|
898
|
-
type: "drop-index",
|
|
899
|
-
table: "test_table",
|
|
900
|
-
name: "idx_email",
|
|
901
|
-
};
|
|
902
|
-
|
|
903
|
-
const result = execute(operation, config, () => {
|
|
904
|
-
throw new Error("No custom operations");
|
|
905
|
-
});
|
|
906
|
-
|
|
907
|
-
assertSingleResult(result);
|
|
908
|
-
|
|
909
|
-
const compiled = result.compile();
|
|
910
|
-
expect(compiled.sql).toMatchInlineSnapshot(`"drop index if exists "idx_email""`);
|
|
911
|
-
});
|
|
912
|
-
});
|
|
913
|
-
|
|
914
|
-
describe("custom operations", () => {
|
|
915
|
-
it("should handle custom operations via callback", () => {
|
|
916
|
-
const operation: MigrationOperation = {
|
|
917
|
-
type: "custom",
|
|
918
|
-
customType: "test-operation",
|
|
919
|
-
data: "test-data",
|
|
920
|
-
};
|
|
921
|
-
|
|
922
|
-
let customCallbackCalled = false;
|
|
923
|
-
|
|
924
|
-
const result = execute(operation, config, (op) => {
|
|
925
|
-
customCallbackCalled = true;
|
|
926
|
-
expect(op).toEqual(operation);
|
|
927
|
-
|
|
928
|
-
// Return a kysely query
|
|
929
|
-
return db.schema.createTable("custom_table").addColumn("id", "integer");
|
|
930
|
-
});
|
|
931
|
-
|
|
932
|
-
expect(customCallbackCalled).toBe(true);
|
|
933
|
-
|
|
934
|
-
assertSingleResult(result);
|
|
935
|
-
|
|
936
|
-
const compiled = result.compile();
|
|
937
|
-
expect(compiled.sql).toContain("create table");
|
|
938
|
-
expect(compiled.sql).toContain("custom_table");
|
|
939
|
-
});
|
|
940
|
-
|
|
941
|
-
it("should support custom operations returning array of nodes", () => {
|
|
942
|
-
const operation: MigrationOperation = {
|
|
943
|
-
type: "custom",
|
|
944
|
-
customType: "multi-operation",
|
|
945
|
-
};
|
|
946
|
-
|
|
947
|
-
const results = execute(operation, config, () => {
|
|
948
|
-
return [
|
|
949
|
-
db.schema.createTable("table1").addColumn("id", "integer"),
|
|
950
|
-
db.schema.createTable("table2").addColumn("id", "integer"),
|
|
951
|
-
];
|
|
952
|
-
});
|
|
953
|
-
|
|
954
|
-
if (!Array.isArray(results)) {
|
|
955
|
-
throw new Error("Expected array of results");
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
expect(results).toHaveLength(2);
|
|
959
|
-
expect(results[0].compile().sql).toContain("table1");
|
|
960
|
-
expect(results[1].compile().sql).toContain("table2");
|
|
961
|
-
});
|
|
962
|
-
});
|
|
963
|
-
|
|
964
|
-
describe("complex migration scenarios", () => {
|
|
965
|
-
it("should generate correct SQL for full schema migration", () => {
|
|
966
|
-
// 1. Create users table
|
|
967
|
-
const createUsers = execute(
|
|
968
|
-
{
|
|
969
|
-
type: "create-table",
|
|
970
|
-
name: "users",
|
|
971
|
-
columns: [
|
|
972
|
-
{ name: "id", type: "integer", isNullable: false, role: "external-id" },
|
|
973
|
-
{ name: "email", type: "string", isNullable: false, role: "regular" },
|
|
974
|
-
{ name: "name", type: "string", isNullable: false, role: "regular" },
|
|
975
|
-
],
|
|
976
|
-
},
|
|
977
|
-
config,
|
|
978
|
-
() => {
|
|
979
|
-
throw new Error("No custom operations");
|
|
980
|
-
},
|
|
981
|
-
);
|
|
982
|
-
|
|
983
|
-
assertSingleResult(createUsers);
|
|
984
|
-
|
|
985
|
-
expect(createUsers.compile().sql).toMatchInlineSnapshot(
|
|
986
|
-
`"create table "users" ("id" integer not null unique, "email" text not null, "name" text not null)"`,
|
|
987
|
-
);
|
|
988
|
-
|
|
989
|
-
// 2. Add unique index on email
|
|
990
|
-
const addIndex = execute(
|
|
991
|
-
{
|
|
992
|
-
type: "add-index",
|
|
993
|
-
table: "users",
|
|
994
|
-
columns: ["email"],
|
|
995
|
-
name: "idx_unique_email",
|
|
996
|
-
unique: true,
|
|
997
|
-
},
|
|
998
|
-
config,
|
|
999
|
-
() => {
|
|
1000
|
-
throw new Error("No custom operations");
|
|
1001
|
-
},
|
|
1002
|
-
);
|
|
1003
|
-
|
|
1004
|
-
assertSingleResult(addIndex);
|
|
1005
|
-
|
|
1006
|
-
expect(addIndex.compile().sql).toMatchInlineSnapshot(
|
|
1007
|
-
`"create unique index "idx_unique_email" on "users" ("email")"`,
|
|
1008
|
-
);
|
|
1009
|
-
|
|
1010
|
-
// 3. Create posts table
|
|
1011
|
-
const createPosts = execute(
|
|
1012
|
-
{
|
|
1013
|
-
type: "create-table",
|
|
1014
|
-
name: "posts",
|
|
1015
|
-
columns: [
|
|
1016
|
-
{ name: "id", type: "integer", isNullable: false, role: "external-id" },
|
|
1017
|
-
{ name: "user_id", type: "integer", isNullable: false, role: "reference" },
|
|
1018
|
-
{ name: "title", type: "string", isNullable: false, role: "regular" },
|
|
1019
|
-
{ name: "content", type: "string", isNullable: false, role: "regular" },
|
|
1020
|
-
],
|
|
1021
|
-
},
|
|
1022
|
-
config,
|
|
1023
|
-
() => {
|
|
1024
|
-
throw new Error("No custom operations");
|
|
1025
|
-
},
|
|
1026
|
-
);
|
|
1027
|
-
|
|
1028
|
-
assertSingleResult(createPosts);
|
|
1029
|
-
|
|
1030
|
-
expect(createPosts.compile().sql).toMatchInlineSnapshot(
|
|
1031
|
-
`"create table "posts" ("id" integer not null unique, "user_id" integer not null, "title" text not null, "content" text not null)"`,
|
|
1032
|
-
);
|
|
1033
|
-
|
|
1034
|
-
// 4. Add foreign key
|
|
1035
|
-
const addFk = execute(
|
|
1036
|
-
{
|
|
1037
|
-
type: "add-foreign-key",
|
|
1038
|
-
table: "posts",
|
|
1039
|
-
value: {
|
|
1040
|
-
name: "posts_user_id_fk",
|
|
1041
|
-
columns: ["user_id"],
|
|
1042
|
-
referencedTable: "users",
|
|
1043
|
-
referencedColumns: ["id"],
|
|
1044
|
-
},
|
|
1045
|
-
},
|
|
1046
|
-
config,
|
|
1047
|
-
() => {
|
|
1048
|
-
throw new Error("No custom operations");
|
|
1049
|
-
},
|
|
1050
|
-
);
|
|
1051
|
-
|
|
1052
|
-
assertSingleResult(addFk);
|
|
1053
|
-
|
|
1054
|
-
expect(addFk.compile().sql).toMatchInlineSnapshot(
|
|
1055
|
-
`"alter table "posts" add constraint "posts_user_id_fk" foreign key ("user_id") references "users" ("id") on delete restrict on update restrict"`,
|
|
1056
|
-
);
|
|
1057
|
-
|
|
1058
|
-
// 5. Alter posts table to add a new column
|
|
1059
|
-
const alterResults = execute(
|
|
1060
|
-
{
|
|
1061
|
-
type: "alter-table",
|
|
1062
|
-
name: "posts",
|
|
1063
|
-
value: [
|
|
1064
|
-
{
|
|
1065
|
-
type: "create-column",
|
|
1066
|
-
value: {
|
|
1067
|
-
name: "published",
|
|
1068
|
-
type: "bool",
|
|
1069
|
-
isNullable: false,
|
|
1070
|
-
role: "regular",
|
|
1071
|
-
default: { value: false },
|
|
1072
|
-
},
|
|
1073
|
-
},
|
|
1074
|
-
],
|
|
1075
|
-
},
|
|
1076
|
-
config,
|
|
1077
|
-
() => {
|
|
1078
|
-
throw new Error("No custom operations");
|
|
1079
|
-
},
|
|
1080
|
-
);
|
|
1081
|
-
|
|
1082
|
-
if (!Array.isArray(alterResults)) {
|
|
1083
|
-
throw new Error("Expected array of results");
|
|
1084
|
-
}
|
|
1085
|
-
|
|
1086
|
-
expect(alterResults[0].compile().sql).toMatchInlineSnapshot(
|
|
1087
|
-
`"alter table "posts" add column "published" boolean default false not null"`,
|
|
1088
|
-
);
|
|
1089
|
-
});
|
|
1090
|
-
|
|
1091
|
-
it("should handle multiple alter-table operations", () => {
|
|
1092
|
-
const operation: MigrationOperation = {
|
|
1093
|
-
type: "alter-table",
|
|
1094
|
-
name: "users",
|
|
1095
|
-
value: [
|
|
1096
|
-
{
|
|
1097
|
-
type: "create-column",
|
|
1098
|
-
value: {
|
|
1099
|
-
name: "age",
|
|
1100
|
-
type: "integer",
|
|
1101
|
-
isNullable: true,
|
|
1102
|
-
role: "regular",
|
|
1103
|
-
},
|
|
1104
|
-
},
|
|
1105
|
-
{
|
|
1106
|
-
type: "rename-column",
|
|
1107
|
-
from: "name",
|
|
1108
|
-
to: "full_name",
|
|
1109
|
-
},
|
|
1110
|
-
{
|
|
1111
|
-
type: "drop-column",
|
|
1112
|
-
name: "old_field",
|
|
1113
|
-
},
|
|
1114
|
-
],
|
|
1115
|
-
};
|
|
1116
|
-
|
|
1117
|
-
const results = execute(operation, config, () => {
|
|
1118
|
-
throw new Error("No custom operations");
|
|
1119
|
-
});
|
|
1120
|
-
|
|
1121
|
-
if (!Array.isArray(results)) {
|
|
1122
|
-
throw new Error("Expected array of results");
|
|
1123
|
-
}
|
|
1124
|
-
|
|
1125
|
-
expect(results).toHaveLength(3);
|
|
1126
|
-
expect(results[0].compile().sql).toMatchInlineSnapshot(
|
|
1127
|
-
`"alter table "users" add column "age" integer"`,
|
|
1128
|
-
);
|
|
1129
|
-
expect(results[1].compile().sql).toMatchInlineSnapshot(
|
|
1130
|
-
`"alter table "users" rename column "name" to "full_name""`,
|
|
1131
|
-
);
|
|
1132
|
-
expect(results[2].compile().sql).toMatchInlineSnapshot(
|
|
1133
|
-
`"alter table "users" drop column "old_field""`,
|
|
1134
|
-
);
|
|
1135
|
-
});
|
|
1136
|
-
});
|
|
1137
|
-
|
|
1138
|
-
describe("edge cases", () => {
|
|
1139
|
-
it("should handle table names with special characters", () => {
|
|
1140
|
-
const operation: MigrationOperation = {
|
|
1141
|
-
type: "create-table",
|
|
1142
|
-
name: "user-profiles",
|
|
1143
|
-
columns: [{ name: "id", type: "integer", isNullable: false, role: "external-id" }],
|
|
1144
|
-
};
|
|
1145
|
-
|
|
1146
|
-
const result = execute(operation, config, () => {
|
|
1147
|
-
throw new Error("No custom operations");
|
|
1148
|
-
});
|
|
1149
|
-
|
|
1150
|
-
assertSingleResult(result);
|
|
1151
|
-
|
|
1152
|
-
const compiled = result.compile();
|
|
1153
|
-
expect(compiled.sql).toContain('"user-profiles"');
|
|
1154
|
-
});
|
|
1155
|
-
|
|
1156
|
-
it("should handle column names with special characters", () => {
|
|
1157
|
-
const operation: MigrationOperation = {
|
|
1158
|
-
type: "create-table",
|
|
1159
|
-
name: "test",
|
|
1160
|
-
columns: [
|
|
1161
|
-
{ name: "id", type: "integer", isNullable: false, role: "external-id" },
|
|
1162
|
-
{ name: "user-name", type: "string", isNullable: false, role: "regular" },
|
|
1163
|
-
],
|
|
1164
|
-
};
|
|
1165
|
-
|
|
1166
|
-
const result = execute(operation, config, () => {
|
|
1167
|
-
throw new Error("No custom operations");
|
|
1168
|
-
});
|
|
1169
|
-
|
|
1170
|
-
assertSingleResult(result);
|
|
1171
|
-
|
|
1172
|
-
const compiled = result.compile();
|
|
1173
|
-
expect(compiled.sql).toContain('"user-name"');
|
|
1174
|
-
});
|
|
1175
|
-
|
|
1176
|
-
it("should properly escape string default values", () => {
|
|
1177
|
-
const operation: MigrationOperation = {
|
|
1178
|
-
type: "create-table",
|
|
1179
|
-
name: "test",
|
|
1180
|
-
columns: [
|
|
1181
|
-
{ name: "id", type: "integer", isNullable: false, role: "external-id" },
|
|
1182
|
-
{
|
|
1183
|
-
name: "status",
|
|
1184
|
-
type: "string",
|
|
1185
|
-
isNullable: false,
|
|
1186
|
-
role: "regular",
|
|
1187
|
-
default: { value: "it's pending" },
|
|
1188
|
-
},
|
|
1189
|
-
],
|
|
1190
|
-
};
|
|
1191
|
-
|
|
1192
|
-
const result = execute(operation, config, () => {
|
|
1193
|
-
throw new Error("No custom operations");
|
|
1194
|
-
});
|
|
1195
|
-
|
|
1196
|
-
assertSingleResult(result);
|
|
1197
|
-
|
|
1198
|
-
const compiled = result.compile();
|
|
1199
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
1200
|
-
`"create table "test" ("id" integer not null unique, "status" text default 'it''s pending' not null)"`,
|
|
1201
|
-
);
|
|
1202
|
-
});
|
|
1203
|
-
});
|
|
1204
|
-
|
|
1205
|
-
describe("real-world complex scenarios", () => {
|
|
1206
|
-
it("should handle complete blog schema migration with auto-increment IDs", () => {
|
|
1207
|
-
// 1. Create users table with auto-increment ID
|
|
1208
|
-
const createUsers = execute(
|
|
1209
|
-
{
|
|
1210
|
-
type: "create-table",
|
|
1211
|
-
name: "users",
|
|
1212
|
-
columns: [
|
|
1213
|
-
{
|
|
1214
|
-
name: "id",
|
|
1215
|
-
type: "integer",
|
|
1216
|
-
isNullable: false,
|
|
1217
|
-
role: "external-id",
|
|
1218
|
-
default: { runtime: "cuid" },
|
|
1219
|
-
},
|
|
1220
|
-
{
|
|
1221
|
-
name: "name",
|
|
1222
|
-
type: "string",
|
|
1223
|
-
isNullable: false,
|
|
1224
|
-
role: "regular",
|
|
1225
|
-
},
|
|
1226
|
-
],
|
|
1227
|
-
},
|
|
1228
|
-
config,
|
|
1229
|
-
() => {
|
|
1230
|
-
throw new Error("No custom operations");
|
|
1231
|
-
},
|
|
1232
|
-
);
|
|
1233
|
-
|
|
1234
|
-
assertSingleResult(createUsers);
|
|
1235
|
-
expect(createUsers.compile().sql).toMatchInlineSnapshot(
|
|
1236
|
-
`"create table "users" ("id" integer not null unique, "name" text not null)"`,
|
|
1237
|
-
);
|
|
1238
|
-
|
|
1239
|
-
// 2. Create posts table with auto-increment ID and reference
|
|
1240
|
-
const createPosts = execute(
|
|
1241
|
-
{
|
|
1242
|
-
type: "create-table",
|
|
1243
|
-
name: "posts",
|
|
1244
|
-
columns: [
|
|
1245
|
-
{
|
|
1246
|
-
name: "id",
|
|
1247
|
-
type: "integer",
|
|
1248
|
-
isNullable: false,
|
|
1249
|
-
role: "external-id",
|
|
1250
|
-
default: { runtime: "cuid" },
|
|
1251
|
-
},
|
|
1252
|
-
{
|
|
1253
|
-
name: "title",
|
|
1254
|
-
type: "string",
|
|
1255
|
-
isNullable: false,
|
|
1256
|
-
role: "regular",
|
|
1257
|
-
},
|
|
1258
|
-
{
|
|
1259
|
-
name: "content",
|
|
1260
|
-
type: "string",
|
|
1261
|
-
isNullable: false,
|
|
1262
|
-
role: "regular",
|
|
1263
|
-
},
|
|
1264
|
-
{
|
|
1265
|
-
name: "userId",
|
|
1266
|
-
type: "integer",
|
|
1267
|
-
isNullable: false,
|
|
1268
|
-
role: "reference",
|
|
1269
|
-
},
|
|
1270
|
-
],
|
|
1271
|
-
},
|
|
1272
|
-
config,
|
|
1273
|
-
() => {
|
|
1274
|
-
throw new Error("No custom operations");
|
|
1275
|
-
},
|
|
1276
|
-
);
|
|
1277
|
-
|
|
1278
|
-
assertSingleResult(createPosts);
|
|
1279
|
-
expect(createPosts.compile().sql).toMatchInlineSnapshot(
|
|
1280
|
-
`"create table "posts" ("id" integer not null unique, "title" text not null, "content" text not null, "userId" integer not null)"`,
|
|
1281
|
-
);
|
|
1282
|
-
|
|
1283
|
-
// 3. Add foreign key reference
|
|
1284
|
-
const addReference = execute(
|
|
1285
|
-
{
|
|
1286
|
-
type: "add-foreign-key",
|
|
1287
|
-
table: "posts",
|
|
1288
|
-
value: {
|
|
1289
|
-
name: "posts_userId_fk",
|
|
1290
|
-
columns: ["userId"],
|
|
1291
|
-
referencedTable: "users",
|
|
1292
|
-
referencedColumns: ["id"],
|
|
1293
|
-
},
|
|
1294
|
-
},
|
|
1295
|
-
config,
|
|
1296
|
-
() => {
|
|
1297
|
-
throw new Error("No custom operations");
|
|
1298
|
-
},
|
|
1299
|
-
);
|
|
1300
|
-
|
|
1301
|
-
assertSingleResult(addReference);
|
|
1302
|
-
expect(addReference.compile().sql).toMatchInlineSnapshot(
|
|
1303
|
-
`"alter table "posts" add constraint "posts_userId_fk" foreign key ("userId") references "users" ("id") on delete restrict on update restrict"`,
|
|
1304
|
-
);
|
|
1305
|
-
|
|
1306
|
-
// 4. Alter posts table to add nullable summary column
|
|
1307
|
-
const alterPosts = execute(
|
|
1308
|
-
{
|
|
1309
|
-
type: "alter-table",
|
|
1310
|
-
name: "posts",
|
|
1311
|
-
value: [
|
|
1312
|
-
{
|
|
1313
|
-
type: "create-column",
|
|
1314
|
-
value: {
|
|
1315
|
-
name: "summary",
|
|
1316
|
-
type: "string",
|
|
1317
|
-
isNullable: true,
|
|
1318
|
-
role: "regular",
|
|
1319
|
-
},
|
|
1320
|
-
},
|
|
1321
|
-
],
|
|
1322
|
-
},
|
|
1323
|
-
config,
|
|
1324
|
-
() => {
|
|
1325
|
-
throw new Error("No custom operations");
|
|
1326
|
-
},
|
|
1327
|
-
);
|
|
1328
|
-
|
|
1329
|
-
if (!Array.isArray(alterPosts)) {
|
|
1330
|
-
throw new Error("Expected array of results");
|
|
1331
|
-
}
|
|
1332
|
-
|
|
1333
|
-
expect(alterPosts).toHaveLength(1);
|
|
1334
|
-
expect(alterPosts[0].compile().sql).toMatchInlineSnapshot(
|
|
1335
|
-
`"alter table "posts" add column "summary" text"`,
|
|
1336
|
-
);
|
|
1337
|
-
|
|
1338
|
-
// 5. Create index on title
|
|
1339
|
-
const createIndex = execute(
|
|
1340
|
-
{
|
|
1341
|
-
type: "add-index",
|
|
1342
|
-
table: "posts",
|
|
1343
|
-
columns: ["title"],
|
|
1344
|
-
name: "idx_title",
|
|
1345
|
-
unique: false,
|
|
1346
|
-
},
|
|
1347
|
-
config,
|
|
1348
|
-
() => {
|
|
1349
|
-
throw new Error("No custom operations");
|
|
1350
|
-
},
|
|
1351
|
-
);
|
|
1352
|
-
|
|
1353
|
-
assertSingleResult(createIndex);
|
|
1354
|
-
expect(createIndex.compile().sql).toMatchInlineSnapshot(
|
|
1355
|
-
`"create index "idx_title" on "posts" ("title")"`,
|
|
1356
|
-
);
|
|
1357
|
-
});
|
|
1358
|
-
|
|
1359
|
-
it("should handle e-commerce schema with complex relationships", () => {
|
|
1360
|
-
// 1. Create customers table
|
|
1361
|
-
const createCustomers = execute(
|
|
1362
|
-
{
|
|
1363
|
-
type: "create-table",
|
|
1364
|
-
name: "customers",
|
|
1365
|
-
columns: [
|
|
1366
|
-
{
|
|
1367
|
-
name: "id",
|
|
1368
|
-
type: "integer",
|
|
1369
|
-
isNullable: false,
|
|
1370
|
-
role: "external-id",
|
|
1371
|
-
default: { runtime: "cuid" },
|
|
1372
|
-
},
|
|
1373
|
-
{
|
|
1374
|
-
name: "email",
|
|
1375
|
-
type: "string",
|
|
1376
|
-
isNullable: false,
|
|
1377
|
-
role: "regular",
|
|
1378
|
-
},
|
|
1379
|
-
{
|
|
1380
|
-
name: "firstName",
|
|
1381
|
-
type: "string",
|
|
1382
|
-
isNullable: false,
|
|
1383
|
-
role: "regular",
|
|
1384
|
-
},
|
|
1385
|
-
{
|
|
1386
|
-
name: "lastName",
|
|
1387
|
-
type: "string",
|
|
1388
|
-
isNullable: false,
|
|
1389
|
-
role: "regular",
|
|
1390
|
-
},
|
|
1391
|
-
{
|
|
1392
|
-
name: "phone",
|
|
1393
|
-
type: "string",
|
|
1394
|
-
isNullable: true,
|
|
1395
|
-
role: "regular",
|
|
1396
|
-
},
|
|
1397
|
-
{
|
|
1398
|
-
name: "createdAt",
|
|
1399
|
-
type: "timestamp",
|
|
1400
|
-
isNullable: false,
|
|
1401
|
-
role: "regular",
|
|
1402
|
-
default: { dbSpecial: "now" },
|
|
1403
|
-
},
|
|
1404
|
-
],
|
|
1405
|
-
},
|
|
1406
|
-
config,
|
|
1407
|
-
() => {
|
|
1408
|
-
throw new Error("No custom operations");
|
|
1409
|
-
},
|
|
1410
|
-
);
|
|
1411
|
-
|
|
1412
|
-
assertSingleResult(createCustomers);
|
|
1413
|
-
expect(createCustomers.compile().sql).toMatchInlineSnapshot(
|
|
1414
|
-
`"create table "customers" ("id" integer not null unique, "email" text not null, "firstName" text not null, "lastName" text not null, "phone" text, "createdAt" timestamp default CURRENT_TIMESTAMP not null)"`,
|
|
1415
|
-
);
|
|
1416
|
-
|
|
1417
|
-
// 2. Create products table
|
|
1418
|
-
const createProducts = execute(
|
|
1419
|
-
{
|
|
1420
|
-
type: "create-table",
|
|
1421
|
-
name: "products",
|
|
1422
|
-
columns: [
|
|
1423
|
-
{
|
|
1424
|
-
name: "id",
|
|
1425
|
-
type: "integer",
|
|
1426
|
-
isNullable: false,
|
|
1427
|
-
role: "external-id",
|
|
1428
|
-
default: { runtime: "cuid" },
|
|
1429
|
-
},
|
|
1430
|
-
{
|
|
1431
|
-
name: "name",
|
|
1432
|
-
type: "string",
|
|
1433
|
-
isNullable: false,
|
|
1434
|
-
role: "regular",
|
|
1435
|
-
},
|
|
1436
|
-
{
|
|
1437
|
-
name: "description",
|
|
1438
|
-
type: "string",
|
|
1439
|
-
isNullable: true,
|
|
1440
|
-
role: "regular",
|
|
1441
|
-
},
|
|
1442
|
-
{
|
|
1443
|
-
name: "price",
|
|
1444
|
-
type: "decimal",
|
|
1445
|
-
isNullable: false,
|
|
1446
|
-
role: "regular",
|
|
1447
|
-
},
|
|
1448
|
-
{
|
|
1449
|
-
name: "stock",
|
|
1450
|
-
type: "integer",
|
|
1451
|
-
isNullable: false,
|
|
1452
|
-
role: "regular",
|
|
1453
|
-
default: { value: 0 },
|
|
1454
|
-
},
|
|
1455
|
-
{
|
|
1456
|
-
name: "isActive",
|
|
1457
|
-
type: "bool",
|
|
1458
|
-
isNullable: false,
|
|
1459
|
-
role: "regular",
|
|
1460
|
-
default: { value: true },
|
|
1461
|
-
},
|
|
1462
|
-
],
|
|
1463
|
-
},
|
|
1464
|
-
config,
|
|
1465
|
-
() => {
|
|
1466
|
-
throw new Error("No custom operations");
|
|
1467
|
-
},
|
|
1468
|
-
);
|
|
1469
|
-
|
|
1470
|
-
assertSingleResult(createProducts);
|
|
1471
|
-
expect(createProducts.compile().sql).toMatchInlineSnapshot(
|
|
1472
|
-
`"create table "products" ("id" integer not null unique, "name" text not null, "description" text, "price" decimal not null, "stock" integer default 0 not null, "isActive" boolean default true not null)"`,
|
|
1473
|
-
);
|
|
1474
|
-
|
|
1475
|
-
// 3. Create orders table
|
|
1476
|
-
const createOrders = execute(
|
|
1477
|
-
{
|
|
1478
|
-
type: "create-table",
|
|
1479
|
-
name: "orders",
|
|
1480
|
-
columns: [
|
|
1481
|
-
{
|
|
1482
|
-
name: "id",
|
|
1483
|
-
type: "integer",
|
|
1484
|
-
isNullable: false,
|
|
1485
|
-
role: "external-id",
|
|
1486
|
-
default: { runtime: "cuid" },
|
|
1487
|
-
},
|
|
1488
|
-
{
|
|
1489
|
-
name: "customerId",
|
|
1490
|
-
type: "integer",
|
|
1491
|
-
isNullable: false,
|
|
1492
|
-
role: "reference",
|
|
1493
|
-
},
|
|
1494
|
-
{
|
|
1495
|
-
name: "status",
|
|
1496
|
-
type: "string",
|
|
1497
|
-
isNullable: false,
|
|
1498
|
-
role: "regular",
|
|
1499
|
-
default: { value: "pending" },
|
|
1500
|
-
},
|
|
1501
|
-
{
|
|
1502
|
-
name: "total",
|
|
1503
|
-
type: "decimal",
|
|
1504
|
-
isNullable: false,
|
|
1505
|
-
role: "regular",
|
|
1506
|
-
},
|
|
1507
|
-
{
|
|
1508
|
-
name: "orderDate",
|
|
1509
|
-
type: "timestamp",
|
|
1510
|
-
isNullable: false,
|
|
1511
|
-
role: "regular",
|
|
1512
|
-
default: { dbSpecial: "now" },
|
|
1513
|
-
},
|
|
1514
|
-
],
|
|
1515
|
-
},
|
|
1516
|
-
config,
|
|
1517
|
-
() => {
|
|
1518
|
-
throw new Error("No custom operations");
|
|
1519
|
-
},
|
|
1520
|
-
);
|
|
1521
|
-
|
|
1522
|
-
assertSingleResult(createOrders);
|
|
1523
|
-
expect(createOrders.compile().sql).toMatchInlineSnapshot(
|
|
1524
|
-
`"create table "orders" ("id" integer not null unique, "customerId" integer not null, "status" text default 'pending' not null, "total" decimal not null, "orderDate" timestamp default CURRENT_TIMESTAMP not null)"`,
|
|
1525
|
-
);
|
|
1526
|
-
|
|
1527
|
-
// 4. Create order_items table (junction table)
|
|
1528
|
-
const createOrderItems = execute(
|
|
1529
|
-
{
|
|
1530
|
-
type: "create-table",
|
|
1531
|
-
name: "order_items",
|
|
1532
|
-
columns: [
|
|
1533
|
-
{
|
|
1534
|
-
name: "id",
|
|
1535
|
-
type: "integer",
|
|
1536
|
-
isNullable: false,
|
|
1537
|
-
role: "external-id",
|
|
1538
|
-
default: { runtime: "cuid" },
|
|
1539
|
-
},
|
|
1540
|
-
{
|
|
1541
|
-
name: "orderId",
|
|
1542
|
-
type: "integer",
|
|
1543
|
-
isNullable: false,
|
|
1544
|
-
role: "reference",
|
|
1545
|
-
},
|
|
1546
|
-
{
|
|
1547
|
-
name: "productId",
|
|
1548
|
-
type: "integer",
|
|
1549
|
-
isNullable: false,
|
|
1550
|
-
role: "reference",
|
|
1551
|
-
},
|
|
1552
|
-
{
|
|
1553
|
-
name: "quantity",
|
|
1554
|
-
type: "integer",
|
|
1555
|
-
isNullable: false,
|
|
1556
|
-
role: "regular",
|
|
1557
|
-
},
|
|
1558
|
-
{
|
|
1559
|
-
name: "unitPrice",
|
|
1560
|
-
type: "decimal",
|
|
1561
|
-
isNullable: false,
|
|
1562
|
-
role: "regular",
|
|
1563
|
-
},
|
|
1564
|
-
],
|
|
1565
|
-
},
|
|
1566
|
-
config,
|
|
1567
|
-
() => {
|
|
1568
|
-
throw new Error("No custom operations");
|
|
1569
|
-
},
|
|
1570
|
-
);
|
|
1571
|
-
|
|
1572
|
-
assertSingleResult(createOrderItems);
|
|
1573
|
-
expect(createOrderItems.compile().sql).toMatchInlineSnapshot(
|
|
1574
|
-
`"create table "order_items" ("id" integer not null unique, "orderId" integer not null, "productId" integer not null, "quantity" integer not null, "unitPrice" decimal not null)"`,
|
|
1575
|
-
);
|
|
1576
|
-
|
|
1577
|
-
// 5. Add all foreign key constraints
|
|
1578
|
-
const addCustomerFk = execute(
|
|
1579
|
-
{
|
|
1580
|
-
type: "add-foreign-key",
|
|
1581
|
-
table: "orders",
|
|
1582
|
-
value: {
|
|
1583
|
-
name: "orders_customerId_fk",
|
|
1584
|
-
columns: ["customerId"],
|
|
1585
|
-
referencedTable: "customers",
|
|
1586
|
-
referencedColumns: ["id"],
|
|
1587
|
-
},
|
|
1588
|
-
},
|
|
1589
|
-
config,
|
|
1590
|
-
() => {
|
|
1591
|
-
throw new Error("No custom operations");
|
|
1592
|
-
},
|
|
1593
|
-
);
|
|
1594
|
-
|
|
1595
|
-
assertSingleResult(addCustomerFk);
|
|
1596
|
-
expect(addCustomerFk.compile().sql).toMatchInlineSnapshot(
|
|
1597
|
-
`"alter table "orders" add constraint "orders_customerId_fk" foreign key ("customerId") references "customers" ("id") on delete restrict on update restrict"`,
|
|
1598
|
-
);
|
|
1599
|
-
|
|
1600
|
-
const addOrderFk = execute(
|
|
1601
|
-
{
|
|
1602
|
-
type: "add-foreign-key",
|
|
1603
|
-
table: "order_items",
|
|
1604
|
-
value: {
|
|
1605
|
-
name: "order_items_orderId_fk",
|
|
1606
|
-
columns: ["orderId"],
|
|
1607
|
-
referencedTable: "orders",
|
|
1608
|
-
referencedColumns: ["id"],
|
|
1609
|
-
},
|
|
1610
|
-
},
|
|
1611
|
-
config,
|
|
1612
|
-
() => {
|
|
1613
|
-
throw new Error("No custom operations");
|
|
1614
|
-
},
|
|
1615
|
-
);
|
|
1616
|
-
|
|
1617
|
-
assertSingleResult(addOrderFk);
|
|
1618
|
-
expect(addOrderFk.compile().sql).toMatchInlineSnapshot(
|
|
1619
|
-
`"alter table "order_items" add constraint "order_items_orderId_fk" foreign key ("orderId") references "orders" ("id") on delete restrict on update restrict"`,
|
|
1620
|
-
);
|
|
1621
|
-
|
|
1622
|
-
const addProductFk = execute(
|
|
1623
|
-
{
|
|
1624
|
-
type: "add-foreign-key",
|
|
1625
|
-
table: "order_items",
|
|
1626
|
-
value: {
|
|
1627
|
-
name: "order_items_productId_fk",
|
|
1628
|
-
columns: ["productId"],
|
|
1629
|
-
referencedTable: "products",
|
|
1630
|
-
referencedColumns: ["id"],
|
|
1631
|
-
},
|
|
1632
|
-
},
|
|
1633
|
-
config,
|
|
1634
|
-
() => {
|
|
1635
|
-
throw new Error("No custom operations");
|
|
1636
|
-
},
|
|
1637
|
-
);
|
|
1638
|
-
|
|
1639
|
-
assertSingleResult(addProductFk);
|
|
1640
|
-
expect(addProductFk.compile().sql).toMatchInlineSnapshot(
|
|
1641
|
-
`"alter table "order_items" add constraint "order_items_productId_fk" foreign key ("productId") references "products" ("id") on delete restrict on update restrict"`,
|
|
1642
|
-
);
|
|
1643
|
-
|
|
1644
|
-
// 6. Create indexes for performance
|
|
1645
|
-
const createEmailIndex = execute(
|
|
1646
|
-
{
|
|
1647
|
-
type: "add-index",
|
|
1648
|
-
table: "customers",
|
|
1649
|
-
columns: ["email"],
|
|
1650
|
-
name: "idx_customers_email",
|
|
1651
|
-
unique: true,
|
|
1652
|
-
},
|
|
1653
|
-
config,
|
|
1654
|
-
() => {
|
|
1655
|
-
throw new Error("No custom operations");
|
|
1656
|
-
},
|
|
1657
|
-
);
|
|
1658
|
-
|
|
1659
|
-
assertSingleResult(createEmailIndex);
|
|
1660
|
-
expect(createEmailIndex.compile().sql).toMatchInlineSnapshot(
|
|
1661
|
-
`"create unique index "idx_customers_email" on "customers" ("email")"`,
|
|
1662
|
-
);
|
|
1663
|
-
|
|
1664
|
-
const createOrderStatusIndex = execute(
|
|
1665
|
-
{
|
|
1666
|
-
type: "add-index",
|
|
1667
|
-
table: "orders",
|
|
1668
|
-
columns: ["status", "orderDate"],
|
|
1669
|
-
name: "idx_orders_status_date",
|
|
1670
|
-
unique: false,
|
|
1671
|
-
},
|
|
1672
|
-
config,
|
|
1673
|
-
() => {
|
|
1674
|
-
throw new Error("No custom operations");
|
|
1675
|
-
},
|
|
1676
|
-
);
|
|
1677
|
-
|
|
1678
|
-
assertSingleResult(createOrderStatusIndex);
|
|
1679
|
-
expect(createOrderStatusIndex.compile().sql).toMatchInlineSnapshot(
|
|
1680
|
-
`"create index "idx_orders_status_date" on "orders" ("status", "orderDate")"`,
|
|
1681
|
-
);
|
|
1682
|
-
});
|
|
1683
|
-
|
|
1684
|
-
it("should handle schema evolution with complex column updates", () => {
|
|
1685
|
-
// 1. Create initial users table
|
|
1686
|
-
const createUsers = execute(
|
|
1687
|
-
{
|
|
1688
|
-
type: "create-table",
|
|
1689
|
-
name: "users",
|
|
1690
|
-
columns: [
|
|
1691
|
-
{
|
|
1692
|
-
name: "id",
|
|
1693
|
-
type: "integer",
|
|
1694
|
-
isNullable: false,
|
|
1695
|
-
role: "external-id",
|
|
1696
|
-
default: { runtime: "cuid" },
|
|
1697
|
-
},
|
|
1698
|
-
{
|
|
1699
|
-
name: "username",
|
|
1700
|
-
type: "string",
|
|
1701
|
-
isNullable: false,
|
|
1702
|
-
role: "regular",
|
|
1703
|
-
},
|
|
1704
|
-
{
|
|
1705
|
-
name: "email",
|
|
1706
|
-
type: "string",
|
|
1707
|
-
isNullable: false,
|
|
1708
|
-
role: "regular",
|
|
1709
|
-
},
|
|
1710
|
-
{
|
|
1711
|
-
name: "age",
|
|
1712
|
-
type: "integer",
|
|
1713
|
-
isNullable: true,
|
|
1714
|
-
role: "regular",
|
|
1715
|
-
},
|
|
1716
|
-
],
|
|
1717
|
-
},
|
|
1718
|
-
config,
|
|
1719
|
-
() => {
|
|
1720
|
-
throw new Error("No custom operations");
|
|
1721
|
-
},
|
|
1722
|
-
);
|
|
1723
|
-
|
|
1724
|
-
assertSingleResult(createUsers);
|
|
1725
|
-
expect(createUsers.compile().sql).toMatchInlineSnapshot(
|
|
1726
|
-
`"create table "users" ("id" integer not null unique, "username" text not null, "email" text not null, "age" integer)"`,
|
|
1727
|
-
);
|
|
1728
|
-
|
|
1729
|
-
// 2. Complex alter table with multiple operations
|
|
1730
|
-
const alterUsers = execute(
|
|
1731
|
-
{
|
|
1732
|
-
type: "alter-table",
|
|
1733
|
-
name: "users",
|
|
1734
|
-
value: [
|
|
1735
|
-
// Add new columns
|
|
1736
|
-
{
|
|
1737
|
-
type: "create-column",
|
|
1738
|
-
value: {
|
|
1739
|
-
name: "firstName",
|
|
1740
|
-
type: "string",
|
|
1741
|
-
isNullable: true,
|
|
1742
|
-
role: "regular",
|
|
1743
|
-
},
|
|
1744
|
-
},
|
|
1745
|
-
{
|
|
1746
|
-
type: "create-column",
|
|
1747
|
-
value: {
|
|
1748
|
-
name: "lastName",
|
|
1749
|
-
type: "string",
|
|
1750
|
-
isNullable: true,
|
|
1751
|
-
role: "regular",
|
|
1752
|
-
},
|
|
1753
|
-
},
|
|
1754
|
-
{
|
|
1755
|
-
type: "create-column",
|
|
1756
|
-
value: {
|
|
1757
|
-
name: "birthDate",
|
|
1758
|
-
type: "date",
|
|
1759
|
-
isNullable: true,
|
|
1760
|
-
role: "regular",
|
|
1761
|
-
},
|
|
1762
|
-
},
|
|
1763
|
-
{
|
|
1764
|
-
type: "create-column",
|
|
1765
|
-
value: {
|
|
1766
|
-
name: "isVerified",
|
|
1767
|
-
type: "bool",
|
|
1768
|
-
isNullable: false,
|
|
1769
|
-
role: "regular",
|
|
1770
|
-
default: { value: false },
|
|
1771
|
-
},
|
|
1772
|
-
},
|
|
1773
|
-
// Rename column
|
|
1774
|
-
{
|
|
1775
|
-
type: "rename-column",
|
|
1776
|
-
from: "username",
|
|
1777
|
-
to: "displayName",
|
|
1778
|
-
},
|
|
1779
|
-
// Update column (change age to be NOT NULL with default)
|
|
1780
|
-
{
|
|
1781
|
-
type: "update-column",
|
|
1782
|
-
name: "age",
|
|
1783
|
-
value: {
|
|
1784
|
-
name: "age",
|
|
1785
|
-
type: "integer",
|
|
1786
|
-
isNullable: false,
|
|
1787
|
-
role: "regular",
|
|
1788
|
-
default: { value: 0 },
|
|
1789
|
-
},
|
|
1790
|
-
updateDataType: false,
|
|
1791
|
-
updateNullable: true,
|
|
1792
|
-
updateDefault: true,
|
|
1793
|
-
},
|
|
1794
|
-
],
|
|
1795
|
-
},
|
|
1796
|
-
config,
|
|
1797
|
-
() => {
|
|
1798
|
-
throw new Error("No custom operations");
|
|
1799
|
-
},
|
|
1800
|
-
);
|
|
1801
|
-
|
|
1802
|
-
if (!Array.isArray(alterUsers)) {
|
|
1803
|
-
throw new Error("Expected array of results");
|
|
1804
|
-
}
|
|
1805
|
-
|
|
1806
|
-
expect(alterUsers).toHaveLength(7);
|
|
1807
|
-
expect(alterUsers[0].compile().sql).toMatchInlineSnapshot(
|
|
1808
|
-
`"alter table "users" add column "firstName" text"`,
|
|
1809
|
-
);
|
|
1810
|
-
expect(alterUsers[1].compile().sql).toMatchInlineSnapshot(
|
|
1811
|
-
`"alter table "users" add column "lastName" text"`,
|
|
1812
|
-
);
|
|
1813
|
-
expect(alterUsers[2].compile().sql).toMatchInlineSnapshot(
|
|
1814
|
-
`"alter table "users" add column "birthDate" date"`,
|
|
1815
|
-
);
|
|
1816
|
-
expect(alterUsers[3].compile().sql).toMatchInlineSnapshot(
|
|
1817
|
-
`"alter table "users" add column "isVerified" boolean default false not null"`,
|
|
1818
|
-
);
|
|
1819
|
-
expect(alterUsers[4].compile().sql).toMatchInlineSnapshot(
|
|
1820
|
-
`"alter table "users" rename column "username" to "displayName""`,
|
|
1821
|
-
);
|
|
1822
|
-
expect(alterUsers[5].compile().sql).toMatchInlineSnapshot(
|
|
1823
|
-
`"alter table "users" alter column "age" set not null"`,
|
|
1824
|
-
);
|
|
1825
|
-
expect(alterUsers[6].compile().sql).toMatchInlineSnapshot(
|
|
1826
|
-
`"alter table "users" alter column "age" set default 0"`,
|
|
1827
|
-
);
|
|
1828
|
-
|
|
1829
|
-
// 3. Create indexes after schema changes
|
|
1830
|
-
const createIndexes = execute(
|
|
1831
|
-
{
|
|
1832
|
-
type: "add-index",
|
|
1833
|
-
table: "users",
|
|
1834
|
-
columns: ["email"],
|
|
1835
|
-
name: "idx_users_email",
|
|
1836
|
-
unique: true,
|
|
1837
|
-
},
|
|
1838
|
-
config,
|
|
1839
|
-
() => {
|
|
1840
|
-
throw new Error("No custom operations");
|
|
1841
|
-
},
|
|
1842
|
-
);
|
|
1843
|
-
|
|
1844
|
-
assertSingleResult(createIndexes);
|
|
1845
|
-
expect(createIndexes.compile().sql).toMatchInlineSnapshot(
|
|
1846
|
-
`"create unique index "idx_users_email" on "users" ("email")"`,
|
|
1847
|
-
);
|
|
1848
|
-
|
|
1849
|
-
const createCompositeIndex = execute(
|
|
1850
|
-
{
|
|
1851
|
-
type: "add-index",
|
|
1852
|
-
table: "users",
|
|
1853
|
-
columns: ["firstName", "lastName"],
|
|
1854
|
-
name: "idx_users_name",
|
|
1855
|
-
unique: false,
|
|
1856
|
-
},
|
|
1857
|
-
config,
|
|
1858
|
-
() => {
|
|
1859
|
-
throw new Error("No custom operations");
|
|
1860
|
-
},
|
|
1861
|
-
);
|
|
1862
|
-
|
|
1863
|
-
assertSingleResult(createCompositeIndex);
|
|
1864
|
-
expect(createCompositeIndex.compile().sql).toMatchInlineSnapshot(
|
|
1865
|
-
`"create index "idx_users_name" on "users" ("firstName", "lastName")"`,
|
|
1866
|
-
);
|
|
1867
|
-
});
|
|
1868
|
-
|
|
1869
|
-
it("should handle content management system schema", () => {
|
|
1870
|
-
// 1. Create categories table
|
|
1871
|
-
const createCategories = execute(
|
|
1872
|
-
{
|
|
1873
|
-
type: "create-table",
|
|
1874
|
-
name: "categories",
|
|
1875
|
-
columns: [
|
|
1876
|
-
{
|
|
1877
|
-
name: "id",
|
|
1878
|
-
type: "integer",
|
|
1879
|
-
isNullable: false,
|
|
1880
|
-
role: "external-id",
|
|
1881
|
-
default: { runtime: "cuid" },
|
|
1882
|
-
},
|
|
1883
|
-
{
|
|
1884
|
-
name: "name",
|
|
1885
|
-
type: "string",
|
|
1886
|
-
isNullable: false,
|
|
1887
|
-
role: "regular",
|
|
1888
|
-
},
|
|
1889
|
-
{
|
|
1890
|
-
name: "slug",
|
|
1891
|
-
type: "string",
|
|
1892
|
-
isNullable: false,
|
|
1893
|
-
role: "regular",
|
|
1894
|
-
},
|
|
1895
|
-
{
|
|
1896
|
-
name: "description",
|
|
1897
|
-
type: "string",
|
|
1898
|
-
isNullable: true,
|
|
1899
|
-
role: "regular",
|
|
1900
|
-
},
|
|
1901
|
-
{
|
|
1902
|
-
name: "parentId",
|
|
1903
|
-
type: "integer",
|
|
1904
|
-
isNullable: true,
|
|
1905
|
-
role: "reference",
|
|
1906
|
-
},
|
|
1907
|
-
{
|
|
1908
|
-
name: "isActive",
|
|
1909
|
-
type: "bool",
|
|
1910
|
-
isNullable: false,
|
|
1911
|
-
role: "regular",
|
|
1912
|
-
default: { value: true },
|
|
1913
|
-
},
|
|
1914
|
-
{
|
|
1915
|
-
name: "createdAt",
|
|
1916
|
-
type: "timestamp",
|
|
1917
|
-
isNullable: false,
|
|
1918
|
-
role: "regular",
|
|
1919
|
-
default: { dbSpecial: "now" },
|
|
1920
|
-
},
|
|
1921
|
-
{
|
|
1922
|
-
name: "updatedAt",
|
|
1923
|
-
type: "timestamp",
|
|
1924
|
-
isNullable: false,
|
|
1925
|
-
role: "regular",
|
|
1926
|
-
default: { dbSpecial: "now" },
|
|
1927
|
-
},
|
|
1928
|
-
],
|
|
1929
|
-
},
|
|
1930
|
-
config,
|
|
1931
|
-
() => {
|
|
1932
|
-
throw new Error("No custom operations");
|
|
1933
|
-
},
|
|
1934
|
-
);
|
|
1935
|
-
|
|
1936
|
-
assertSingleResult(createCategories);
|
|
1937
|
-
expect(createCategories.compile().sql).toMatchInlineSnapshot(
|
|
1938
|
-
`"create table "categories" ("id" integer not null unique, "name" text not null, "slug" text not null, "description" text, "parentId" integer, "isActive" boolean default true not null, "createdAt" timestamp default CURRENT_TIMESTAMP not null, "updatedAt" timestamp default CURRENT_TIMESTAMP not null)"`,
|
|
1939
|
-
);
|
|
1940
|
-
|
|
1941
|
-
// 2. Create articles table
|
|
1942
|
-
const createArticles = execute(
|
|
1943
|
-
{
|
|
1944
|
-
type: "create-table",
|
|
1945
|
-
name: "articles",
|
|
1946
|
-
columns: [
|
|
1947
|
-
{
|
|
1948
|
-
name: "id",
|
|
1949
|
-
type: "integer",
|
|
1950
|
-
isNullable: false,
|
|
1951
|
-
role: "external-id",
|
|
1952
|
-
default: { runtime: "cuid" },
|
|
1953
|
-
},
|
|
1954
|
-
{
|
|
1955
|
-
name: "title",
|
|
1956
|
-
type: "string",
|
|
1957
|
-
isNullable: false,
|
|
1958
|
-
role: "regular",
|
|
1959
|
-
},
|
|
1960
|
-
{
|
|
1961
|
-
name: "slug",
|
|
1962
|
-
type: "string",
|
|
1963
|
-
isNullable: false,
|
|
1964
|
-
role: "regular",
|
|
1965
|
-
},
|
|
1966
|
-
{
|
|
1967
|
-
name: "excerpt",
|
|
1968
|
-
type: "string",
|
|
1969
|
-
isNullable: true,
|
|
1970
|
-
role: "regular",
|
|
1971
|
-
},
|
|
1972
|
-
{
|
|
1973
|
-
name: "content",
|
|
1974
|
-
type: "string",
|
|
1975
|
-
isNullable: false,
|
|
1976
|
-
role: "regular",
|
|
1977
|
-
},
|
|
1978
|
-
{
|
|
1979
|
-
name: "categoryId",
|
|
1980
|
-
type: "integer",
|
|
1981
|
-
isNullable: false,
|
|
1982
|
-
role: "reference",
|
|
1983
|
-
},
|
|
1984
|
-
{
|
|
1985
|
-
name: "authorId",
|
|
1986
|
-
type: "integer",
|
|
1987
|
-
isNullable: false,
|
|
1988
|
-
role: "reference",
|
|
1989
|
-
},
|
|
1990
|
-
{
|
|
1991
|
-
name: "status",
|
|
1992
|
-
type: "string",
|
|
1993
|
-
isNullable: false,
|
|
1994
|
-
role: "regular",
|
|
1995
|
-
default: { value: "draft" },
|
|
1996
|
-
},
|
|
1997
|
-
{
|
|
1998
|
-
name: "publishedAt",
|
|
1999
|
-
type: "timestamp",
|
|
2000
|
-
isNullable: true,
|
|
2001
|
-
role: "regular",
|
|
2002
|
-
},
|
|
2003
|
-
{
|
|
2004
|
-
name: "viewCount",
|
|
2005
|
-
type: "integer",
|
|
2006
|
-
isNullable: false,
|
|
2007
|
-
role: "regular",
|
|
2008
|
-
default: { value: 0 },
|
|
2009
|
-
},
|
|
2010
|
-
{
|
|
2011
|
-
name: "createdAt",
|
|
2012
|
-
type: "timestamp",
|
|
2013
|
-
isNullable: false,
|
|
2014
|
-
role: "regular",
|
|
2015
|
-
default: { dbSpecial: "now" },
|
|
2016
|
-
},
|
|
2017
|
-
{
|
|
2018
|
-
name: "updatedAt",
|
|
2019
|
-
type: "timestamp",
|
|
2020
|
-
isNullable: false,
|
|
2021
|
-
role: "regular",
|
|
2022
|
-
default: { dbSpecial: "now" },
|
|
2023
|
-
},
|
|
2024
|
-
],
|
|
2025
|
-
},
|
|
2026
|
-
config,
|
|
2027
|
-
() => {
|
|
2028
|
-
throw new Error("No custom operations");
|
|
2029
|
-
},
|
|
2030
|
-
);
|
|
2031
|
-
|
|
2032
|
-
assertSingleResult(createArticles);
|
|
2033
|
-
expect(createArticles.compile().sql).toMatchInlineSnapshot(
|
|
2034
|
-
`"create table "articles" ("id" integer not null unique, "title" text not null, "slug" text not null, "excerpt" text, "content" text not null, "categoryId" integer not null, "authorId" integer not null, "status" text default 'draft' not null, "publishedAt" timestamp, "viewCount" integer default 0 not null, "createdAt" timestamp default CURRENT_TIMESTAMP not null, "updatedAt" timestamp default CURRENT_TIMESTAMP not null)"`,
|
|
2035
|
-
);
|
|
2036
|
-
|
|
2037
|
-
// 3. Create tags table
|
|
2038
|
-
const createTags = execute(
|
|
2039
|
-
{
|
|
2040
|
-
type: "create-table",
|
|
2041
|
-
name: "tags",
|
|
2042
|
-
columns: [
|
|
2043
|
-
{
|
|
2044
|
-
name: "id",
|
|
2045
|
-
type: "integer",
|
|
2046
|
-
isNullable: false,
|
|
2047
|
-
role: "external-id",
|
|
2048
|
-
default: { runtime: "cuid" },
|
|
2049
|
-
},
|
|
2050
|
-
{
|
|
2051
|
-
name: "name",
|
|
2052
|
-
type: "string",
|
|
2053
|
-
isNullable: false,
|
|
2054
|
-
role: "regular",
|
|
2055
|
-
},
|
|
2056
|
-
{
|
|
2057
|
-
name: "slug",
|
|
2058
|
-
type: "string",
|
|
2059
|
-
isNullable: false,
|
|
2060
|
-
role: "regular",
|
|
2061
|
-
},
|
|
2062
|
-
{
|
|
2063
|
-
name: "color",
|
|
2064
|
-
type: "string",
|
|
2065
|
-
isNullable: true,
|
|
2066
|
-
role: "regular",
|
|
2067
|
-
default: { value: "#000000" },
|
|
2068
|
-
},
|
|
2069
|
-
],
|
|
2070
|
-
},
|
|
2071
|
-
config,
|
|
2072
|
-
() => {
|
|
2073
|
-
throw new Error("No custom operations");
|
|
2074
|
-
},
|
|
2075
|
-
);
|
|
2076
|
-
|
|
2077
|
-
assertSingleResult(createTags);
|
|
2078
|
-
expect(createTags.compile().sql).toMatchInlineSnapshot(
|
|
2079
|
-
`"create table "tags" ("id" integer not null unique, "name" text not null, "slug" text not null, "color" text default '#000000')"`,
|
|
2080
|
-
);
|
|
2081
|
-
|
|
2082
|
-
// 4. Create article_tags junction table
|
|
2083
|
-
const createArticleTags = execute(
|
|
2084
|
-
{
|
|
2085
|
-
type: "create-table",
|
|
2086
|
-
name: "article_tags",
|
|
2087
|
-
columns: [
|
|
2088
|
-
{
|
|
2089
|
-
name: "articleId",
|
|
2090
|
-
type: "integer",
|
|
2091
|
-
isNullable: false,
|
|
2092
|
-
role: "reference",
|
|
2093
|
-
},
|
|
2094
|
-
{
|
|
2095
|
-
name: "tagId",
|
|
2096
|
-
type: "integer",
|
|
2097
|
-
isNullable: false,
|
|
2098
|
-
role: "reference",
|
|
2099
|
-
},
|
|
2100
|
-
],
|
|
2101
|
-
},
|
|
2102
|
-
config,
|
|
2103
|
-
() => {
|
|
2104
|
-
throw new Error("No custom operations");
|
|
2105
|
-
},
|
|
2106
|
-
);
|
|
2107
|
-
|
|
2108
|
-
assertSingleResult(createArticleTags);
|
|
2109
|
-
expect(createArticleTags.compile().sql).toMatchInlineSnapshot(
|
|
2110
|
-
`"create table "article_tags" ("articleId" integer not null, "tagId" integer not null)"`,
|
|
2111
|
-
);
|
|
2112
|
-
|
|
2113
|
-
// 5. Add all foreign key constraints
|
|
2114
|
-
const addCategorySelfRef = execute(
|
|
2115
|
-
{
|
|
2116
|
-
type: "add-foreign-key",
|
|
2117
|
-
table: "categories",
|
|
2118
|
-
value: {
|
|
2119
|
-
name: "categories_parentId_fk",
|
|
2120
|
-
columns: ["parentId"],
|
|
2121
|
-
referencedTable: "categories",
|
|
2122
|
-
referencedColumns: ["id"],
|
|
2123
|
-
},
|
|
2124
|
-
},
|
|
2125
|
-
config,
|
|
2126
|
-
() => {
|
|
2127
|
-
throw new Error("No custom operations");
|
|
2128
|
-
},
|
|
2129
|
-
);
|
|
2130
|
-
|
|
2131
|
-
assertSingleResult(addCategorySelfRef);
|
|
2132
|
-
expect(addCategorySelfRef.compile().sql).toMatchInlineSnapshot(
|
|
2133
|
-
`"alter table "categories" add constraint "categories_parentId_fk" foreign key ("parentId") references "categories" ("id") on delete restrict on update restrict"`,
|
|
2134
|
-
);
|
|
2135
|
-
|
|
2136
|
-
const addArticleCategoryFk = execute(
|
|
2137
|
-
{
|
|
2138
|
-
type: "add-foreign-key",
|
|
2139
|
-
table: "articles",
|
|
2140
|
-
value: {
|
|
2141
|
-
name: "articles_categoryId_fk",
|
|
2142
|
-
columns: ["categoryId"],
|
|
2143
|
-
referencedTable: "categories",
|
|
2144
|
-
referencedColumns: ["id"],
|
|
2145
|
-
},
|
|
2146
|
-
},
|
|
2147
|
-
config,
|
|
2148
|
-
() => {
|
|
2149
|
-
throw new Error("No custom operations");
|
|
2150
|
-
},
|
|
2151
|
-
);
|
|
2152
|
-
|
|
2153
|
-
assertSingleResult(addArticleCategoryFk);
|
|
2154
|
-
expect(addArticleCategoryFk.compile().sql).toMatchInlineSnapshot(
|
|
2155
|
-
`"alter table "articles" add constraint "articles_categoryId_fk" foreign key ("categoryId") references "categories" ("id") on delete restrict on update restrict"`,
|
|
2156
|
-
);
|
|
2157
|
-
|
|
2158
|
-
const addArticleTagFks = execute(
|
|
2159
|
-
{
|
|
2160
|
-
type: "add-foreign-key",
|
|
2161
|
-
table: "article_tags",
|
|
2162
|
-
value: {
|
|
2163
|
-
name: "article_tags_articleId_fk",
|
|
2164
|
-
columns: ["articleId"],
|
|
2165
|
-
referencedTable: "articles",
|
|
2166
|
-
referencedColumns: ["id"],
|
|
2167
|
-
},
|
|
2168
|
-
},
|
|
2169
|
-
config,
|
|
2170
|
-
() => {
|
|
2171
|
-
throw new Error("No custom operations");
|
|
2172
|
-
},
|
|
2173
|
-
);
|
|
2174
|
-
|
|
2175
|
-
assertSingleResult(addArticleTagFks);
|
|
2176
|
-
expect(addArticleTagFks.compile().sql).toMatchInlineSnapshot(
|
|
2177
|
-
`"alter table "article_tags" add constraint "article_tags_articleId_fk" foreign key ("articleId") references "articles" ("id") on delete restrict on update restrict"`,
|
|
2178
|
-
);
|
|
2179
|
-
|
|
2180
|
-
const addTagFk = execute(
|
|
2181
|
-
{
|
|
2182
|
-
type: "add-foreign-key",
|
|
2183
|
-
table: "article_tags",
|
|
2184
|
-
value: {
|
|
2185
|
-
name: "article_tags_tagId_fk",
|
|
2186
|
-
columns: ["tagId"],
|
|
2187
|
-
referencedTable: "tags",
|
|
2188
|
-
referencedColumns: ["id"],
|
|
2189
|
-
},
|
|
2190
|
-
},
|
|
2191
|
-
config,
|
|
2192
|
-
() => {
|
|
2193
|
-
throw new Error("No custom operations");
|
|
2194
|
-
},
|
|
2195
|
-
);
|
|
2196
|
-
|
|
2197
|
-
assertSingleResult(addTagFk);
|
|
2198
|
-
expect(addTagFk.compile().sql).toMatchInlineSnapshot(
|
|
2199
|
-
`"alter table "article_tags" add constraint "article_tags_tagId_fk" foreign key ("tagId") references "tags" ("id") on delete restrict on update restrict"`,
|
|
2200
|
-
);
|
|
2201
|
-
|
|
2202
|
-
// 6. Create comprehensive indexes
|
|
2203
|
-
const createSlugIndexes = execute(
|
|
2204
|
-
{
|
|
2205
|
-
type: "add-index",
|
|
2206
|
-
table: "categories",
|
|
2207
|
-
columns: ["slug"],
|
|
2208
|
-
name: "idx_categories_slug",
|
|
2209
|
-
unique: true,
|
|
2210
|
-
},
|
|
2211
|
-
config,
|
|
2212
|
-
() => {
|
|
2213
|
-
throw new Error("No custom operations");
|
|
2214
|
-
},
|
|
2215
|
-
);
|
|
2216
|
-
|
|
2217
|
-
assertSingleResult(createSlugIndexes);
|
|
2218
|
-
expect(createSlugIndexes.compile().sql).toMatchInlineSnapshot(
|
|
2219
|
-
`"create unique index "idx_categories_slug" on "categories" ("slug")"`,
|
|
2220
|
-
);
|
|
2221
|
-
|
|
2222
|
-
const createArticleSlugIndex = execute(
|
|
2223
|
-
{
|
|
2224
|
-
type: "add-index",
|
|
2225
|
-
table: "articles",
|
|
2226
|
-
columns: ["slug"],
|
|
2227
|
-
name: "idx_articles_slug",
|
|
2228
|
-
unique: true,
|
|
2229
|
-
},
|
|
2230
|
-
config,
|
|
2231
|
-
() => {
|
|
2232
|
-
throw new Error("No custom operations");
|
|
2233
|
-
},
|
|
2234
|
-
);
|
|
2235
|
-
|
|
2236
|
-
assertSingleResult(createArticleSlugIndex);
|
|
2237
|
-
expect(createArticleSlugIndex.compile().sql).toMatchInlineSnapshot(
|
|
2238
|
-
`"create unique index "idx_articles_slug" on "articles" ("slug")"`,
|
|
2239
|
-
);
|
|
2240
|
-
|
|
2241
|
-
const createArticleStatusIndex = execute(
|
|
2242
|
-
{
|
|
2243
|
-
type: "add-index",
|
|
2244
|
-
table: "articles",
|
|
2245
|
-
columns: ["status", "publishedAt"],
|
|
2246
|
-
name: "idx_articles_status_published",
|
|
2247
|
-
unique: false,
|
|
2248
|
-
},
|
|
2249
|
-
config,
|
|
2250
|
-
() => {
|
|
2251
|
-
throw new Error("No custom operations");
|
|
2252
|
-
},
|
|
2253
|
-
);
|
|
2254
|
-
|
|
2255
|
-
assertSingleResult(createArticleStatusIndex);
|
|
2256
|
-
expect(createArticleStatusIndex.compile().sql).toMatchInlineSnapshot(
|
|
2257
|
-
`"create index "idx_articles_status_published" on "articles" ("status", "publishedAt")"`,
|
|
2258
|
-
);
|
|
2259
|
-
|
|
2260
|
-
const createTagSlugIndex = execute(
|
|
2261
|
-
{
|
|
2262
|
-
type: "add-index",
|
|
2263
|
-
table: "tags",
|
|
2264
|
-
columns: ["slug"],
|
|
2265
|
-
name: "idx_tags_slug",
|
|
2266
|
-
unique: true,
|
|
2267
|
-
},
|
|
2268
|
-
config,
|
|
2269
|
-
() => {
|
|
2270
|
-
throw new Error("No custom operations");
|
|
2271
|
-
},
|
|
2272
|
-
);
|
|
2273
|
-
|
|
2274
|
-
assertSingleResult(createTagSlugIndex);
|
|
2275
|
-
expect(createTagSlugIndex.compile().sql).toMatchInlineSnapshot(
|
|
2276
|
-
`"create unique index "idx_tags_slug" on "tags" ("slug")"`,
|
|
2277
|
-
);
|
|
2278
|
-
|
|
2279
|
-
const createArticleTagCompositeIndex = execute(
|
|
2280
|
-
{
|
|
2281
|
-
type: "add-index",
|
|
2282
|
-
table: "article_tags",
|
|
2283
|
-
columns: ["articleId", "tagId"],
|
|
2284
|
-
name: "idx_article_tags_composite",
|
|
2285
|
-
unique: true,
|
|
2286
|
-
},
|
|
2287
|
-
config,
|
|
2288
|
-
() => {
|
|
2289
|
-
throw new Error("No custom operations");
|
|
2290
|
-
},
|
|
2291
|
-
);
|
|
2292
|
-
|
|
2293
|
-
assertSingleResult(createArticleTagCompositeIndex);
|
|
2294
|
-
expect(createArticleTagCompositeIndex.compile().sql).toMatchInlineSnapshot(
|
|
2295
|
-
`"create unique index "idx_article_tags_composite" on "article_tags" ("articleId", "tagId")"`,
|
|
2296
|
-
);
|
|
2297
|
-
});
|
|
2298
|
-
});
|
|
2299
|
-
});
|
|
2300
|
-
|
|
2301
|
-
describe("execute() - CockroachDB", () => {
|
|
2302
|
-
let db: KyselyAny;
|
|
2303
|
-
let config: KyselyConfig;
|
|
2304
|
-
|
|
2305
|
-
beforeAll(async () => {
|
|
2306
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2307
|
-
db = new Kysely({ dialect: new PostgresDialect({} as any) });
|
|
2308
|
-
config = { db, provider: "cockroachdb" };
|
|
2309
|
-
});
|
|
2310
|
-
|
|
2311
|
-
describe("create-table", () => {
|
|
2312
|
-
it("should generate SQL for simple table with columns", () => {
|
|
2313
|
-
const operation: MigrationOperation = {
|
|
2314
|
-
type: "create-table",
|
|
2315
|
-
name: "users",
|
|
2316
|
-
columns: [
|
|
2317
|
-
{
|
|
2318
|
-
name: "id",
|
|
2319
|
-
type: "integer",
|
|
2320
|
-
isNullable: false,
|
|
2321
|
-
role: "external-id",
|
|
2322
|
-
},
|
|
2323
|
-
{
|
|
2324
|
-
name: "name",
|
|
2325
|
-
type: "string",
|
|
2326
|
-
isNullable: false,
|
|
2327
|
-
role: "regular",
|
|
2328
|
-
},
|
|
2329
|
-
{
|
|
2330
|
-
name: "email",
|
|
2331
|
-
type: "string",
|
|
2332
|
-
isNullable: false,
|
|
2333
|
-
role: "regular",
|
|
2334
|
-
},
|
|
2335
|
-
],
|
|
2336
|
-
};
|
|
2337
|
-
|
|
2338
|
-
const result = execute(operation, config, () => {
|
|
2339
|
-
throw new Error("No custom operations");
|
|
2340
|
-
});
|
|
2341
|
-
|
|
2342
|
-
assertSingleResult(result);
|
|
2343
|
-
|
|
2344
|
-
const compiled = result.compile();
|
|
2345
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
2346
|
-
`"create table "users" ("id" integer not null unique, "name" text not null, "email" text not null)"`,
|
|
2347
|
-
);
|
|
2348
|
-
});
|
|
2349
|
-
|
|
2350
|
-
it("should generate SQL for table with various column types", () => {
|
|
2351
|
-
const operation: MigrationOperation = {
|
|
2352
|
-
type: "create-table",
|
|
2353
|
-
name: "test_types",
|
|
2354
|
-
columns: [
|
|
2355
|
-
{ name: "col_int", type: "integer", isNullable: false, role: "external-id" },
|
|
2356
|
-
{ name: "col_bigint", type: "bigint", isNullable: false, role: "regular" },
|
|
2357
|
-
{ name: "col_decimal", type: "decimal", isNullable: false, role: "regular" },
|
|
2358
|
-
{ name: "col_bool", type: "bool", isNullable: false, role: "regular" },
|
|
2359
|
-
{ name: "col_date", type: "date", isNullable: false, role: "regular" },
|
|
2360
|
-
{ name: "col_timestamp", type: "timestamp", isNullable: false, role: "regular" },
|
|
2361
|
-
{ name: "col_json", type: "json", isNullable: false, role: "regular" },
|
|
2362
|
-
{ name: "col_binary", type: "binary", isNullable: false, role: "regular" },
|
|
2363
|
-
{ name: "col_varchar", type: "varchar(255)", isNullable: false, role: "regular" },
|
|
2364
|
-
],
|
|
2365
|
-
};
|
|
2366
|
-
|
|
2367
|
-
const result = execute(operation, config, () => {
|
|
2368
|
-
throw new Error("No custom operations");
|
|
2369
|
-
});
|
|
2370
|
-
|
|
2371
|
-
assertSingleResult(result);
|
|
2372
|
-
|
|
2373
|
-
const compiled = result.compile();
|
|
2374
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
2375
|
-
`"create table "test_types" ("col_int" integer not null unique, "col_bigint" bigint not null, "col_decimal" decimal not null, "col_bool" boolean not null, "col_date" date not null, "col_timestamp" timestamp not null, "col_json" json not null, "col_binary" bytea not null, "col_varchar" varchar(255) not null)"`,
|
|
2376
|
-
);
|
|
2377
|
-
});
|
|
2378
|
-
|
|
2379
|
-
it("should generate SQL for table with default values", () => {
|
|
2380
|
-
const operation: MigrationOperation = {
|
|
2381
|
-
type: "create-table",
|
|
2382
|
-
name: "defaults_test",
|
|
2383
|
-
columns: [
|
|
2384
|
-
{ name: "id", type: "integer", isNullable: false, role: "external-id" },
|
|
2385
|
-
{
|
|
2386
|
-
name: "status",
|
|
2387
|
-
type: "string",
|
|
2388
|
-
isNullable: false,
|
|
2389
|
-
role: "regular",
|
|
2390
|
-
default: { value: "pending" },
|
|
2391
|
-
},
|
|
2392
|
-
{
|
|
2393
|
-
name: "count",
|
|
2394
|
-
type: "integer",
|
|
2395
|
-
isNullable: false,
|
|
2396
|
-
role: "regular",
|
|
2397
|
-
default: { value: 0 },
|
|
2398
|
-
},
|
|
2399
|
-
{
|
|
2400
|
-
name: "is_active",
|
|
2401
|
-
type: "bool",
|
|
2402
|
-
isNullable: false,
|
|
2403
|
-
role: "regular",
|
|
2404
|
-
default: { value: true },
|
|
2405
|
-
},
|
|
2406
|
-
],
|
|
2407
|
-
};
|
|
2408
|
-
|
|
2409
|
-
const result = execute(operation, config, () => {
|
|
2410
|
-
throw new Error("No custom operations");
|
|
2411
|
-
});
|
|
2412
|
-
|
|
2413
|
-
assertSingleResult(result);
|
|
2414
|
-
|
|
2415
|
-
const compiled = result.compile();
|
|
2416
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
2417
|
-
`"create table "defaults_test" ("id" integer not null unique, "status" text default 'pending' not null, "count" integer default 0 not null, "is_active" boolean default true not null)"`,
|
|
2418
|
-
);
|
|
2419
|
-
});
|
|
2420
|
-
});
|
|
2421
|
-
|
|
2422
|
-
describe("alter-table - update-column", () => {
|
|
2423
|
-
it("should generate SQL to update column data type (CockroachDB uses USING clause like PostgreSQL)", () => {
|
|
2424
|
-
const operation: MigrationOperation = {
|
|
2425
|
-
type: "alter-table",
|
|
2426
|
-
name: "test_table",
|
|
2427
|
-
value: [
|
|
2428
|
-
{
|
|
2429
|
-
type: "update-column",
|
|
2430
|
-
name: "test_col",
|
|
2431
|
-
value: {
|
|
2432
|
-
name: "test_col",
|
|
2433
|
-
type: "integer",
|
|
2434
|
-
isNullable: true,
|
|
2435
|
-
role: "regular",
|
|
2436
|
-
},
|
|
2437
|
-
updateDataType: true,
|
|
2438
|
-
updateNullable: false,
|
|
2439
|
-
updateDefault: false,
|
|
2440
|
-
},
|
|
2441
|
-
],
|
|
2442
|
-
};
|
|
2443
|
-
|
|
2444
|
-
const results = execute(operation, config, () => {
|
|
2445
|
-
throw new Error("No custom operations");
|
|
2446
|
-
});
|
|
2447
|
-
|
|
2448
|
-
if (!Array.isArray(results)) {
|
|
2449
|
-
throw new Error("Expected array of results");
|
|
2450
|
-
}
|
|
2451
|
-
|
|
2452
|
-
expect(results).toHaveLength(1);
|
|
2453
|
-
const compiled = results[0].compile();
|
|
2454
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
2455
|
-
`"ALTER TABLE "test_table" ALTER COLUMN "test_col" TYPE integer USING ("test_col"::integer)"`,
|
|
2456
|
-
);
|
|
2457
|
-
});
|
|
2458
|
-
});
|
|
2459
|
-
|
|
2460
|
-
describe("drop-index", () => {
|
|
2461
|
-
it("should generate SQL to drop index with CASCADE (CockroachDB specific)", () => {
|
|
2462
|
-
const operation: MigrationOperation = {
|
|
2463
|
-
type: "drop-index",
|
|
2464
|
-
table: "test_table",
|
|
2465
|
-
name: "idx_email",
|
|
2466
|
-
};
|
|
2467
|
-
|
|
2468
|
-
const result = execute(operation, config, () => {
|
|
2469
|
-
throw new Error("No custom operations");
|
|
2470
|
-
});
|
|
2471
|
-
|
|
2472
|
-
assertSingleResult(result);
|
|
2473
|
-
|
|
2474
|
-
const compiled = result.compile();
|
|
2475
|
-
expect(compiled.sql).toMatchInlineSnapshot(`"drop index if exists "idx_email" cascade"`);
|
|
2476
|
-
});
|
|
2477
|
-
|
|
2478
|
-
it("should generate SQL to drop unique index with CASCADE", () => {
|
|
2479
|
-
const operation: MigrationOperation = {
|
|
2480
|
-
type: "drop-index",
|
|
2481
|
-
table: "test_table",
|
|
2482
|
-
name: "idx_unique_email",
|
|
2483
|
-
};
|
|
2484
|
-
|
|
2485
|
-
const result = execute(operation, config, () => {
|
|
2486
|
-
throw new Error("No custom operations");
|
|
2487
|
-
});
|
|
2488
|
-
|
|
2489
|
-
assertSingleResult(result);
|
|
2490
|
-
|
|
2491
|
-
const compiled = result.compile();
|
|
2492
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
2493
|
-
`"drop index if exists "idx_unique_email" cascade"`,
|
|
2494
|
-
);
|
|
2495
|
-
});
|
|
2496
|
-
});
|
|
2497
|
-
|
|
2498
|
-
describe("add-foreign-key", () => {
|
|
2499
|
-
it("should generate SQL for foreign key constraint", () => {
|
|
2500
|
-
const operation: MigrationOperation = {
|
|
2501
|
-
type: "add-foreign-key",
|
|
2502
|
-
table: "posts",
|
|
2503
|
-
value: {
|
|
2504
|
-
name: "posts_user_id_fk",
|
|
2505
|
-
columns: ["user_id"],
|
|
2506
|
-
referencedTable: "users",
|
|
2507
|
-
referencedColumns: ["id"],
|
|
2508
|
-
},
|
|
2509
|
-
};
|
|
2510
|
-
|
|
2511
|
-
const result = execute(operation, config, () => {
|
|
2512
|
-
throw new Error("No custom operations");
|
|
2513
|
-
});
|
|
2514
|
-
|
|
2515
|
-
assertSingleResult(result);
|
|
2516
|
-
|
|
2517
|
-
const compiled = result.compile();
|
|
2518
|
-
expect(compiled.sql).toMatchInlineSnapshot(
|
|
2519
|
-
`"alter table "posts" add constraint "posts_user_id_fk" foreign key ("user_id") references "users" ("id") on delete restrict on update restrict"`,
|
|
2520
|
-
);
|
|
2521
|
-
});
|
|
2522
|
-
});
|
|
2523
|
-
|
|
2524
|
-
describe("rename-table", () => {
|
|
2525
|
-
it("should generate SQL for CockroachDB rename (same as PostgreSQL)", () => {
|
|
2526
|
-
const operation: MigrationOperation = {
|
|
2527
|
-
type: "rename-table",
|
|
2528
|
-
from: "old_name",
|
|
2529
|
-
to: "new_name",
|
|
2530
|
-
};
|
|
2531
|
-
|
|
2532
|
-
const result = execute(operation, config, () => {
|
|
2533
|
-
throw new Error("No custom operations");
|
|
2534
|
-
});
|
|
2535
|
-
|
|
2536
|
-
assertSingleResult(result);
|
|
2537
|
-
|
|
2538
|
-
const compiled = result.compile();
|
|
2539
|
-
expect(compiled.sql).toMatchInlineSnapshot(`"alter table "old_name" rename to "new_name""`);
|
|
2540
|
-
});
|
|
2541
|
-
});
|
|
2542
|
-
|
|
2543
|
-
describe("complex migration scenarios", () => {
|
|
2544
|
-
it("should generate correct SQL for full schema migration", () => {
|
|
2545
|
-
// 1. Create users table
|
|
2546
|
-
const createUsers = execute(
|
|
2547
|
-
{
|
|
2548
|
-
type: "create-table",
|
|
2549
|
-
name: "users",
|
|
2550
|
-
columns: [
|
|
2551
|
-
{ name: "id", type: "integer", isNullable: false, role: "external-id" },
|
|
2552
|
-
{ name: "email", type: "string", isNullable: false, role: "regular" },
|
|
2553
|
-
{ name: "name", type: "string", isNullable: false, role: "regular" },
|
|
2554
|
-
],
|
|
2555
|
-
},
|
|
2556
|
-
config,
|
|
2557
|
-
() => {
|
|
2558
|
-
throw new Error("No custom operations");
|
|
2559
|
-
},
|
|
2560
|
-
);
|
|
2561
|
-
|
|
2562
|
-
assertSingleResult(createUsers);
|
|
2563
|
-
|
|
2564
|
-
expect(createUsers.compile().sql).toMatchInlineSnapshot(
|
|
2565
|
-
`"create table "users" ("id" integer not null unique, "email" text not null, "name" text not null)"`,
|
|
2566
|
-
);
|
|
2567
|
-
|
|
2568
|
-
// 2. Add unique index on email
|
|
2569
|
-
const addIndex = execute(
|
|
2570
|
-
{
|
|
2571
|
-
type: "add-index",
|
|
2572
|
-
table: "users",
|
|
2573
|
-
columns: ["email"],
|
|
2574
|
-
name: "idx_unique_email",
|
|
2575
|
-
unique: true,
|
|
2576
|
-
},
|
|
2577
|
-
config,
|
|
2578
|
-
() => {
|
|
2579
|
-
throw new Error("No custom operations");
|
|
2580
|
-
},
|
|
2581
|
-
);
|
|
2582
|
-
|
|
2583
|
-
assertSingleResult(addIndex);
|
|
2584
|
-
|
|
2585
|
-
expect(addIndex.compile().sql).toMatchInlineSnapshot(
|
|
2586
|
-
`"create unique index "idx_unique_email" on "users" ("email")"`,
|
|
2587
|
-
);
|
|
2588
|
-
|
|
2589
|
-
// 3. Create posts table
|
|
2590
|
-
const createPosts = execute(
|
|
2591
|
-
{
|
|
2592
|
-
type: "create-table",
|
|
2593
|
-
name: "posts",
|
|
2594
|
-
columns: [
|
|
2595
|
-
{ name: "id", type: "integer", isNullable: false, role: "external-id" },
|
|
2596
|
-
{ name: "user_id", type: "integer", isNullable: false, role: "reference" },
|
|
2597
|
-
{ name: "title", type: "string", isNullable: false, role: "regular" },
|
|
2598
|
-
{ name: "content", type: "string", isNullable: false, role: "regular" },
|
|
2599
|
-
],
|
|
2600
|
-
},
|
|
2601
|
-
config,
|
|
2602
|
-
() => {
|
|
2603
|
-
throw new Error("No custom operations");
|
|
2604
|
-
},
|
|
2605
|
-
);
|
|
2606
|
-
|
|
2607
|
-
assertSingleResult(createPosts);
|
|
2608
|
-
|
|
2609
|
-
expect(createPosts.compile().sql).toMatchInlineSnapshot(
|
|
2610
|
-
`"create table "posts" ("id" integer not null unique, "user_id" integer not null, "title" text not null, "content" text not null)"`,
|
|
2611
|
-
);
|
|
2612
|
-
|
|
2613
|
-
// 4. Add foreign key
|
|
2614
|
-
const addFk = execute(
|
|
2615
|
-
{
|
|
2616
|
-
type: "add-foreign-key",
|
|
2617
|
-
table: "posts",
|
|
2618
|
-
value: {
|
|
2619
|
-
name: "posts_user_id_fk",
|
|
2620
|
-
columns: ["user_id"],
|
|
2621
|
-
referencedTable: "users",
|
|
2622
|
-
referencedColumns: ["id"],
|
|
2623
|
-
},
|
|
2624
|
-
},
|
|
2625
|
-
config,
|
|
2626
|
-
() => {
|
|
2627
|
-
throw new Error("No custom operations");
|
|
2628
|
-
},
|
|
2629
|
-
);
|
|
2630
|
-
|
|
2631
|
-
assertSingleResult(addFk);
|
|
2632
|
-
|
|
2633
|
-
expect(addFk.compile().sql).toMatchInlineSnapshot(
|
|
2634
|
-
`"alter table "posts" add constraint "posts_user_id_fk" foreign key ("user_id") references "users" ("id") on delete restrict on update restrict"`,
|
|
2635
|
-
);
|
|
2636
|
-
|
|
2637
|
-
// 5. Drop index with CASCADE (CockroachDB specific)
|
|
2638
|
-
const dropIndex = execute(
|
|
2639
|
-
{
|
|
2640
|
-
type: "drop-index",
|
|
2641
|
-
table: "users",
|
|
2642
|
-
name: "idx_unique_email",
|
|
2643
|
-
},
|
|
2644
|
-
config,
|
|
2645
|
-
() => {
|
|
2646
|
-
throw new Error("No custom operations");
|
|
2647
|
-
},
|
|
2648
|
-
);
|
|
2649
|
-
|
|
2650
|
-
assertSingleResult(dropIndex);
|
|
2651
|
-
|
|
2652
|
-
expect(dropIndex.compile().sql).toMatchInlineSnapshot(
|
|
2653
|
-
`"drop index if exists "idx_unique_email" cascade"`,
|
|
2654
|
-
);
|
|
2655
|
-
});
|
|
2656
|
-
});
|
|
2657
|
-
});
|