@prisma-next/target-postgres 0.12.0-dev.7 → 0.12.0-dev.71
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/dist/{codec-ids-DliyCWPY.d.mts → codec-ids-B1vOchLE.d.mts} +3 -2
- package/dist/codec-ids-B1vOchLE.d.mts.map +1 -0
- package/dist/{codec-ids-C5qzBqus.mjs → codec-ids-CTikp1if.mjs} +3 -2
- package/dist/codec-ids-CTikp1if.mjs.map +1 -0
- package/dist/codec-ids.d.mts +2 -2
- package/dist/codec-ids.mjs +2 -2
- package/dist/{codec-types-BF1DXTPs.d.mts → codec-types-CnFiNML4.d.mts} +8 -9
- package/dist/codec-types-CnFiNML4.d.mts.map +1 -0
- package/dist/codec-types.d.mts +2 -2
- package/dist/{codecs-DuP3d9Au.d.mts → codecs-CBpEv4s5.d.mts} +33 -35
- package/dist/codecs-CBpEv4s5.d.mts.map +1 -0
- package/dist/codecs.d.mts +1 -1
- package/dist/codecs.mjs +37 -2
- package/dist/codecs.mjs.map +1 -1
- package/dist/contract-free.d.mts +80 -0
- package/dist/contract-free.d.mts.map +1 -0
- package/dist/contract-free.mjs +117 -0
- package/dist/contract-free.mjs.map +1 -0
- package/dist/control.d.mts +1 -1
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +66 -40
- package/dist/control.mjs.map +1 -1
- package/dist/{data-transform-CRkv2T_U.mjs → data-transform-D25tLeYU.mjs} +1 -1
- package/dist/{data-transform-CRkv2T_U.mjs.map → data-transform-D25tLeYU.mjs.map} +1 -1
- package/dist/{data-transform-CAPmAdxS.d.mts → data-transform-DGOqcLrf.d.mts} +2 -2
- package/dist/{data-transform-CAPmAdxS.d.mts.map → data-transform-DGOqcLrf.d.mts.map} +1 -1
- package/dist/data-transform.d.mts +1 -1
- package/dist/data-transform.mjs +1 -1
- package/dist/ddl-77SyXgFt.mjs +30 -0
- package/dist/ddl-77SyXgFt.mjs.map +1 -0
- package/dist/ddl.d.mts +2 -0
- package/dist/ddl.mjs +2 -0
- package/dist/{default-normalizer-DaAhmzBV.mjs → default-normalizer-DyyCHQWs.mjs} +1 -1
- package/dist/{default-normalizer-DaAhmzBV.mjs.map → default-normalizer-DyyCHQWs.mjs.map} +1 -1
- package/dist/default-normalizer.mjs +1 -1
- package/dist/{descriptor-meta-Uu8QaClr.mjs → descriptor-meta-DKmj-IMN.mjs} +3 -2
- package/dist/descriptor-meta-DKmj-IMN.mjs.map +1 -0
- package/dist/{descriptor-meta-runtime-DMRX39kp.mjs → descriptor-meta-runtime-My8_s4cs.mjs} +2 -2
- package/dist/{descriptor-meta-runtime-DMRX39kp.mjs.map → descriptor-meta-runtime-My8_s4cs.mjs.map} +1 -1
- package/dist/{enum-planning-DRA9LaMU.mjs → enum-planning-BCyvlFHk.mjs} +0 -0
- package/dist/{enum-planning-DRA9LaMU.mjs.map → enum-planning-BCyvlFHk.mjs.map} +1 -1
- package/dist/enum-planning.d.mts +1 -1
- package/dist/enum-planning.mjs +1 -1
- package/dist/{errors-BbnITmAD.mjs → errors-CUk87ByX.mjs} +1 -1
- package/dist/{errors-BbnITmAD.mjs.map → errors-CUk87ByX.mjs.map} +1 -1
- package/dist/errors.d.mts.map +1 -1
- package/dist/errors.mjs +1 -1
- package/dist/{issue-planner-BtaL6OfW.mjs → issue-planner-SHnDHfoQ.mjs} +130 -28
- package/dist/issue-planner-SHnDHfoQ.mjs.map +1 -0
- package/dist/issue-planner.d.mts +1 -1
- package/dist/issue-planner.d.mts.map +1 -1
- package/dist/issue-planner.mjs +1 -1
- package/dist/migration.d.mts +7 -8
- package/dist/migration.d.mts.map +1 -1
- package/dist/migration.mjs +5 -4
- package/dist/migration.mjs.map +1 -1
- package/dist/{native-type-normalizer-BNEQ9VDs.mjs → native-type-normalizer-Bc9XJzWC.mjs} +1 -1
- package/dist/{native-type-normalizer-BNEQ9VDs.mjs.map → native-type-normalizer-Bc9XJzWC.mjs.map} +1 -1
- package/dist/native-type-normalizer.mjs +1 -1
- package/dist/nodes-779hmCfL.d.mts +40 -0
- package/dist/nodes-779hmCfL.d.mts.map +1 -0
- package/dist/nodes-DZk2JZG3.mjs +47 -0
- package/dist/nodes-DZk2JZG3.mjs.map +1 -0
- package/dist/op-factory-call-D2aAUhmS.mjs +1307 -0
- package/dist/op-factory-call-D2aAUhmS.mjs.map +1 -0
- package/dist/{op-factory-call-CDlImOF_.d.mts → op-factory-call-DMA86_2D.d.mts} +39 -14
- package/dist/op-factory-call-DMA86_2D.d.mts.map +1 -0
- package/dist/op-factory-call.d.mts +2 -2
- package/dist/op-factory-call.mjs +2 -2
- package/dist/pack.d.mts +5 -6
- package/dist/pack.d.mts.map +1 -1
- package/dist/pack.mjs +1 -1
- package/dist/planner-Bv5LV2A-.mjs +344 -0
- package/dist/planner-Bv5LV2A-.mjs.map +1 -0
- package/dist/{planner-ddl-builders-BNMfSE9r.mjs → planner-ddl-builders-DDyptTt5.mjs} +4 -28
- package/dist/planner-ddl-builders-DDyptTt5.mjs.map +1 -0
- package/dist/planner-ddl-builders.d.mts +6 -7
- package/dist/planner-ddl-builders.d.mts.map +1 -1
- package/dist/planner-ddl-builders.mjs +2 -2
- package/dist/{planner-identity-values-nhVj0hp-.mjs → planner-identity-values-BIpa5p2I.mjs} +1 -1
- package/dist/{planner-identity-values-nhVj0hp-.mjs.map → planner-identity-values-BIpa5p2I.mjs.map} +1 -1
- package/dist/planner-identity-values.mjs +1 -1
- package/dist/{planner-produced-postgres-migration-D02NOhVQ.d.mts → planner-produced-postgres-migration-B4EDvLdz.d.mts} +5 -4
- package/dist/planner-produced-postgres-migration-B4EDvLdz.d.mts.map +1 -0
- package/dist/{planner-produced-postgres-migration-D_nsXbhl.mjs → planner-produced-postgres-migration-NSEhWL0L.mjs} +8 -6
- package/dist/planner-produced-postgres-migration-NSEhWL0L.mjs.map +1 -0
- package/dist/planner-produced-postgres-migration.d.mts +1 -1
- package/dist/planner-produced-postgres-migration.mjs +1 -1
- package/dist/{planner-schema-lookup-CGxxYfnD.mjs → planner-schema-lookup-CiVaAQP-.mjs} +1 -1
- package/dist/{planner-schema-lookup-CGxxYfnD.mjs.map → planner-schema-lookup-CiVaAQP-.mjs.map} +1 -1
- package/dist/planner-schema-lookup.mjs +1 -1
- package/dist/{planner-sql-checks-CfEiTXoQ.mjs → planner-sql-checks-DAdhnI2c.mjs} +41 -30
- package/dist/planner-sql-checks-DAdhnI2c.mjs.map +1 -0
- package/dist/planner-sql-checks.d.mts.map +1 -1
- package/dist/planner-sql-checks.mjs +1 -1
- package/dist/{planner-target-details-a_wuOiYf.d.mts → planner-target-details-CIY6tLeo.d.mts} +2 -2
- package/dist/planner-target-details-CIY6tLeo.d.mts.map +1 -0
- package/dist/planner-target-details.d.mts +2 -2
- package/dist/planner-type-resolution-836DExFN.mjs +20 -0
- package/dist/planner-type-resolution-836DExFN.mjs.map +1 -0
- package/dist/planner.d.mts +7 -3
- package/dist/planner.d.mts.map +1 -1
- package/dist/planner.mjs +1 -1
- package/dist/{postgres-contract-serializer-BnOboPWs.mjs → postgres-contract-serializer-DYTyXjPf.mjs} +33 -24
- package/dist/postgres-contract-serializer-DYTyXjPf.mjs.map +1 -0
- package/dist/{postgres-enum-type-CSzsvXrO.d.mts → postgres-enum-type-BVn63a89.d.mts} +1 -1
- package/dist/{postgres-enum-type-CSzsvXrO.d.mts.map → postgres-enum-type-BVn63a89.d.mts.map} +1 -1
- package/dist/{postgres-enum-type-BMgyxNyy.mjs → postgres-enum-type-DPKqCBem.mjs} +1 -1
- package/dist/{postgres-enum-type-BMgyxNyy.mjs.map → postgres-enum-type-DPKqCBem.mjs.map} +1 -1
- package/dist/{postgres-migration-BatbEvU6.mjs → postgres-migration-COore9Mz.mjs} +23 -3
- package/dist/postgres-migration-COore9Mz.mjs.map +1 -0
- package/dist/{postgres-migration-DRY8V-bQ.d.mts → postgres-migration-DZ_gLUOW.d.mts} +25 -3
- package/dist/postgres-migration-DZ_gLUOW.d.mts.map +1 -0
- package/dist/{postgres-schema-BxAuNFX0.mjs → postgres-schema-BuxCxbvB.mjs} +29 -14
- package/dist/postgres-schema-BuxCxbvB.mjs.map +1 -0
- package/dist/{render-ops-XhICjX_P.mjs → render-ops-BpjstrKQ.mjs} +4 -3
- package/dist/{render-ops-XhICjX_P.mjs.map → render-ops-BpjstrKQ.mjs.map} +1 -1
- package/dist/render-ops.d.mts +3 -2
- package/dist/render-ops.d.mts.map +1 -1
- package/dist/render-ops.mjs +1 -1
- package/dist/{render-typescript-K125n-RZ.mjs → render-typescript-KMgosran.mjs} +5 -2
- package/dist/render-typescript-KMgosran.mjs.map +1 -0
- package/dist/render-typescript.mjs +1 -1
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +2 -2
- package/dist/{shared-Do_a5ymU.d.mts → shared-DarONYBZ.d.mts} +5 -5
- package/dist/{shared-Do_a5ymU.d.mts.map → shared-DarONYBZ.d.mts.map} +1 -1
- package/dist/{sql-utils-CggjWNij.mjs → sql-utils-DcfMz4MQ.mjs} +1 -1
- package/dist/{sql-utils-CggjWNij.mjs.map → sql-utils-DcfMz4MQ.mjs.map} +1 -1
- package/dist/sql-utils.mjs +1 -1
- package/dist/{types-O40IcFV9.d.mts → types-BDKkx8MA.d.mts} +1 -1
- package/dist/types-BDKkx8MA.d.mts.map +1 -0
- package/dist/types.d.mts +16 -11
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs +2 -2
- package/package.json +21 -20
- package/src/contract-free/columns.ts +49 -0
- package/src/contract-free/control-bootstrap.ts +55 -0
- package/src/contract-free/ddl.ts +37 -0
- package/src/core/ast/table-source.ts +23 -0
- package/src/core/codec-ids.ts +1 -0
- package/src/core/codecs.ts +44 -0
- package/src/core/ddl/nodes.ts +72 -0
- package/src/core/descriptor-meta.ts +1 -0
- package/src/core/migrations/control-policy.ts +234 -0
- package/src/core/migrations/issue-planner.ts +81 -13
- package/src/core/migrations/op-factory-call.ts +289 -46
- package/src/core/migrations/operations/constraints.ts +79 -10
- package/src/core/migrations/operations/dependencies.ts +0 -17
- package/src/core/migrations/operations/shared.ts +3 -3
- package/src/core/migrations/operations/tables.ts +1 -39
- package/src/core/migrations/planner-ddl-builders.ts +4 -46
- package/src/core/migrations/planner-produced-postgres-migration.ts +11 -6
- package/src/core/migrations/planner-sql-checks.ts +9 -9
- package/src/core/migrations/planner-strategies.ts +149 -11
- package/src/core/migrations/planner-target-details.ts +2 -1
- package/src/core/migrations/planner.ts +66 -8
- package/src/core/migrations/postgres-migration.ts +41 -0
- package/src/core/migrations/render-ops.ts +7 -2
- package/src/core/migrations/render-typescript.ts +5 -1
- package/src/core/migrations/runner.ts +78 -50
- package/src/core/postgres-contract-serializer.ts +52 -46
- package/src/core/postgres-schema.ts +43 -25
- package/src/exports/contract-free.ts +7 -0
- package/src/exports/control.ts +6 -8
- package/src/exports/ddl.ts +7 -0
- package/src/exports/migration.ts +11 -2
- package/src/exports/op-factory-call.ts +2 -0
- package/src/exports/planner-ddl-builders.ts +0 -1
- package/dist/codec-ids-C5qzBqus.mjs.map +0 -1
- package/dist/codec-ids-DliyCWPY.d.mts.map +0 -1
- package/dist/codec-types-BF1DXTPs.d.mts.map +0 -1
- package/dist/codecs-DuP3d9Au.d.mts.map +0 -1
- package/dist/descriptor-meta-Uu8QaClr.mjs.map +0 -1
- package/dist/issue-planner-BtaL6OfW.mjs.map +0 -1
- package/dist/op-factory-call-CDlImOF_.d.mts.map +0 -1
- package/dist/op-factory-call-ewOd5q6L.mjs +0 -625
- package/dist/op-factory-call-ewOd5q6L.mjs.map +0 -1
- package/dist/planner-Bjz5pnLa.mjs +0 -177
- package/dist/planner-Bjz5pnLa.mjs.map +0 -1
- package/dist/planner-ddl-builders-BNMfSE9r.mjs.map +0 -1
- package/dist/planner-produced-postgres-migration-D02NOhVQ.d.mts.map +0 -1
- package/dist/planner-produced-postgres-migration-D_nsXbhl.mjs.map +0 -1
- package/dist/planner-sql-checks-CfEiTXoQ.mjs.map +0 -1
- package/dist/planner-target-details-a_wuOiYf.d.mts.map +0 -1
- package/dist/postgres-contract-serializer-BnOboPWs.mjs.map +0 -1
- package/dist/postgres-migration-BatbEvU6.mjs.map +0 -1
- package/dist/postgres-migration-DRY8V-bQ.d.mts.map +0 -1
- package/dist/postgres-schema-BxAuNFX0.mjs.map +0 -1
- package/dist/render-typescript-K125n-RZ.mjs.map +0 -1
- package/dist/statement-builders-DVI5IVAa.mjs +0 -131
- package/dist/statement-builders-DVI5IVAa.mjs.map +0 -1
- package/dist/statement-builders.d.mts +0 -51
- package/dist/statement-builders.d.mts.map +0 -1
- package/dist/statement-builders.mjs +0 -2
- package/dist/tables-DoA39Yqo.mjs +0 -516
- package/dist/tables-DoA39Yqo.mjs.map +0 -1
- package/dist/types-O40IcFV9.d.mts.map +0 -1
- package/src/core/migrations/statement-builders.ts +0 -183
- package/src/exports/statement-builders.ts +0 -8
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { DdlColumn, DdlTableConstraint } from '@prisma-next/sql-relational-core/ast';
|
|
2
|
+
import { PostgresCreateSchema, PostgresCreateTable } from '../core/ddl/nodes';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Build a Postgres `CREATE TABLE` query node.
|
|
6
|
+
*
|
|
7
|
+
* Pass `constraints` for table-level composite primary keys, foreign keys, and
|
|
8
|
+
* unique constraints — use the {@link PrimaryKeyConstraint}, {@link ForeignKeyConstraint},
|
|
9
|
+
* and {@link UniqueConstraint} classes from `@prisma-next/sql-relational-core/ast`.
|
|
10
|
+
*
|
|
11
|
+
* Precondition: identifiers (`table`, `schema`, column names/types) are
|
|
12
|
+
* emitted to SQL verbatim — they are not quoted or escaped, so callers must
|
|
13
|
+
* pass pre-trusted values (e.g. fixed control-plane identifiers). String-literal
|
|
14
|
+
* default values, by contrast, are single-quote-escaped (embedded `'` doubled)
|
|
15
|
+
* by the renderer. Identifier quoting for untrusted identifiers is added when
|
|
16
|
+
* the migration planner adopts this lowering path.
|
|
17
|
+
*/
|
|
18
|
+
export function createTable(options: {
|
|
19
|
+
readonly table: string;
|
|
20
|
+
readonly schema?: string;
|
|
21
|
+
readonly ifNotExists?: boolean;
|
|
22
|
+
readonly columns: readonly DdlColumn[];
|
|
23
|
+
readonly constraints?: readonly DdlTableConstraint[];
|
|
24
|
+
}): PostgresCreateTable {
|
|
25
|
+
return new PostgresCreateTable(options);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Build a Postgres `CREATE SCHEMA` query node. See {@link createTable} for the
|
|
30
|
+
* pre-trusted-identifier precondition.
|
|
31
|
+
*/
|
|
32
|
+
export function createSchema(options: {
|
|
33
|
+
readonly schema: string;
|
|
34
|
+
readonly ifNotExists?: boolean;
|
|
35
|
+
}): PostgresCreateSchema {
|
|
36
|
+
return new PostgresCreateSchema(options);
|
|
37
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type AnyFromSource,
|
|
3
|
+
type AstRewriter,
|
|
4
|
+
TableSource,
|
|
5
|
+
} from '@prisma-next/sql-relational-core/ast';
|
|
6
|
+
|
|
7
|
+
export class PostgresTableSource extends TableSource {
|
|
8
|
+
readonly schema: string | undefined;
|
|
9
|
+
|
|
10
|
+
constructor(options: {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly schema?: string;
|
|
13
|
+
readonly alias?: string;
|
|
14
|
+
}) {
|
|
15
|
+
super(options.name, options.alias);
|
|
16
|
+
this.schema = options.schema;
|
|
17
|
+
this.freeze();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
override rewrite(rewriter: AstRewriter): AnyFromSource {
|
|
21
|
+
return rewriter.tableSource ? rewriter.tableSource(this) : this;
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/core/codec-ids.ts
CHANGED
|
@@ -7,6 +7,7 @@ export {
|
|
|
7
7
|
SQL_VARCHAR_CODEC_ID,
|
|
8
8
|
} from '@prisma-next/sql-relational-core/ast';
|
|
9
9
|
export const PG_TEXT_CODEC_ID = 'pg/text@1' as const;
|
|
10
|
+
export const PG_TEXT_ARRAY_CODEC_ID = 'pg/text-array@1' as const;
|
|
10
11
|
export const PG_ENUM_CODEC_ID = 'pg/enum@1' as const;
|
|
11
12
|
export const PG_CHAR_CODEC_ID = 'pg/char@1' as const;
|
|
12
13
|
export const PG_VARCHAR_CODEC_ID = 'pg/varchar@1' as const;
|
package/src/core/codecs.ts
CHANGED
|
@@ -71,6 +71,7 @@ import {
|
|
|
71
71
|
PG_JSON_CODEC_ID,
|
|
72
72
|
PG_JSONB_CODEC_ID,
|
|
73
73
|
PG_NUMERIC_CODEC_ID,
|
|
74
|
+
PG_TEXT_ARRAY_CODEC_ID,
|
|
74
75
|
PG_TEXT_CODEC_ID,
|
|
75
76
|
PG_TIME_CODEC_ID,
|
|
76
77
|
PG_TIMESTAMP_CODEC_ID,
|
|
@@ -99,6 +100,7 @@ const precisionParamsSchema = arktype({
|
|
|
99
100
|
}) satisfies StandardSchemaV1<PrecisionParams>;
|
|
100
101
|
|
|
101
102
|
const PG_TEXT_META = { db: { sql: { postgres: { nativeType: 'text' } } } } as const;
|
|
103
|
+
const PG_TEXT_ARRAY_META = { db: { sql: { postgres: { nativeType: 'text[]' } } } } as const;
|
|
102
104
|
const PG_INT4_META = { db: { sql: { postgres: { nativeType: 'integer' } } } } as const;
|
|
103
105
|
const PG_INT2_META = { db: { sql: { postgres: { nativeType: 'smallint' } } } } as const;
|
|
104
106
|
const PG_INT8_META = { db: { sql: { postgres: { nativeType: 'bigint' } } } } as const;
|
|
@@ -160,6 +162,47 @@ export const pgTextColumn = () =>
|
|
|
160
162
|
pgTextColumn satisfies ColumnHelperFor<PgTextDescriptor>;
|
|
161
163
|
pgTextColumn satisfies ColumnHelperForStrict<PgTextDescriptor>;
|
|
162
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Postgres `text[]` codec. Encode is an identity pass-through: the pg wire
|
|
167
|
+
* driver serialises a JS `string[]` to a Postgres array literal under the
|
|
168
|
+
* `$N::text[]` cast the renderer emits from this codec's `text[]` native type,
|
|
169
|
+
* and decode reads it back as a JS array. Used by the control plane to write
|
|
170
|
+
* the marker's `invariants` column. Not a user-facing scalar — it is not part
|
|
171
|
+
* of the authorable `CodecTypes` surface, only the runtime codec registry.
|
|
172
|
+
*/
|
|
173
|
+
export class PgTextArrayCodec extends CodecImpl<
|
|
174
|
+
typeof PG_TEXT_ARRAY_CODEC_ID,
|
|
175
|
+
readonly ['equality'],
|
|
176
|
+
readonly string[],
|
|
177
|
+
readonly string[]
|
|
178
|
+
> {
|
|
179
|
+
async encode(value: readonly string[], _ctx: CodecCallContext): Promise<readonly string[]> {
|
|
180
|
+
return value;
|
|
181
|
+
}
|
|
182
|
+
async decode(wire: readonly string[], _ctx: CodecCallContext): Promise<readonly string[]> {
|
|
183
|
+
return wire;
|
|
184
|
+
}
|
|
185
|
+
encodeJson(value: readonly string[]): JsonValue {
|
|
186
|
+
return [...value];
|
|
187
|
+
}
|
|
188
|
+
decodeJson(json: JsonValue): readonly string[] {
|
|
189
|
+
return Array.isArray(json) ? json.map((entry) => String(entry)) : [];
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export class PgTextArrayDescriptor extends CodecDescriptorImpl<void> {
|
|
194
|
+
override readonly codecId = PG_TEXT_ARRAY_CODEC_ID;
|
|
195
|
+
override readonly traits = ['equality'] as const;
|
|
196
|
+
override readonly targetTypes = ['text[]'] as const;
|
|
197
|
+
override readonly meta = PG_TEXT_ARRAY_META;
|
|
198
|
+
override readonly paramsSchema: StandardSchemaV1<void> = voidParamsSchema;
|
|
199
|
+
override factory(): (ctx: CodecInstanceContext) => PgTextArrayCodec {
|
|
200
|
+
return () => new PgTextArrayCodec(this);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export const pgTextArrayDescriptor = new PgTextArrayDescriptor();
|
|
205
|
+
|
|
163
206
|
export class PgInt4Codec extends CodecImpl<
|
|
164
207
|
typeof PG_INT4_CODEC_ID,
|
|
165
208
|
readonly ['equality', 'order', 'numeric'],
|
|
@@ -1036,4 +1079,5 @@ export const codecDescriptors: readonly AnyCodecDescriptor[] = [
|
|
|
1036
1079
|
pgEnumDescriptor,
|
|
1037
1080
|
pgJsonDescriptor,
|
|
1038
1081
|
pgJsonbDescriptor,
|
|
1082
|
+
pgTextArrayDescriptor,
|
|
1039
1083
|
];
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type DdlColumn,
|
|
3
|
+
DdlNode,
|
|
4
|
+
type DdlTableConstraint,
|
|
5
|
+
} from '@prisma-next/sql-relational-core/ast';
|
|
6
|
+
|
|
7
|
+
export interface PostgresDdlVisitor<R> {
|
|
8
|
+
createTable(node: PostgresCreateTable): R;
|
|
9
|
+
createSchema(node: PostgresCreateSchema): R;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export abstract class PostgresDdlNode extends DdlNode {
|
|
13
|
+
abstract accept<R>(visitor: PostgresDdlVisitor<R>): R;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function freezeDdlColumns(columns: readonly DdlColumn[]): ReadonlyArray<DdlColumn> {
|
|
17
|
+
return Object.freeze([...columns]);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function freezeConstraints(
|
|
21
|
+
constraints: readonly DdlTableConstraint[] | undefined,
|
|
22
|
+
): ReadonlyArray<DdlTableConstraint> | undefined {
|
|
23
|
+
return constraints ? Object.freeze([...constraints]) : undefined;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class PostgresCreateTable extends PostgresDdlNode {
|
|
27
|
+
readonly kind = 'create-table' as const;
|
|
28
|
+
readonly table: string;
|
|
29
|
+
readonly schema: string | undefined;
|
|
30
|
+
readonly ifNotExists: boolean | undefined;
|
|
31
|
+
readonly columns: ReadonlyArray<DdlColumn>;
|
|
32
|
+
readonly constraints: ReadonlyArray<DdlTableConstraint> | undefined;
|
|
33
|
+
|
|
34
|
+
constructor(options: {
|
|
35
|
+
readonly table: string;
|
|
36
|
+
readonly schema?: string;
|
|
37
|
+
readonly ifNotExists?: boolean;
|
|
38
|
+
readonly columns: readonly DdlColumn[];
|
|
39
|
+
readonly constraints?: readonly DdlTableConstraint[];
|
|
40
|
+
}) {
|
|
41
|
+
super();
|
|
42
|
+
this.table = options.table;
|
|
43
|
+
this.schema = options.schema;
|
|
44
|
+
this.ifNotExists = options.ifNotExists;
|
|
45
|
+
this.columns = freezeDdlColumns(options.columns);
|
|
46
|
+
this.constraints = freezeConstraints(options.constraints);
|
|
47
|
+
this.freeze();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
override accept<R>(visitor: PostgresDdlVisitor<R>): R {
|
|
51
|
+
return visitor.createTable(this);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export class PostgresCreateSchema extends PostgresDdlNode {
|
|
56
|
+
readonly kind = 'create-schema' as const;
|
|
57
|
+
readonly schema: string;
|
|
58
|
+
readonly ifNotExists: boolean | undefined;
|
|
59
|
+
|
|
60
|
+
constructor(options: { readonly schema: string; readonly ifNotExists?: boolean }) {
|
|
61
|
+
super();
|
|
62
|
+
this.schema = options.schema;
|
|
63
|
+
this.ifNotExists = options.ifNotExists;
|
|
64
|
+
this.freeze();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
override accept<R>(visitor: PostgresDdlVisitor<R>): R {
|
|
68
|
+
return visitor.createSchema(this);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export type AnyPostgresDdlNode = PostgresCreateTable | PostgresCreateSchema;
|
|
@@ -8,6 +8,7 @@ import { postgresTargetDescriptorMetaRuntime } from './descriptor-meta-runtime';
|
|
|
8
8
|
|
|
9
9
|
const postgresTargetDescriptorMetaBase = {
|
|
10
10
|
...postgresTargetDescriptorMetaRuntime,
|
|
11
|
+
defaultNamespaceId: 'public',
|
|
11
12
|
authoring: {
|
|
12
13
|
type: postgresAuthoringTypes,
|
|
13
14
|
field: postgresAuthoringFieldPresets,
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import type { Contract } from '@prisma-next/contract/types';
|
|
2
|
+
import type { ControlPolicySubject } from '@prisma-next/family-sql/control';
|
|
3
|
+
import type { SchemaIssue } from '@prisma-next/framework-components/control';
|
|
4
|
+
import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
|
|
5
|
+
import {
|
|
6
|
+
isPostgresEnumStorageEntry,
|
|
7
|
+
type SqlStorage,
|
|
8
|
+
storageTableAt,
|
|
9
|
+
} from '@prisma-next/sql-contract/types';
|
|
10
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
11
|
+
import { isPostgresSchema } from '../postgres-schema';
|
|
12
|
+
import type { PostgresOpFactoryCall } from './op-factory-call';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Factory calls that create a whole, previously-absent top-level storage
|
|
16
|
+
* object. Used to decide whether `tolerated` permits a call (it only allows
|
|
17
|
+
* creating absent objects, never modifying existing ones).
|
|
18
|
+
*
|
|
19
|
+
* Deliberately an explicit, closed set rather than a `factoryName`
|
|
20
|
+
* create/alter/drop classification: it answers exactly one yes/no question
|
|
21
|
+
* and is fail-closed. Any call not listed here — including future or
|
|
22
|
+
* extension-contributed factories — is treated as NOT object-creation, so it
|
|
23
|
+
* is suppressed under `tolerated` rather than permissively emitted.
|
|
24
|
+
*/
|
|
25
|
+
const OBJECT_CREATION_FACTORIES: ReadonlySet<string> = new Set<string>([
|
|
26
|
+
'createTable',
|
|
27
|
+
'createEnumType',
|
|
28
|
+
'createSchema',
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
function createsNewTopLevelObject(call: PostgresOpFactoryCall): boolean {
|
|
32
|
+
return OBJECT_CREATION_FACTORIES.has(call.factoryName);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function ddlSchemaNameForNamespace(contract: Contract<SqlStorage>, namespaceId: string): string {
|
|
36
|
+
const namespace = contract.storage.namespaces[namespaceId];
|
|
37
|
+
return isPostgresSchema(namespace) ? namespace.ddlSchemaName(contract.storage) : namespaceId;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function resolveNamespaceIdForTable(
|
|
41
|
+
contract: Contract<SqlStorage>,
|
|
42
|
+
tableName: string,
|
|
43
|
+
ddlSchemaName: string | undefined,
|
|
44
|
+
): string {
|
|
45
|
+
for (const namespaceId of Object.keys(contract.storage.namespaces)) {
|
|
46
|
+
const table = storageTableAt(contract.storage, namespaceId, tableName);
|
|
47
|
+
if (!table) continue;
|
|
48
|
+
if (
|
|
49
|
+
ddlSchemaName === undefined ||
|
|
50
|
+
ddlSchemaNameForNamespace(contract, namespaceId) === ddlSchemaName
|
|
51
|
+
) {
|
|
52
|
+
return namespaceId;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return UNBOUND_NAMESPACE_ID;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function resolveNamespaceIdForDdlSchema(
|
|
59
|
+
contract: Contract<SqlStorage>,
|
|
60
|
+
ddlSchemaName: string,
|
|
61
|
+
): string {
|
|
62
|
+
for (const namespaceId of Object.keys(contract.storage.namespaces)) {
|
|
63
|
+
const ns = contract.storage.namespaces[namespaceId];
|
|
64
|
+
if (isPostgresSchema(ns) && ns.ddlSchemaName(contract.storage) === ddlSchemaName) {
|
|
65
|
+
return namespaceId;
|
|
66
|
+
}
|
|
67
|
+
if (namespaceId === ddlSchemaName) {
|
|
68
|
+
return namespaceId;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return UNBOUND_NAMESPACE_ID;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface PostgresCallFields {
|
|
75
|
+
readonly schemaName?: string;
|
|
76
|
+
readonly tableName?: string;
|
|
77
|
+
readonly columnName?: string;
|
|
78
|
+
readonly typeName?: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function postgresCallFields(call: PostgresOpFactoryCall): PostgresCallFields {
|
|
82
|
+
return {
|
|
83
|
+
...ifDefined('schemaName', 'schemaName' in call ? call.schemaName : undefined),
|
|
84
|
+
...ifDefined('tableName', 'tableName' in call ? call.tableName : undefined),
|
|
85
|
+
...ifDefined('columnName', 'columnName' in call ? call.columnName : undefined),
|
|
86
|
+
...ifDefined('typeName', 'typeName' in call ? call.typeName : undefined),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function formatPostgresControlPolicySubjectLabel(
|
|
91
|
+
factoryName: string,
|
|
92
|
+
subject: ControlPolicySubject | undefined,
|
|
93
|
+
contract: Contract<SqlStorage>,
|
|
94
|
+
): string {
|
|
95
|
+
if (subject?.table) {
|
|
96
|
+
const ddlSchema = ddlSchemaNameForNamespace(contract, subject.namespaceId);
|
|
97
|
+
return `${factoryName}(${ddlSchema}.${subject.table})`;
|
|
98
|
+
}
|
|
99
|
+
if (subject?.typeName) {
|
|
100
|
+
const ddlSchema = ddlSchemaNameForNamespace(contract, subject.namespaceId);
|
|
101
|
+
return `${factoryName}(${ddlSchema}.${subject.typeName})`;
|
|
102
|
+
}
|
|
103
|
+
return factoryName;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function resolvePostgresCallControlPolicySubject(
|
|
107
|
+
call: PostgresOpFactoryCall,
|
|
108
|
+
contract: Contract<SqlStorage>,
|
|
109
|
+
): ControlPolicySubject | undefined {
|
|
110
|
+
const callFields = postgresCallFields(call);
|
|
111
|
+
const createsNewObject = createsNewTopLevelObject(call);
|
|
112
|
+
|
|
113
|
+
if (call.factoryName === 'createSchema' && callFields.schemaName) {
|
|
114
|
+
return {
|
|
115
|
+
namespaceId: resolveNamespaceIdForDdlSchema(contract, callFields.schemaName),
|
|
116
|
+
createsNewObject,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (callFields.typeName && call.factoryName !== 'addColumn') {
|
|
121
|
+
const namespaceId = callFields.schemaName
|
|
122
|
+
? resolveNamespaceIdForDdlSchema(contract, callFields.schemaName)
|
|
123
|
+
: UNBOUND_NAMESPACE_ID;
|
|
124
|
+
const ns = contract.storage.namespaces[namespaceId];
|
|
125
|
+
const rawEnum = isPostgresSchema(ns) ? ns.entries.type[callFields.typeName] : undefined;
|
|
126
|
+
const controlPolicy = isPostgresEnumStorageEntry(rawEnum) ? rawEnum.control : undefined;
|
|
127
|
+
return {
|
|
128
|
+
namespaceId,
|
|
129
|
+
...ifDefined('explicitNodeControlPolicy', controlPolicy),
|
|
130
|
+
typeName: callFields.typeName,
|
|
131
|
+
createsNewObject,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (callFields.tableName) {
|
|
136
|
+
const namespaceId = resolveNamespaceIdForTable(
|
|
137
|
+
contract,
|
|
138
|
+
callFields.tableName,
|
|
139
|
+
callFields.schemaName,
|
|
140
|
+
);
|
|
141
|
+
const table = storageTableAt(contract.storage, namespaceId, callFields.tableName);
|
|
142
|
+
const tableControlPolicy = table?.control;
|
|
143
|
+
return {
|
|
144
|
+
namespaceId,
|
|
145
|
+
...ifDefined('explicitNodeControlPolicy', tableControlPolicy),
|
|
146
|
+
table: callFields.tableName,
|
|
147
|
+
...ifDefined('column', callFields.columnName),
|
|
148
|
+
createsNewObject,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (callFields.schemaName) {
|
|
153
|
+
return {
|
|
154
|
+
namespaceId: resolveNamespaceIdForDdlSchema(contract, callFields.schemaName),
|
|
155
|
+
createsNewObject,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Issue kinds that describe the absence of a whole, top-level Postgres
|
|
164
|
+
* object — the same kinds `createsNewTopLevelObject` recognises for calls.
|
|
165
|
+
* Used by {@link resolvePostgresIssueCreationFactoryName} to decide whether
|
|
166
|
+
* a `tolerated` subject permits the issue to flow into the planner
|
|
167
|
+
* (create-if-absent) and to seed the suppressed-subject warning's
|
|
168
|
+
* `factoryName` when the planner is skipped.
|
|
169
|
+
*/
|
|
170
|
+
const POSTGRES_ISSUE_CREATION_FACTORY: Readonly<Record<string, string>> = Object.freeze({
|
|
171
|
+
missing_schema: 'createSchema',
|
|
172
|
+
missing_table: 'createTable',
|
|
173
|
+
type_missing: 'createEnumType',
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
export function resolvePostgresIssueCreationFactoryName(issue: SchemaIssue): string | undefined {
|
|
177
|
+
return POSTGRES_ISSUE_CREATION_FACTORY[issue.kind];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Resolve the control-policy subject coordinate for a single
|
|
182
|
+
* {@link SchemaIssue}. Mirrors the resolution `resolvePostgresCallControlPolicySubject`
|
|
183
|
+
* performs for a generated DDL call, but works *off the issue* — so the
|
|
184
|
+
* planner can partition issues by effective policy before the diff engine
|
|
185
|
+
* runs. `createsNewObject` is derived from the issue's kind: schema/table/
|
|
186
|
+
* type-missing issues describe a brand-new top-level object; everything else
|
|
187
|
+
* touches an existing object.
|
|
188
|
+
*
|
|
189
|
+
* An `extra_table` issue carries no contract namespace coordinate (the table
|
|
190
|
+
* isn't in any contract namespace), so the subject's `namespaceId` falls
|
|
191
|
+
* back to {@link UNBOUND_NAMESPACE_ID}; the call-side resolver does the same
|
|
192
|
+
* for the `DropTableCall` it produces.
|
|
193
|
+
*/
|
|
194
|
+
export function resolvePostgresIssueControlPolicySubject(
|
|
195
|
+
issue: SchemaIssue,
|
|
196
|
+
contract: Contract<SqlStorage>,
|
|
197
|
+
): ControlPolicySubject | undefined {
|
|
198
|
+
const createsNewObject = POSTGRES_ISSUE_CREATION_FACTORY[issue.kind] !== undefined;
|
|
199
|
+
|
|
200
|
+
if (issue.kind === 'missing_schema' && issue.namespaceId) {
|
|
201
|
+
return { namespaceId: issue.namespaceId, createsNewObject };
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if ('typeName' in issue && issue.typeName) {
|
|
205
|
+
const namespaceId =
|
|
206
|
+
'namespaceId' in issue && issue.namespaceId ? issue.namespaceId : UNBOUND_NAMESPACE_ID;
|
|
207
|
+
const ns = contract.storage.namespaces[namespaceId];
|
|
208
|
+
const rawEnum = isPostgresSchema(ns) ? ns.entries.type[issue.typeName] : undefined;
|
|
209
|
+
const controlPolicy = isPostgresEnumStorageEntry(rawEnum) ? rawEnum.control : undefined;
|
|
210
|
+
return {
|
|
211
|
+
namespaceId,
|
|
212
|
+
...ifDefined('explicitNodeControlPolicy', controlPolicy),
|
|
213
|
+
typeName: issue.typeName,
|
|
214
|
+
createsNewObject,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if ('table' in issue && issue.table) {
|
|
219
|
+
const namespaceId =
|
|
220
|
+
'namespaceId' in issue && issue.namespaceId
|
|
221
|
+
? issue.namespaceId
|
|
222
|
+
: resolveNamespaceIdForTable(contract, issue.table, undefined);
|
|
223
|
+
const table = storageTableAt(contract.storage, namespaceId, issue.table);
|
|
224
|
+
return {
|
|
225
|
+
namespaceId,
|
|
226
|
+
...ifDefined('explicitNodeControlPolicy', table?.control),
|
|
227
|
+
table: issue.table,
|
|
228
|
+
...ifDefined('column', 'column' in issue ? issue.column : undefined),
|
|
229
|
+
createsNewObject,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return undefined;
|
|
234
|
+
}
|
|
@@ -25,10 +25,13 @@ import type {
|
|
|
25
25
|
StorageTable,
|
|
26
26
|
StorageTypeInstance,
|
|
27
27
|
} from '@prisma-next/sql-contract/types';
|
|
28
|
+
import type { DdlColumn, DdlTableConstraint } from '@prisma-next/sql-relational-core/ast';
|
|
29
|
+
import * as contractFree from '@prisma-next/sql-relational-core/contract-free';
|
|
28
30
|
import type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';
|
|
29
31
|
import type { Result } from '@prisma-next/utils/result';
|
|
30
32
|
import { notOk, ok } from '@prisma-next/utils/result';
|
|
31
33
|
import { PostgresEnumType } from '../postgres-enum-type';
|
|
34
|
+
import { isPostgresSchema } from '../postgres-schema';
|
|
32
35
|
import {
|
|
33
36
|
AddColumnCall,
|
|
34
37
|
AddForeignKeyCall,
|
|
@@ -39,6 +42,7 @@ import {
|
|
|
39
42
|
CreateIndexCall,
|
|
40
43
|
CreateSchemaCall,
|
|
41
44
|
CreateTableCall,
|
|
45
|
+
DropCheckConstraintCall,
|
|
42
46
|
DropColumnCall,
|
|
43
47
|
DropConstraintCall,
|
|
44
48
|
DropDefaultCall,
|
|
@@ -46,6 +50,7 @@ import {
|
|
|
46
50
|
DropNotNullCall,
|
|
47
51
|
DropTableCall,
|
|
48
52
|
type PostgresOpFactoryCall,
|
|
53
|
+
postgresDefaultToDdlColumnDefault,
|
|
49
54
|
SetDefaultCall,
|
|
50
55
|
SetNotNullCall,
|
|
51
56
|
} from './op-factory-call';
|
|
@@ -73,8 +78,7 @@ function locateNamespaceTypeInStorage(
|
|
|
73
78
|
typeName: string,
|
|
74
79
|
): unknown {
|
|
75
80
|
const ns = storage.namespaces[namespaceId];
|
|
76
|
-
|
|
77
|
-
return (ns.enum as Record<string, unknown>)[typeName];
|
|
81
|
+
return isPostgresSchema(ns) ? ns.entries.type[typeName] : undefined;
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
// ============================================================================
|
|
@@ -118,6 +122,11 @@ const ISSUE_KIND_ORDER: Record<string, number> = {
|
|
|
118
122
|
unique_constraint_mismatch: 51,
|
|
119
123
|
index_mismatch: 52,
|
|
120
124
|
foreign_key_mismatch: 60,
|
|
125
|
+
|
|
126
|
+
// Check constraints
|
|
127
|
+
check_missing: 53,
|
|
128
|
+
check_mismatch: 54,
|
|
129
|
+
check_removed: 55,
|
|
121
130
|
};
|
|
122
131
|
|
|
123
132
|
function issueOrder(issue: SchemaIssue): number {
|
|
@@ -191,16 +200,26 @@ function toColumnSpec(
|
|
|
191
200
|
): ColumnSpec {
|
|
192
201
|
return {
|
|
193
202
|
name,
|
|
194
|
-
typeSql: buildColumnTypeSql(
|
|
195
|
-
column,
|
|
196
|
-
codecHooks as Map<string, CodecControlHooks>,
|
|
197
|
-
storageTypes as Record<string, StorageTypeInstance | PostgresEnumStorageEntry>,
|
|
198
|
-
),
|
|
203
|
+
typeSql: buildColumnTypeSql(column, codecHooks, storageTypes),
|
|
199
204
|
defaultSql: buildColumnDefaultSql(column.default, column),
|
|
200
205
|
nullable: column.nullable,
|
|
201
206
|
};
|
|
202
207
|
}
|
|
203
208
|
|
|
209
|
+
function toDdlColumn(
|
|
210
|
+
name: string,
|
|
211
|
+
column: StorageColumn,
|
|
212
|
+
codecHooks: ReadonlyMap<string, CodecControlHooks>,
|
|
213
|
+
storageTypes: Readonly<Record<string, StorageTypeInstance | PostgresEnumStorageEntry>>,
|
|
214
|
+
): DdlColumn {
|
|
215
|
+
const typeSql = buildColumnTypeSql(column, codecHooks, storageTypes);
|
|
216
|
+
const ddlDefault = postgresDefaultToDdlColumnDefault(column.default);
|
|
217
|
+
return contractFree.col(name, typeSql, {
|
|
218
|
+
...(!column.nullable ? { notNull: true } : {}),
|
|
219
|
+
...(ddlDefault ? { default: ddlDefault } : {}),
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
204
223
|
function mapIssueToCall(
|
|
205
224
|
issue: SchemaIssue,
|
|
206
225
|
ctx: StrategyContext,
|
|
@@ -245,14 +264,18 @@ function mapIssueToCall(
|
|
|
245
264
|
);
|
|
246
265
|
}
|
|
247
266
|
const schemaForTable = tableSchema(issue);
|
|
248
|
-
const
|
|
249
|
-
|
|
267
|
+
const ddlColumns: DdlColumn[] = Object.entries(contractTable.columns).map(([name, column]) =>
|
|
268
|
+
toDdlColumn(name, column, codecHooks, storageTypes),
|
|
250
269
|
);
|
|
251
|
-
const
|
|
252
|
-
?
|
|
270
|
+
const ddlConstraints: DdlTableConstraint[] | undefined = contractTable.primaryKey
|
|
271
|
+
? [
|
|
272
|
+
contractFree.primaryKey(contractTable.primaryKey.columns, {
|
|
273
|
+
...(contractTable.primaryKey.name ? { name: contractTable.primaryKey.name } : {}),
|
|
274
|
+
}),
|
|
275
|
+
]
|
|
253
276
|
: undefined;
|
|
254
277
|
const calls: PostgresOpFactoryCall[] = [
|
|
255
|
-
new CreateTableCall(schemaForTable, issue.table,
|
|
278
|
+
new CreateTableCall(schemaForTable, issue.table, ddlColumns, ddlConstraints),
|
|
256
279
|
];
|
|
257
280
|
for (const index of contractTable.indexes) {
|
|
258
281
|
const indexName = index.name ?? `${issue.table}_${index.columns.join('_')}_idx`;
|
|
@@ -555,6 +578,48 @@ function mapIssueToCall(
|
|
|
555
578
|
),
|
|
556
579
|
);
|
|
557
580
|
|
|
581
|
+
case 'check_missing': {
|
|
582
|
+
if (!issue.table || !issue.indexOrConstraint)
|
|
583
|
+
return notOk(
|
|
584
|
+
issueConflict('unsupportedOperation', 'Check missing issue has no table/constraint name'),
|
|
585
|
+
);
|
|
586
|
+
// check_missing is normally consumed by checkConstraintPlanCallStrategy.
|
|
587
|
+
// This case handles any that arrive here (e.g. in tests that invoke
|
|
588
|
+
// mapIssueToCall directly or skip the strategy).
|
|
589
|
+
return notOk(
|
|
590
|
+
issueConflict(
|
|
591
|
+
'unsupportedOperation',
|
|
592
|
+
`Check constraint "${issue.indexOrConstraint}" missing on "${issue.table}" — handled by checkConstraintPlanCallStrategy`,
|
|
593
|
+
),
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
case 'check_mismatch': {
|
|
598
|
+
if (!issue.table || !issue.indexOrConstraint)
|
|
599
|
+
return notOk(
|
|
600
|
+
issueConflict(
|
|
601
|
+
'unsupportedOperation',
|
|
602
|
+
'Check mismatch issue has no table/constraint name',
|
|
603
|
+
),
|
|
604
|
+
);
|
|
605
|
+
return notOk(
|
|
606
|
+
issueConflict(
|
|
607
|
+
'unsupportedOperation',
|
|
608
|
+
`Check constraint "${issue.indexOrConstraint}" values mismatch on "${issue.table}" — handled by checkConstraintPlanCallStrategy`,
|
|
609
|
+
),
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
case 'check_removed': {
|
|
614
|
+
if (!issue.table || !issue.indexOrConstraint)
|
|
615
|
+
return notOk(
|
|
616
|
+
issueConflict('unsupportedOperation', 'Check removed issue has no table/constraint name'),
|
|
617
|
+
);
|
|
618
|
+
return ok([
|
|
619
|
+
new DropCheckConstraintCall(tableSchema(issue), issue.table, issue.indexOrConstraint),
|
|
620
|
+
]);
|
|
621
|
+
}
|
|
622
|
+
|
|
558
623
|
case 'foreign_key_mismatch':
|
|
559
624
|
if (!issue.table)
|
|
560
625
|
return notOk(issueConflict('foreignKeyConflict', 'Foreign key issue has no table name'));
|
|
@@ -601,7 +666,7 @@ function mapIssueToCall(
|
|
|
601
666
|
case 'type_missing': {
|
|
602
667
|
if (!issue.typeName)
|
|
603
668
|
return notOk(issueConflict('unsupportedOperation', 'Type missing issue has no typeName'));
|
|
604
|
-
// Codec aliases live in storage.types; enum types live in namespace.
|
|
669
|
+
// Codec aliases live in storage.types; enum types live in namespace.entries.type.
|
|
605
670
|
// Check types first; fall back to the namespace-keyed enum slot using the
|
|
606
671
|
// issue's namespace coordinate (populated by the verifier for enum-related
|
|
607
672
|
// issues per the BaseSchemaIssue.namespaceId contract).
|
|
@@ -687,9 +752,12 @@ function classifyCall(call: PostgresOpFactoryCall): CallCategory {
|
|
|
687
752
|
case 'dropTable':
|
|
688
753
|
case 'dropColumn':
|
|
689
754
|
case 'dropConstraint':
|
|
755
|
+
case 'dropCheckConstraint':
|
|
690
756
|
case 'dropIndex':
|
|
691
757
|
case 'dropDefault':
|
|
692
758
|
return 'drop';
|
|
759
|
+
case 'addCheckConstraint':
|
|
760
|
+
return 'unique'; // after uniques, before indexes
|
|
693
761
|
case 'createTable':
|
|
694
762
|
return 'table';
|
|
695
763
|
case 'addColumn':
|