@prisma-next/target-postgres 0.15.0 → 0.16.0-dev.10
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/{authoring-BtsOWgI3.mjs → authoring-34L18kA1.mjs} +18 -8
- package/dist/authoring-34L18kA1.mjs.map +1 -0
- package/dist/canonicalize-D1F4vUnP.d.mts.map +1 -1
- package/dist/{codec-ids-CI144z7g.d.mts → codec-ids-BswpvvND.d.mts} +3 -3
- package/dist/codec-ids-BswpvvND.d.mts.map +1 -0
- package/dist/{codec-ids-B10ZZHzw.mjs → codec-ids-D3G8K0YM.mjs} +3 -2
- package/dist/codec-ids-D3G8K0YM.mjs.map +1 -0
- package/dist/codec-ids.d.mts +2 -2
- package/dist/codec-ids.mjs +2 -2
- package/dist/{codec-types-CTfT4U4O.d.mts → codec-types-CQ07nOz-.d.mts} +4 -5
- package/dist/codec-types-CQ07nOz-.d.mts.map +1 -0
- package/dist/codec-types.d.mts +1 -1
- package/dist/{codecs-D7W9O0Xx.d.mts → codecs-G4DTY0F_.d.mts} +35 -7
- package/dist/codecs-G4DTY0F_.d.mts.map +1 -0
- package/dist/{codecs-DRbb26Or.mjs → codecs-TCsGgW-Y.mjs} +77 -5
- package/dist/codecs-TCsGgW-Y.mjs.map +1 -0
- package/dist/codecs.d.mts +2 -3
- package/dist/codecs.d.mts.map +1 -1
- package/dist/codecs.mjs +2 -2
- package/dist/contract-free.d.mts +2 -3
- package/dist/contract-free.d.mts.map +1 -1
- package/dist/contract-free.mjs +3 -3
- package/dist/{control-policy-DtbkLLGv.mjs → control-policy-S7XBe07W.mjs} +44 -75
- package/dist/control-policy-S7XBe07W.mjs.map +1 -0
- package/dist/control.d.mts +0 -1
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +75 -25
- package/dist/control.mjs.map +1 -1
- package/dist/data-transform-BOWpliq8.mjs.map +1 -1
- package/dist/{data-transform-DPzwBMhW.d.mts → data-transform-CGvE8yGx.d.mts} +1 -2
- package/dist/data-transform-CGvE8yGx.d.mts.map +1 -0
- package/dist/data-transform.d.mts +1 -1
- package/dist/{ddl-GTTOvjx_.mjs → ddl-DHXKzQ99.mjs} +3 -3
- package/dist/{ddl-GTTOvjx_.mjs.map → ddl-DHXKzQ99.mjs.map} +1 -1
- package/dist/ddl.d.mts +1 -1
- package/dist/default-normalizer-B9ZUiyUE.mjs +264 -0
- package/dist/default-normalizer-B9ZUiyUE.mjs.map +1 -0
- package/dist/default-normalizer.d.mts +14 -2
- package/dist/default-normalizer.d.mts.map +1 -1
- package/dist/default-normalizer.mjs +2 -248
- package/dist/{descriptor-meta-CFQKLXl_.mjs → descriptor-meta-qubYaxQA.mjs} +9 -4
- package/dist/descriptor-meta-qubYaxQA.mjs.map +1 -0
- package/dist/{diff-database-schema-GncqMuSI.mjs → diff-database-schema-BRxq7l98.mjs} +92 -26
- package/dist/diff-database-schema-BRxq7l98.mjs.map +1 -0
- package/dist/diff-database-schema.d.mts +4 -13
- package/dist/diff-database-schema.d.mts.map +1 -1
- package/dist/diff-database-schema.mjs +1 -1
- package/dist/{errors-DO-w0EUS.mjs → errors-ByDS0xJL.mjs} +6 -6
- package/dist/errors-ByDS0xJL.mjs.map +1 -0
- package/dist/errors.d.mts +4 -4
- package/dist/errors.d.mts.map +1 -1
- package/dist/errors.mjs +1 -1
- package/dist/issue-planner.d.mts +1 -2
- package/dist/issue-planner.d.mts.map +1 -1
- package/dist/issue-planner.mjs +1 -1
- package/dist/migration.d.mts +3 -4
- package/dist/migration.d.mts.map +1 -1
- package/dist/migration.mjs +2 -2
- package/dist/native-type-normalizer.d.mts.map +1 -1
- package/dist/{nodes-Dv5eCSq9.d.mts → nodes-CQzM2hR0.d.mts} +1 -2
- package/dist/nodes-CQzM2hR0.d.mts.map +1 -0
- package/dist/{op-factory-call-C38NzvQD.mjs → op-factory-call-Ci3H6InB.mjs} +37 -21
- package/dist/op-factory-call-Ci3H6InB.mjs.map +1 -0
- package/dist/{op-factory-call-Bn9zDx4_.d.mts → op-factory-call-DT7kdjVP.d.mts} +10 -7
- package/dist/op-factory-call-DT7kdjVP.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 +122 -6
- package/dist/pack.d.mts.map +1 -1
- package/dist/pack.mjs +1 -1
- package/dist/{planner-kql24i_F.mjs → planner-BpL7uktH.mjs} +15 -15
- package/dist/planner-BpL7uktH.mjs.map +1 -0
- package/dist/planner-ddl-builders.d.mts +1 -2
- package/dist/planner-ddl-builders.d.mts.map +1 -1
- package/dist/planner-identity-values.d.mts +0 -1
- package/dist/planner-identity-values.d.mts.map +1 -1
- package/dist/{planner-produced-postgres-migration-BEY1T0Xm.d.mts → planner-produced-postgres-migration-8QP8eMph.d.mts} +3 -4
- package/dist/planner-produced-postgres-migration-8QP8eMph.d.mts.map +1 -0
- package/dist/{planner-produced-postgres-migration-D7y-PEHK.mjs → planner-produced-postgres-migration-D8exrrxA.mjs} +8 -5
- package/dist/planner-produced-postgres-migration-D8exrrxA.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.d.mts +0 -1
- package/dist/planner-schema-lookup.d.mts.map +1 -1
- package/dist/{planner-sql-checks-zqNfs2XZ.mjs → planner-sql-checks-BuB877wH.mjs} +2 -2
- package/dist/{planner-sql-checks-zqNfs2XZ.mjs.map → planner-sql-checks-BuB877wH.mjs.map} +1 -1
- package/dist/planner-sql-checks.d.mts +0 -1
- package/dist/planner-sql-checks.d.mts.map +1 -1
- package/dist/planner-sql-checks.mjs +1 -1
- package/dist/planner-target-details-HkP4RrRO.d.mts.map +1 -1
- package/dist/planner.d.mts +9 -4
- package/dist/planner.d.mts.map +1 -1
- package/dist/planner.mjs +2 -2
- package/dist/{postgres-contract-view-C9j5cqP0.d.mts → postgres-contract-view-CeU7FJjW.d.mts} +4 -3
- package/dist/postgres-contract-view-CeU7FJjW.d.mts.map +1 -0
- package/dist/{postgres-contract-view-DM8sN1Ot.mjs → postgres-contract-view-DebHMqGR.mjs} +4 -4
- package/dist/{postgres-contract-view-DM8sN1Ot.mjs.map → postgres-contract-view-DebHMqGR.mjs.map} +1 -1
- package/dist/{postgres-database-schema-node-CJv5bfbs.d.mts → postgres-database-schema-node-DMXsIwAb.d.mts} +12 -4
- package/dist/postgres-database-schema-node-DMXsIwAb.d.mts.map +1 -0
- package/dist/{postgres-migration-arMSWU9b.mjs → postgres-migration-Bn3fj1I4.mjs} +22 -6
- package/dist/postgres-migration-Bn3fj1I4.mjs.map +1 -0
- package/dist/{postgres-migration-DbckK1su.d.mts → postgres-migration-DLIvzHjX.d.mts} +31 -7
- package/dist/postgres-migration-DLIvzHjX.d.mts.map +1 -0
- package/dist/{postgres-rls-policy--CSddvMR.d.mts → postgres-rls-policy-CYXdqG9B.d.mts} +1 -2
- package/dist/postgres-rls-policy-CYXdqG9B.d.mts.map +1 -0
- package/dist/{postgres-role-schema-node-Cm-j0ZGM.mjs → postgres-role-schema-node-bg32e7I-.mjs} +3 -2
- package/dist/postgres-role-schema-node-bg32e7I-.mjs.map +1 -0
- package/dist/{postgres-schema-Cm4DtiGA.mjs → postgres-schema-CewLYHB7.mjs} +2 -2
- package/dist/{postgres-schema-Cm4DtiGA.mjs.map → postgres-schema-CewLYHB7.mjs.map} +1 -1
- package/dist/{postgres-schema-DKq6s1P3.d.mts → postgres-schema-FdKRwe7X.d.mts} +3 -4
- package/dist/postgres-schema-FdKRwe7X.d.mts.map +1 -0
- package/dist/render-ops.d.mts +0 -1
- package/dist/render-ops.d.mts.map +1 -1
- package/dist/{render-typescript-7yqILcwr.mjs → render-typescript-Ta7_6CGf.mjs} +20 -8
- package/dist/render-typescript-Ta7_6CGf.mjs.map +1 -0
- package/dist/render-typescript.d.mts +2 -1
- package/dist/render-typescript.d.mts.map +1 -1
- package/dist/render-typescript.mjs +1 -1
- package/dist/{resolve-ddl-schema-XyBaaenM.mjs → resolve-ddl-schema-D0wi_P9Q.mjs} +2 -2
- package/dist/{resolve-ddl-schema-XyBaaenM.mjs.map → resolve-ddl-schema-D0wi_P9Q.mjs.map} +1 -1
- package/dist/rls-canonicalize.d.mts +0 -1
- package/dist/rls-canonicalize.d.mts.map +1 -1
- package/dist/runtime.d.mts +1 -2
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +1 -1
- package/dist/schema-ir-annotations.d.mts +0 -1
- package/dist/schema-ir-annotations.d.mts.map +1 -1
- package/dist/schema-ir-annotations.mjs +1 -1
- package/dist/schema-node-kinds-DxvWh2Ic.d.mts +29 -0
- package/dist/schema-node-kinds-DxvWh2Ic.d.mts.map +1 -0
- package/dist/sql-utils.d.mts.map +1 -1
- package/dist/{table-source-BvFo7gVs.d.mts → table-source-D5c2fxAQ.d.mts} +1 -2
- package/dist/table-source-D5c2fxAQ.d.mts.map +1 -0
- package/dist/{types-BDKkx8MA.d.mts → types-D2MLzLBD.d.mts} +1 -2
- package/dist/types-D2MLzLBD.d.mts.map +1 -0
- package/dist/types.d.mts +6 -5
- package/dist/types.mjs +4 -4
- package/package.json +21 -21
- package/src/core/authoring.ts +18 -5
- package/src/core/codec-helpers.ts +53 -1
- package/src/core/codec-ids.ts +1 -0
- package/src/core/codecs.ts +56 -3
- package/src/core/default-normalizer.ts +22 -0
- package/src/core/descriptor-meta.ts +2 -0
- package/src/core/errors.ts +5 -5
- package/src/core/index-types.ts +15 -0
- package/src/core/migrations/contract-to-postgres-database-schema-node.ts +99 -19
- package/src/core/migrations/control-policy.ts +4 -3
- package/src/core/migrations/diff-database-schema.ts +6 -3
- package/src/core/migrations/issue-planner.ts +41 -80
- package/src/core/migrations/op-factory-call.ts +41 -22
- package/src/core/migrations/operations/data-transform.ts +2 -2
- package/src/core/migrations/planner-produced-postgres-migration.ts +9 -2
- package/src/core/migrations/planner-strategies.ts +6 -6
- package/src/core/migrations/planner.ts +13 -4
- package/src/core/migrations/postgres-migration.ts +62 -2
- package/src/core/migrations/render-typescript.ts +20 -8
- package/src/core/migrations/runner.ts +12 -11
- package/src/core/migrations/verify-postgres-namespaces.ts +0 -1
- package/src/core/psl-infer/infer-psl-contract.ts +130 -12
- package/src/core/schema-ir/postgres-policy-schema-node.ts +12 -2
- package/src/exports/codecs.ts +2 -0
- package/src/exports/control.ts +2 -0
- package/src/exports/default-normalizer.ts +1 -1
- package/src/exports/op-factory-call.ts +5 -0
- package/src/exports/types.ts +1 -0
- package/dist/authoring-BtsOWgI3.mjs.map +0 -1
- package/dist/codec-ids-B10ZZHzw.mjs.map +0 -1
- package/dist/codec-ids-CI144z7g.d.mts.map +0 -1
- package/dist/codec-types-CTfT4U4O.d.mts.map +0 -1
- package/dist/codecs-D7W9O0Xx.d.mts.map +0 -1
- package/dist/codecs-DRbb26Or.mjs.map +0 -1
- package/dist/control-policy-DtbkLLGv.mjs.map +0 -1
- package/dist/data-transform-DPzwBMhW.d.mts.map +0 -1
- package/dist/default-normalizer.mjs.map +0 -1
- package/dist/descriptor-meta-CFQKLXl_.mjs.map +0 -1
- package/dist/diff-database-schema-GncqMuSI.mjs.map +0 -1
- package/dist/errors-DO-w0EUS.mjs.map +0 -1
- package/dist/nodes-Dv5eCSq9.d.mts.map +0 -1
- package/dist/op-factory-call-Bn9zDx4_.d.mts.map +0 -1
- package/dist/op-factory-call-C38NzvQD.mjs.map +0 -1
- package/dist/planner-kql24i_F.mjs.map +0 -1
- package/dist/planner-produced-postgres-migration-BEY1T0Xm.d.mts.map +0 -1
- package/dist/planner-produced-postgres-migration-D7y-PEHK.mjs.map +0 -1
- package/dist/postgres-contract-view-C9j5cqP0.d.mts.map +0 -1
- package/dist/postgres-database-schema-node-CJv5bfbs.d.mts.map +0 -1
- package/dist/postgres-migration-DbckK1su.d.mts.map +0 -1
- package/dist/postgres-migration-arMSWU9b.mjs.map +0 -1
- package/dist/postgres-rls-policy--CSddvMR.d.mts.map +0 -1
- package/dist/postgres-role-schema-node-Cm-j0ZGM.mjs.map +0 -1
- package/dist/postgres-schema-DKq6s1P3.d.mts.map +0 -1
- package/dist/render-typescript-7yqILcwr.mjs.map +0 -1
- package/dist/table-source-BvFo7gVs.d.mts.map +0 -1
- package/dist/types-BDKkx8MA.d.mts.map +0 -1
|
@@ -25,6 +25,7 @@ import type {
|
|
|
25
25
|
} from '@prisma-next/family-sql/control';
|
|
26
26
|
import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
|
|
27
27
|
import type { DiffableNode, SchemaDiffIssue } from '@prisma-next/framework-components/control';
|
|
28
|
+
import { issueOutcome, orderIssuesByDependencies } from '@prisma-next/framework-components/control';
|
|
28
29
|
import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
|
|
29
30
|
import type { SqlStorage, StorageTypeInstance } from '@prisma-next/sql-contract/types';
|
|
30
31
|
import type { DdlTableConstraint } from '@prisma-next/sql-relational-core/ast';
|
|
@@ -136,6 +137,7 @@ export interface IssuePlannerValue {
|
|
|
136
137
|
type CallCategory =
|
|
137
138
|
| 'dep'
|
|
138
139
|
| 'drop'
|
|
140
|
+
| 'dropType'
|
|
139
141
|
| 'table'
|
|
140
142
|
| 'rlsEnable'
|
|
141
143
|
| 'rlsPolicy'
|
|
@@ -151,6 +153,13 @@ type CallCategory =
|
|
|
151
153
|
* legacy walk-schema planner's emission order so `db init` and `db update`
|
|
152
154
|
* produce byte-identical plans for the shared shape (deps → drops → tables
|
|
153
155
|
* → columns → alters → PKs → uniques → indexes → FKs).
|
|
156
|
+
*
|
|
157
|
+
* `dropType` (DROP TYPE for a managed native enum) is its own bucket, ordered
|
|
158
|
+
* after the general drop bucket: a type can only be dropped once every table
|
|
159
|
+
* whose column uses it is gone. A column→enum edge would make this precise,
|
|
160
|
+
* but `coalesceSubtreeIssues` removes the column issue under a whole-table
|
|
161
|
+
* drop, so the edge never reaches the graph; the coarse bucket stands in until
|
|
162
|
+
* that edge lands (the coordinate work is a later slice).
|
|
154
163
|
*/
|
|
155
164
|
function classifyCall(call: PostgresOpFactoryCall): CallCategory {
|
|
156
165
|
switch (call.factoryName) {
|
|
@@ -159,8 +168,9 @@ function classifyCall(call: PostgresOpFactoryCall): CallCategory {
|
|
|
159
168
|
case 'createNativeEnumType':
|
|
160
169
|
case 'addNativeEnumValue':
|
|
161
170
|
return 'dep';
|
|
162
|
-
case 'dropTable':
|
|
163
171
|
case 'dropNativeEnumType':
|
|
172
|
+
return 'dropType';
|
|
173
|
+
case 'dropTable':
|
|
164
174
|
case 'dropColumn':
|
|
165
175
|
case 'dropConstraint':
|
|
166
176
|
case 'dropCheckConstraint':
|
|
@@ -369,57 +379,6 @@ export function columnTypeChanged(expected: SqlColumnIR, actual: SqlColumnIR): b
|
|
|
369
379
|
);
|
|
370
380
|
}
|
|
371
381
|
|
|
372
|
-
// ----------------------------------------------------------------------------
|
|
373
|
-
// Node-keyed issue ordering (re-keys ISSUE_KIND_ORDER on nodeKind + reason)
|
|
374
|
-
// ----------------------------------------------------------------------------
|
|
375
|
-
|
|
376
|
-
/**
|
|
377
|
-
* Re-keys the legacy `ISSUE_KIND_ORDER` on `(nodeKind, reason)`, numbers
|
|
378
|
-
* preserved so the dependency intent stays legible. Final emission order is
|
|
379
|
-
* fixed downstream by `classifyCall` bucketing (dep → drop → table → column →
|
|
380
|
-
* recipe → alter → primaryKey → unique → index → foreignKey), so this only
|
|
381
|
-
* breaks ties within a bucket.
|
|
382
|
-
*/
|
|
383
|
-
export function nodeIssueOrder(issue: SchemaDiffIssue): number {
|
|
384
|
-
const node = issueNode(issue);
|
|
385
|
-
if (node === undefined) return 99;
|
|
386
|
-
switch (node.nodeKind) {
|
|
387
|
-
case PostgresSchemaNodeKind.namespace:
|
|
388
|
-
return 1;
|
|
389
|
-
case PostgresSchemaNodeKind.nativeEnum:
|
|
390
|
-
// Creates order right after namespace creates within the 'dep' bucket
|
|
391
|
-
// (CREATE SCHEMA before CREATE TYPE); drops order after table drops
|
|
392
|
-
// within the 'drop' bucket (DROP TYPE only after its dependents left).
|
|
393
|
-
return issue.reason === 'not-expected' ? 17 : 2;
|
|
394
|
-
case RelationalSchemaNodeKind.foreignKey:
|
|
395
|
-
return issue.reason === 'not-expected' ? 10 : 60;
|
|
396
|
-
case RelationalSchemaNodeKind.unique:
|
|
397
|
-
return issue.reason === 'not-expected' ? 11 : 51;
|
|
398
|
-
case RelationalSchemaNodeKind.primaryKey:
|
|
399
|
-
return issue.reason === 'not-expected' ? 12 : 50;
|
|
400
|
-
case RelationalSchemaNodeKind.index:
|
|
401
|
-
return issue.reason === 'not-expected' ? 13 : 52;
|
|
402
|
-
case RelationalSchemaNodeKind.columnDefault:
|
|
403
|
-
if (issue.reason === 'not-expected') return 14;
|
|
404
|
-
return issue.reason === 'not-found' ? 42 : 43;
|
|
405
|
-
case RelationalSchemaNodeKind.column:
|
|
406
|
-
if (issue.reason === 'not-expected') return 15;
|
|
407
|
-
return issue.reason === 'not-found' ? 30 : 40;
|
|
408
|
-
case PostgresSchemaNodeKind.table:
|
|
409
|
-
return issue.reason === 'not-expected' ? 16 : 20;
|
|
410
|
-
case RelationalSchemaNodeKind.check:
|
|
411
|
-
if (issue.reason === 'not-found') return 53;
|
|
412
|
-
return issue.reason === 'not-expected' ? 55 : 54;
|
|
413
|
-
default:
|
|
414
|
-
return 99;
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
/** Deterministic tiebreak within an order bucket: the diff path already encodes schema → table → child. */
|
|
419
|
-
export function nodeIssueKey(issue: SchemaDiffIssue): string {
|
|
420
|
-
return issue.path.join(' ');
|
|
421
|
-
}
|
|
422
|
-
|
|
423
382
|
// ----------------------------------------------------------------------------
|
|
424
383
|
// Subtree coalescing (the planner's responsibility per the differ's contract)
|
|
425
384
|
// ----------------------------------------------------------------------------
|
|
@@ -437,7 +396,7 @@ export function coalesceSubtreeIssues<TNode extends DiffableNode = DiffableNode>
|
|
|
437
396
|
issues: readonly SchemaDiffIssue<TNode>[],
|
|
438
397
|
): readonly SchemaDiffIssue<TNode>[] {
|
|
439
398
|
const collapsingPaths = issues
|
|
440
|
-
.filter((issue) => issue
|
|
399
|
+
.filter((issue) => issueOutcome(issue) !== 'not-equal')
|
|
441
400
|
.map((issue) => issue.path);
|
|
442
401
|
if (collapsingPaths.length === 0) return issues;
|
|
443
402
|
return issues.filter(
|
|
@@ -601,14 +560,14 @@ function mapNativeEnumNodeIssue(
|
|
|
601
560
|
);
|
|
602
561
|
}
|
|
603
562
|
const schemaName = emissionSchemaName(ctx, ddlSchemaName);
|
|
604
|
-
if (issue
|
|
563
|
+
if (issueOutcome(issue) === 'not-found') {
|
|
605
564
|
const expected = blindCast<
|
|
606
565
|
PostgresNativeEnumSchemaNode,
|
|
607
566
|
'a not-found native-enum issue always carries the expected PostgresNativeEnumSchemaNode'
|
|
608
567
|
>(issue.expected);
|
|
609
568
|
return ok([new CreateNativeEnumTypeCall(schemaName, expected.typeName, expected.members)]);
|
|
610
569
|
}
|
|
611
|
-
if (issue
|
|
570
|
+
if (issueOutcome(issue) === 'not-expected') {
|
|
612
571
|
const actual = blindCast<
|
|
613
572
|
PostgresNativeEnumSchemaNode,
|
|
614
573
|
'a not-expected native-enum issue always carries the actual PostgresNativeEnumSchemaNode'
|
|
@@ -654,14 +613,14 @@ function mapTableNodeIssue(
|
|
|
654
613
|
ddlSchemaName: string,
|
|
655
614
|
codecHooks: ReadonlyMap<string, CodecControlHooks>,
|
|
656
615
|
): Result<readonly PostgresOpFactoryCall[], SqlPlannerConflict> {
|
|
657
|
-
if (issue
|
|
616
|
+
if (issueOutcome(issue) === 'not-found') {
|
|
658
617
|
const table = blindCast<
|
|
659
618
|
PostgresTableSchemaNode,
|
|
660
619
|
'a not-found table issue always carries the expected PostgresTableSchemaNode'
|
|
661
620
|
>(issue.expected);
|
|
662
621
|
return ok(buildCreateTableCallsFromNode(schemaName, ddlSchemaName, table, codecHooks));
|
|
663
622
|
}
|
|
664
|
-
if (issue
|
|
623
|
+
if (issueOutcome(issue) === 'not-expected') {
|
|
665
624
|
const table = blindCast<
|
|
666
625
|
PostgresTableSchemaNode,
|
|
667
626
|
'a not-expected table issue always carries the actual PostgresTableSchemaNode'
|
|
@@ -703,7 +662,7 @@ function mapColumnNodeIssue(
|
|
|
703
662
|
tableName: string,
|
|
704
663
|
codecHooks: ReadonlyMap<string, CodecControlHooks>,
|
|
705
664
|
): Result<readonly PostgresOpFactoryCall[], SqlPlannerConflict> {
|
|
706
|
-
if (issue
|
|
665
|
+
if (issueOutcome(issue) === 'not-found') {
|
|
707
666
|
const column = blindCast<
|
|
708
667
|
SqlColumnIR,
|
|
709
668
|
'a not-found column issue always carries the expected column node'
|
|
@@ -712,7 +671,7 @@ function mapColumnNodeIssue(
|
|
|
712
671
|
new AddColumnCall(schemaName, tableName, renderColumnDdl(column.name, column, codecHooks)),
|
|
713
672
|
]);
|
|
714
673
|
}
|
|
715
|
-
if (issue
|
|
674
|
+
if (issueOutcome(issue) === 'not-expected') {
|
|
716
675
|
const column = blindCast<
|
|
717
676
|
SqlColumnIR,
|
|
718
677
|
'a not-expected column issue always carries the actual column node'
|
|
@@ -755,7 +714,7 @@ function mapColumnDefaultNodeIssue(
|
|
|
755
714
|
tableName: string,
|
|
756
715
|
columnName: string,
|
|
757
716
|
): Result<readonly PostgresOpFactoryCall[], SqlPlannerConflict> {
|
|
758
|
-
if (issue
|
|
717
|
+
if (issueOutcome(issue) === 'not-expected') {
|
|
759
718
|
return ok([new DropDefaultCall(schemaName, tableName, columnName)]);
|
|
760
719
|
}
|
|
761
720
|
// not-found (SET DEFAULT, additive) or not-equal (SET DEFAULT, widening).
|
|
@@ -772,7 +731,7 @@ function mapColumnDefaultNodeIssue(
|
|
|
772
731
|
tableName,
|
|
773
732
|
columnName,
|
|
774
733
|
defaultSql,
|
|
775
|
-
issue
|
|
734
|
+
issueOutcome(issue) === 'not-equal' ? 'widening' : 'additive',
|
|
776
735
|
),
|
|
777
736
|
]);
|
|
778
737
|
}
|
|
@@ -782,7 +741,7 @@ function mapPrimaryKeyNodeIssue(
|
|
|
782
741
|
schemaName: string,
|
|
783
742
|
tableName: string,
|
|
784
743
|
): Result<readonly PostgresOpFactoryCall[], SqlPlannerConflict> {
|
|
785
|
-
if (issue
|
|
744
|
+
if (issueOutcome(issue) === 'not-found') {
|
|
786
745
|
const pk = blindCast<
|
|
787
746
|
{ readonly columns: readonly string[]; readonly name?: string },
|
|
788
747
|
'a not-found primary-key issue always carries the expected PrimaryKey node'
|
|
@@ -790,7 +749,7 @@ function mapPrimaryKeyNodeIssue(
|
|
|
790
749
|
const constraintName = pk.name ?? `${tableName}_pkey`;
|
|
791
750
|
return ok([new AddPrimaryKeyCall(schemaName, tableName, constraintName, [...pk.columns])]);
|
|
792
751
|
}
|
|
793
|
-
if (issue
|
|
752
|
+
if (issueOutcome(issue) === 'not-expected') {
|
|
794
753
|
const pk = blindCast<
|
|
795
754
|
{ readonly name?: string },
|
|
796
755
|
'a not-expected primary-key issue always carries the actual PrimaryKey node'
|
|
@@ -807,14 +766,14 @@ function mapForeignKeyNodeIssue(
|
|
|
807
766
|
schemaName: string,
|
|
808
767
|
tableName: string,
|
|
809
768
|
): Result<readonly PostgresOpFactoryCall[], SqlPlannerConflict> {
|
|
810
|
-
if (issue
|
|
769
|
+
if (issueOutcome(issue) === 'not-found') {
|
|
811
770
|
const fk = blindCast<
|
|
812
771
|
SqlForeignKeyIR,
|
|
813
772
|
'a not-found foreign-key issue always carries the expected foreign-key node'
|
|
814
773
|
>(issue.expected);
|
|
815
774
|
return ok([new AddForeignKeyCall(schemaName, tableName, fkSpecFromNode(fk, tableName))]);
|
|
816
775
|
}
|
|
817
|
-
if (issue
|
|
776
|
+
if (issueOutcome(issue) === 'not-expected') {
|
|
818
777
|
const fk = blindCast<
|
|
819
778
|
SqlForeignKeyIR,
|
|
820
779
|
'a not-expected foreign-key issue always carries the actual foreign-key node'
|
|
@@ -830,7 +789,7 @@ function mapUniqueNodeIssue(
|
|
|
830
789
|
schemaName: string,
|
|
831
790
|
tableName: string,
|
|
832
791
|
): Result<readonly PostgresOpFactoryCall[], SqlPlannerConflict> {
|
|
833
|
-
if (issue
|
|
792
|
+
if (issueOutcome(issue) === 'not-found') {
|
|
834
793
|
const unique = blindCast<
|
|
835
794
|
SqlUniqueIR,
|
|
836
795
|
'a not-found unique issue always carries the expected unique node'
|
|
@@ -838,7 +797,7 @@ function mapUniqueNodeIssue(
|
|
|
838
797
|
const name = unique.name ?? `${tableName}_${unique.columns.join('_')}_key`;
|
|
839
798
|
return ok([new AddUniqueCall(schemaName, tableName, name, [...unique.columns])]);
|
|
840
799
|
}
|
|
841
|
-
if (issue
|
|
800
|
+
if (issueOutcome(issue) === 'not-expected') {
|
|
842
801
|
const unique = blindCast<
|
|
843
802
|
SqlUniqueIR,
|
|
844
803
|
'a not-expected unique issue always carries the actual unique node'
|
|
@@ -854,7 +813,7 @@ function mapIndexNodeIssue(
|
|
|
854
813
|
schemaName: string,
|
|
855
814
|
tableName: string,
|
|
856
815
|
): Result<readonly PostgresOpFactoryCall[], SqlPlannerConflict> {
|
|
857
|
-
if (issue
|
|
816
|
+
if (issueOutcome(issue) === 'not-found') {
|
|
858
817
|
const index = blindCast<
|
|
859
818
|
SqlIndexIR,
|
|
860
819
|
'a not-found index issue always carries the expected index node'
|
|
@@ -865,7 +824,7 @@ function mapIndexNodeIssue(
|
|
|
865
824
|
if (index.options !== undefined) extras.options = index.options;
|
|
866
825
|
return ok([new CreateIndexCall(schemaName, tableName, indexName, [...index.columns], extras)]);
|
|
867
826
|
}
|
|
868
|
-
if (issue
|
|
827
|
+
if (issueOutcome(issue) === 'not-expected') {
|
|
869
828
|
const index = blindCast<
|
|
870
829
|
SqlIndexIR,
|
|
871
830
|
'a not-expected index issue always carries the actual index node'
|
|
@@ -885,7 +844,7 @@ function mapCheckNodeIssue(
|
|
|
885
844
|
// the default mapper handles directly; check_missing / check_mismatch are
|
|
886
845
|
// consumed by `checkConstraintPlanCallStrategy` (drop+recreate), so reaching
|
|
887
846
|
// here for them means the strategy did not run — a conflict.
|
|
888
|
-
if (issue
|
|
847
|
+
if (issueOutcome(issue) === 'not-expected') {
|
|
889
848
|
const check = blindCast<
|
|
890
849
|
{ readonly name: string },
|
|
891
850
|
'a not-expected check issue always carries the actual check node'
|
|
@@ -902,8 +861,8 @@ function mapCheckNodeIssue(
|
|
|
902
861
|
|
|
903
862
|
/**
|
|
904
863
|
* Maps one node-typed diff issue to its migration call(s), dispatching on the
|
|
905
|
-
* node's `nodeKind`
|
|
906
|
-
* from `codecRef` via `column-ddl-rendering.ts`.
|
|
864
|
+
* node's `nodeKind` and the issue's presence-derived `issueOutcome`, reading
|
|
865
|
+
* nodes and resolving column DDL from `codecRef` via `column-ddl-rendering.ts`.
|
|
907
866
|
*/
|
|
908
867
|
export function mapNodeIssueToCall(
|
|
909
868
|
issue: SchemaDiffIssue,
|
|
@@ -919,7 +878,7 @@ export function mapNodeIssueToCall(
|
|
|
919
878
|
);
|
|
920
879
|
}
|
|
921
880
|
if (node.nodeKind === PostgresSchemaNodeKind.namespace) {
|
|
922
|
-
if (issue
|
|
881
|
+
if (issueOutcome(issue) !== 'not-found') {
|
|
923
882
|
return notOk(
|
|
924
883
|
nodeConflict('unsupportedOperation', `Unexpected namespace drift: ${issue.path.join('/')}`),
|
|
925
884
|
);
|
|
@@ -1052,13 +1011,12 @@ export function planIssues(
|
|
|
1052
1011
|
}
|
|
1053
1012
|
}
|
|
1054
1013
|
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
});
|
|
1014
|
+
// Dependency-graph order: a topological sort over the issues' `dependsOn`
|
|
1015
|
+
// cross-links and containment edges (the ordering law drives edge direction
|
|
1016
|
+
// by presence), path-tiebroken for determinism. `classifyCall` bucketing
|
|
1017
|
+
// downstream fixes the coarse cross-entity DDL sequence; this settles the
|
|
1018
|
+
// order within each bucket (notably the teardown order among drops).
|
|
1019
|
+
const sorted = orderIssuesByDependencies(remaining);
|
|
1062
1020
|
|
|
1063
1021
|
const defaultCalls: PostgresOpFactoryCall[] = [];
|
|
1064
1022
|
const conflicts: SqlPlannerConflict[] = [];
|
|
@@ -1106,6 +1064,9 @@ export function planIssues(
|
|
|
1106
1064
|
const calls: PostgresOpFactoryCall[] = [
|
|
1107
1065
|
...byCategory('dep'),
|
|
1108
1066
|
...byCategory('drop'),
|
|
1067
|
+
// DROP TYPE after every table drop — a managed enum type can only go once
|
|
1068
|
+
// no live column still uses it.
|
|
1069
|
+
...byCategory('dropType'),
|
|
1109
1070
|
...byCategory('table'),
|
|
1110
1071
|
...byCategory('column'),
|
|
1111
1072
|
...gatedRecipe,
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - `toOp()` — converts the IR node to a runtime
|
|
10
10
|
* `SqlMigrationPlanOperation` by delegating to the matching pure factory
|
|
11
11
|
* under `operations/`. `DataTransformCall.toOp()` always throws
|
|
12
|
-
* `
|
|
12
|
+
* `MIGRATION.UNFILLED_PLACEHOLDER` because a planner-generated data transform is an
|
|
13
13
|
* unfilled authoring stub by construction.
|
|
14
14
|
* - `renderTypeScript()` / `importRequirements()` — inherited from
|
|
15
15
|
* `TsExpression`. Used by `renderCallsToTypeScript` to emit the call as
|
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
tableExistsAst,
|
|
46
46
|
} from '../../contract-free/checks';
|
|
47
47
|
import * as contractFreeDdl from '../../contract-free/ddl';
|
|
48
|
-
import type { PostgresRlsPolicy } from '../postgres-rls-policy';
|
|
48
|
+
import type { PostgresRlsPolicy, PostgresRlsPolicyInput } from '../postgres-rls-policy';
|
|
49
49
|
import {
|
|
50
50
|
escapeLiteral,
|
|
51
51
|
quoteIdentifier,
|
|
@@ -740,10 +740,6 @@ export class AddNotNullColumnDirectCall extends PostgresOpFactoryCallNode {
|
|
|
740
740
|
renderTypeScript(): string {
|
|
741
741
|
return `rawSql(${jsonToTsSource({ id: `column.${this.tableName}.${this.columnName}`, label: this.label, operationClass: 'additive' })})`;
|
|
742
742
|
}
|
|
743
|
-
|
|
744
|
-
override importRequirements(): readonly ImportRequirement[] {
|
|
745
|
-
return [];
|
|
746
|
-
}
|
|
747
743
|
}
|
|
748
744
|
|
|
749
745
|
/**
|
|
@@ -810,10 +806,6 @@ export class AddNotNullColumnWithTempDefaultCall extends PostgresOpFactoryCallNo
|
|
|
810
806
|
renderTypeScript(): string {
|
|
811
807
|
return `rawSql(${jsonToTsSource({ id: `column.${this.tableName}.${this.columnName}`, label: this.label, operationClass: 'additive' })})`;
|
|
812
808
|
}
|
|
813
|
-
|
|
814
|
-
override importRequirements(): readonly ImportRequirement[] {
|
|
815
|
-
return [];
|
|
816
|
-
}
|
|
817
809
|
}
|
|
818
810
|
|
|
819
811
|
// ============================================================================
|
|
@@ -1515,7 +1507,7 @@ export class AddNativeEnumValueCall extends PostgresOpFactoryCallNode {
|
|
|
1515
1507
|
* A planner-generated data-transform stub. `checkSlot` and `runSlot` name
|
|
1516
1508
|
* the unfilled authoring slots that the rendered `migration.ts` will expose
|
|
1517
1509
|
* to the user via `placeholder("…")` calls. `toOp()` always throws
|
|
1518
|
-
* `
|
|
1510
|
+
* `MIGRATION.UNFILLED_PLACEHOLDER`: the planner cannot lower a stubbed transform to a runtime
|
|
1519
1511
|
* op — the user must fill the rendered `migration.ts` and re-emit.
|
|
1520
1512
|
*/
|
|
1521
1513
|
export class DataTransformCall extends PostgresOpFactoryCallNode {
|
|
@@ -1555,12 +1547,7 @@ export class DataTransformCall extends PostgresOpFactoryCallNode {
|
|
|
1555
1547
|
override importRequirements(): readonly ImportRequirement[] {
|
|
1556
1548
|
return [
|
|
1557
1549
|
{ moduleSpecifier: POSTGRES_MIGRATION_FACADE, symbol: 'placeholder' },
|
|
1558
|
-
|
|
1559
|
-
moduleSpecifier: './end-contract.json',
|
|
1560
|
-
symbol: 'endContract',
|
|
1561
|
-
kind: 'default',
|
|
1562
|
-
attributes: { type: 'json' },
|
|
1563
|
-
},
|
|
1550
|
+
// endContract is imported by the migration scaffold's contractImports; an op never renders outside it.
|
|
1564
1551
|
];
|
|
1565
1552
|
}
|
|
1566
1553
|
}
|
|
@@ -1592,7 +1579,23 @@ export class CreatePostgresRlsPolicyCall extends PostgresOpFactoryCallNode {
|
|
|
1592
1579
|
}
|
|
1593
1580
|
|
|
1594
1581
|
renderTypeScript(): string {
|
|
1595
|
-
|
|
1582
|
+
const p = this.policy;
|
|
1583
|
+
const input: PostgresRlsPolicyInput = {
|
|
1584
|
+
name: p.name,
|
|
1585
|
+
prefix: p.prefix,
|
|
1586
|
+
tableName: p.tableName,
|
|
1587
|
+
namespaceId: p.namespaceId,
|
|
1588
|
+
operation: p.operation,
|
|
1589
|
+
roles: p.roles,
|
|
1590
|
+
...ifDefined('using', p.using),
|
|
1591
|
+
...ifDefined('withCheck', p.withCheck),
|
|
1592
|
+
permissive: p.permissive,
|
|
1593
|
+
};
|
|
1594
|
+
return `this.createRlsPolicy({ schema: ${jsonToTsSource(this.schemaName)}, table: ${jsonToTsSource(this.tableName)}, policy: ${jsonToTsSource(input)} })`;
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
override importRequirements(): readonly ImportRequirement[] {
|
|
1598
|
+
return [];
|
|
1596
1599
|
}
|
|
1597
1600
|
}
|
|
1598
1601
|
|
|
@@ -1623,7 +1626,11 @@ export class DropPostgresRlsPolicyCall extends PostgresOpFactoryCallNode {
|
|
|
1623
1626
|
}
|
|
1624
1627
|
|
|
1625
1628
|
renderTypeScript(): string {
|
|
1626
|
-
return `dropRlsPolicy(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)}, ${jsonToTsSource(this.policyName)})`;
|
|
1629
|
+
return `this.dropRlsPolicy({ schema: ${jsonToTsSource(this.schemaName)}, table: ${jsonToTsSource(this.tableName)}, policy: ${jsonToTsSource(this.policyName)} })`;
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
override importRequirements(): readonly ImportRequirement[] {
|
|
1633
|
+
return [];
|
|
1627
1634
|
}
|
|
1628
1635
|
}
|
|
1629
1636
|
|
|
@@ -1652,7 +1659,11 @@ export class EnableRowLevelSecurityCall extends PostgresOpFactoryCallNode {
|
|
|
1652
1659
|
}
|
|
1653
1660
|
|
|
1654
1661
|
renderTypeScript(): string {
|
|
1655
|
-
return `enableRowLevelSecurity(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)})`;
|
|
1662
|
+
return `this.enableRowLevelSecurity({ schema: ${jsonToTsSource(this.schemaName)}, table: ${jsonToTsSource(this.tableName)} })`;
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
override importRequirements(): readonly ImportRequirement[] {
|
|
1666
|
+
return [];
|
|
1656
1667
|
}
|
|
1657
1668
|
}
|
|
1658
1669
|
|
|
@@ -1681,7 +1692,11 @@ export class DisableRowLevelSecurityCall extends PostgresOpFactoryCallNode {
|
|
|
1681
1692
|
}
|
|
1682
1693
|
|
|
1683
1694
|
renderTypeScript(): string {
|
|
1684
|
-
return `disableRowLevelSecurity(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)})`;
|
|
1695
|
+
return `this.disableRowLevelSecurity({ schema: ${jsonToTsSource(this.schemaName)}, table: ${jsonToTsSource(this.tableName)} })`;
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
override importRequirements(): readonly ImportRequirement[] {
|
|
1699
|
+
return [];
|
|
1685
1700
|
}
|
|
1686
1701
|
}
|
|
1687
1702
|
|
|
@@ -1724,7 +1739,11 @@ export class RenamePostgresRlsPolicyCall extends PostgresOpFactoryCallNode {
|
|
|
1724
1739
|
}
|
|
1725
1740
|
|
|
1726
1741
|
renderTypeScript(): string {
|
|
1727
|
-
return `renameRlsPolicy(${jsonToTsSource(this.schemaName)}, ${jsonToTsSource(this.tableName)}, ${jsonToTsSource(this.oldPolicyName)}, ${jsonToTsSource(this.newPolicyName)})`;
|
|
1742
|
+
return `this.renameRlsPolicy({ schema: ${jsonToTsSource(this.schemaName)}, table: ${jsonToTsSource(this.tableName)}, from: ${jsonToTsSource(this.oldPolicyName)}, to: ${jsonToTsSource(this.newPolicyName)} })`;
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1745
|
+
override importRequirements(): readonly ImportRequirement[] {
|
|
1746
|
+
return [];
|
|
1728
1747
|
}
|
|
1729
1748
|
}
|
|
1730
1749
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* supplies the control adapter from the migration's injected stack:
|
|
6
6
|
*
|
|
7
7
|
* ```ts
|
|
8
|
-
* import endContract from '
|
|
8
|
+
* import endContract from '../../snapshots/93f07d1b…c9e1e5a2/contract.json' with { type: 'json' };
|
|
9
9
|
*
|
|
10
10
|
* class M extends Migration {
|
|
11
11
|
* override get operations() {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
*
|
|
22
22
|
* The factory accepts lazy closures (`() => SqlQueryPlan | Buildable`),
|
|
23
23
|
* invokes each one, asserts that its `meta.storageHash` matches the
|
|
24
|
-
* `contract` it was handed (→ `
|
|
24
|
+
* `contract` it was handed (→ `MIGRATION.DATA_TRANSFORM_CONTRACT_MISMATCH` on mismatch), and lowers the
|
|
25
25
|
* plan via the supplied control adapter to a serialized `{sql, params}`
|
|
26
26
|
* payload.
|
|
27
27
|
*
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* Placeholder-bearing plans: `renderTypeScript()` always succeeds and embeds
|
|
16
16
|
* `() => placeholder("slot")` at each stub. `operations`, in contrast, is
|
|
17
17
|
* _not safe to enumerate_ on a stub-bearing plan — `DataTransformCall.toOp()`
|
|
18
|
-
* throws `
|
|
18
|
+
* throws `MIGRATION.UNFILLED_PLACEHOLDER` because a planner-stubbed closure cannot be lowered
|
|
19
19
|
* to a runtime op. Callers that know a plan may carry stubs must render to
|
|
20
20
|
* `migration.ts`, let the user fill the slots, and re-load the edited
|
|
21
21
|
* migration before enumerating ops. The walk-schema planner does not emit
|
|
@@ -42,6 +42,7 @@ export class TypeScriptRenderablePostgresMigration
|
|
|
42
42
|
readonly #calls: readonly OpFactoryCall[];
|
|
43
43
|
readonly #meta: MigrationMeta;
|
|
44
44
|
readonly #spaceId: string;
|
|
45
|
+
readonly #snapshotsImportPath: string;
|
|
45
46
|
readonly #lowerer: ExecuteRequestLowerer | undefined;
|
|
46
47
|
#operationsCache:
|
|
47
48
|
| readonly (
|
|
@@ -54,12 +55,14 @@ export class TypeScriptRenderablePostgresMigration
|
|
|
54
55
|
calls: readonly OpFactoryCall[],
|
|
55
56
|
meta: MigrationMeta,
|
|
56
57
|
spaceId: string,
|
|
58
|
+
snapshotsImportPath: string,
|
|
57
59
|
lowerer?: ExecuteRequestLowerer,
|
|
58
60
|
) {
|
|
59
61
|
super();
|
|
60
62
|
this.#calls = calls;
|
|
61
63
|
this.#meta = meta;
|
|
62
64
|
this.#spaceId = spaceId;
|
|
65
|
+
this.#snapshotsImportPath = snapshotsImportPath;
|
|
63
66
|
this.#lowerer = lowerer;
|
|
64
67
|
}
|
|
65
68
|
|
|
@@ -85,6 +88,10 @@ export class TypeScriptRenderablePostgresMigration
|
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
renderTypeScript(): string {
|
|
88
|
-
return renderCallsToTypeScript(this.#calls, {
|
|
91
|
+
return renderCallsToTypeScript(this.#calls, {
|
|
92
|
+
from: this.#meta.from,
|
|
93
|
+
to: this.#meta.to,
|
|
94
|
+
snapshotsImportPath: this.#snapshotsImportPath,
|
|
95
|
+
});
|
|
89
96
|
}
|
|
90
97
|
}
|
|
@@ -35,6 +35,7 @@ import type {
|
|
|
35
35
|
import { resolveValueSetValues } from '@prisma-next/family-sql/control';
|
|
36
36
|
import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
|
|
37
37
|
import type { SchemaDiffIssue } from '@prisma-next/framework-components/control';
|
|
38
|
+
import { issueOutcome } from '@prisma-next/framework-components/control';
|
|
38
39
|
import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
|
|
39
40
|
import {
|
|
40
41
|
type SqlStorage,
|
|
@@ -198,7 +199,7 @@ export const notNullBackfillCallStrategy: CallMigrationStrategy = (issues, ctx)
|
|
|
198
199
|
const calls: PostgresOpFactoryCall[] = [];
|
|
199
200
|
|
|
200
201
|
for (const issue of issues) {
|
|
201
|
-
if (issue
|
|
202
|
+
if (issueOutcome(issue) !== 'not-found') continue;
|
|
202
203
|
const node = issueNode(issue);
|
|
203
204
|
if (node === undefined || node.nodeKind !== RelationalSchemaNodeKind.column) continue;
|
|
204
205
|
const expected = blindCast<
|
|
@@ -263,7 +264,7 @@ export const typeChangeCallStrategy: CallMigrationStrategy = (issues, ctx) => {
|
|
|
263
264
|
const calls: PostgresOpFactoryCall[] = [];
|
|
264
265
|
|
|
265
266
|
for (const issue of issues) {
|
|
266
|
-
if (issue
|
|
267
|
+
if (issueOutcome(issue) !== 'not-equal') continue;
|
|
267
268
|
const pair = columnNodePair(issue);
|
|
268
269
|
if (pair === undefined) continue;
|
|
269
270
|
const { expected, actual } = pair;
|
|
@@ -357,7 +358,7 @@ export const nullableTighteningCallStrategy: CallMigrationStrategy = (issues, ct
|
|
|
357
358
|
const calls: PostgresOpFactoryCall[] = [];
|
|
358
359
|
|
|
359
360
|
for (const issue of issues) {
|
|
360
|
-
if (issue
|
|
361
|
+
if (issueOutcome(issue) !== 'not-equal') continue;
|
|
361
362
|
const pair = columnNodePair(issue);
|
|
362
363
|
if (pair === undefined) continue;
|
|
363
364
|
const { expected, actual } = pair;
|
|
@@ -590,7 +591,7 @@ export const notNullAddColumnCallStrategy: CallMigrationStrategy = (issues, ctx)
|
|
|
590
591
|
const mutableStorageTypes = ctx.storageTypes as Record<string, StorageTypeInstance>;
|
|
591
592
|
|
|
592
593
|
for (const issue of issues) {
|
|
593
|
-
if (issue
|
|
594
|
+
if (issueOutcome(issue) !== 'not-found') continue;
|
|
594
595
|
const node = issueNode(issue);
|
|
595
596
|
if (node === undefined || node.nodeKind !== RelationalSchemaNodeKind.column) continue;
|
|
596
597
|
const expected = blindCast<
|
|
@@ -685,8 +686,7 @@ function canUseSharedTemporaryDefaultStrategy(options: {
|
|
|
685
686
|
}
|
|
686
687
|
|
|
687
688
|
for (const foreignKey of table.foreignKeys) {
|
|
688
|
-
if (
|
|
689
|
-
continue;
|
|
689
|
+
if (!foreignKey.source.columns.includes(columnName)) continue;
|
|
690
690
|
if (!schemaLookup || !hasForeignKey(schemaLookup, foreignKey)) return false;
|
|
691
691
|
}
|
|
692
692
|
|
|
@@ -21,6 +21,7 @@ import type {
|
|
|
21
21
|
SchemaDiffIssue,
|
|
22
22
|
SchemaOwnership,
|
|
23
23
|
} from '@prisma-next/framework-components/control';
|
|
24
|
+
import { issueOutcome } from '@prisma-next/framework-components/control';
|
|
24
25
|
import { UNBOUND_NAMESPACE_ID } from '@prisma-next/framework-components/ir';
|
|
25
26
|
import type { SqlStorage } from '@prisma-next/sql-contract/types';
|
|
26
27
|
import type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';
|
|
@@ -140,6 +141,12 @@ export class PostgresMigrationPlanner implements MigrationPlanner<'sql', 'postgr
|
|
|
140
141
|
* {@link SqlMigrationPlannerPlanOptions.ownership}.
|
|
141
142
|
*/
|
|
142
143
|
readonly ownership?: SchemaOwnership;
|
|
144
|
+
/**
|
|
145
|
+
* POSIX-relative path from the migration package dir to
|
|
146
|
+
* `migrations/snapshots` — see
|
|
147
|
+
* {@link SqlMigrationPlannerPlanOptions.snapshotsImportPath}.
|
|
148
|
+
*/
|
|
149
|
+
readonly snapshotsImportPath: string;
|
|
143
150
|
}): PostgresPlanResult {
|
|
144
151
|
return this.planSql(options as SqlMigrationPlannerPlanOptions);
|
|
145
152
|
}
|
|
@@ -155,6 +162,7 @@ export class PostgresMigrationPlanner implements MigrationPlanner<'sql', 'postgr
|
|
|
155
162
|
to: context.toHash,
|
|
156
163
|
},
|
|
157
164
|
spaceId,
|
|
165
|
+
context.snapshotsImportPath,
|
|
158
166
|
this.#lowerer,
|
|
159
167
|
);
|
|
160
168
|
}
|
|
@@ -211,7 +219,7 @@ export class PostgresMigrationPlanner implements MigrationPlanner<'sql', 'postgr
|
|
|
211
219
|
options.policy.allowedOperationClasses.includes('destructive');
|
|
212
220
|
const coalesced = coalesceSubtreeIssues(relationalDiffIssues);
|
|
213
221
|
const owned = retainUnownedExtras(coalesced, options.ownership, options.contract);
|
|
214
|
-
const gated = strict ? owned : owned.filter((issue) => issue
|
|
222
|
+
const gated = strict ? owned : owned.filter((issue) => issueOutcome(issue) !== 'not-expected');
|
|
215
223
|
|
|
216
224
|
// Namespace presence (`CREATE SCHEMA`) is a planner-only op-generation
|
|
217
225
|
// concern stitched in here rather than inside the shared diff — verify
|
|
@@ -322,6 +330,7 @@ export class PostgresMigrationPlanner implements MigrationPlanner<'sql', 'postgr
|
|
|
322
330
|
to: options.contract.storage.storageHash,
|
|
323
331
|
},
|
|
324
332
|
options.spaceId,
|
|
333
|
+
options.snapshotsImportPath,
|
|
325
334
|
this.#lowerer,
|
|
326
335
|
),
|
|
327
336
|
...(warnings.length > 0 ? { warnings: Object.freeze(warnings) } : {}),
|
|
@@ -369,7 +378,7 @@ export class PostgresMigrationPlanner implements MigrationPlanner<'sql', 'postgr
|
|
|
369
378
|
// 'not-equal' is unreachable for content-addressed policies: the wire name
|
|
370
379
|
// encodes the body hash, so two policies sharing a local key (same name)
|
|
371
380
|
// are always equal and isEqualTo never returns false.
|
|
372
|
-
if (issue
|
|
381
|
+
if (issueOutcome(issue) === 'not-found') {
|
|
373
382
|
const expected = issue.expected;
|
|
374
383
|
PostgresPolicySchemaNode.assert(expected);
|
|
375
384
|
// expected.namespaceId is the DDL schema name (resolved during projection);
|
|
@@ -381,7 +390,7 @@ export class PostgresMigrationPlanner implements MigrationPlanner<'sql', 'postgr
|
|
|
381
390
|
expected.namespaceId,
|
|
382
391
|
),
|
|
383
392
|
});
|
|
384
|
-
} else if (issue
|
|
393
|
+
} else if (issueOutcome(issue) === 'not-expected') {
|
|
385
394
|
const actual = issue.actual;
|
|
386
395
|
PostgresPolicySchemaNode.assert(actual);
|
|
387
396
|
extra.push({
|
|
@@ -505,7 +514,7 @@ function retainUnownedExtras(
|
|
|
505
514
|
): readonly SchemaDiffIssue<SqlSchemaDiffNode>[] {
|
|
506
515
|
if (ownership === undefined) return issues;
|
|
507
516
|
return issues.filter((issue) => {
|
|
508
|
-
if (issue
|
|
517
|
+
if (issueOutcome(issue) !== 'not-expected') return true;
|
|
509
518
|
const node = issueNode(issue);
|
|
510
519
|
if (node === undefined) return true;
|
|
511
520
|
const coordinate = postgresNodeStorageCoordinate(node);
|