@prisma-next/target-postgres 0.9.0-dev.7 → 0.9.0-dev.9
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-RvYfmUmi.d.mts → codec-ids-D9fJ4HP5.d.mts} +1 -1
- package/dist/{codec-ids-RvYfmUmi.d.mts.map → codec-ids-D9fJ4HP5.d.mts.map} +1 -1
- package/dist/codec-ids.d.mts +1 -1
- package/dist/{codec-types-667FxIW8.d.mts → codec-types-CRlHq7Cz.d.mts} +2 -2
- package/dist/{codec-types-667FxIW8.d.mts.map → codec-types-CRlHq7Cz.d.mts.map} +1 -1
- package/dist/codec-types.d.mts +1 -1
- package/dist/{codecs-DXeDABSO.d.mts → codecs-Dud5KDNk.d.mts} +2 -2
- package/dist/{codecs-DXeDABSO.d.mts.map → codecs-Dud5KDNk.d.mts.map} +1 -1
- package/dist/codecs.d.mts +1 -1
- package/dist/control.d.mts +1 -1
- package/dist/control.mjs +5 -5
- package/dist/{data-transform-COkGR6Ns.mjs → data-transform-CdtGUWp2.mjs} +1 -1
- package/dist/{data-transform-COkGR6Ns.mjs.map → data-transform-CdtGUWp2.mjs.map} +1 -1
- package/dist/{data-transform-B6p02mFJ.d.mts → data-transform-bmOKkygi.d.mts} +2 -2
- package/dist/{data-transform-B6p02mFJ.d.mts.map → data-transform-bmOKkygi.d.mts.map} +1 -1
- package/dist/data-transform.d.mts +1 -1
- package/dist/data-transform.mjs +1 -1
- package/dist/descriptor-meta-zrZzWmJF.mjs +91 -0
- package/dist/{descriptor-meta-DFUCClk_.mjs.map → descriptor-meta-zrZzWmJF.mjs.map} +1 -1
- package/dist/enum-planning.d.mts +1 -1
- package/dist/{errors-BiOloWUh.mjs → errors--zafB5_n.mjs} +1 -1
- package/dist/{errors-BiOloWUh.mjs.map → errors--zafB5_n.mjs.map} +1 -1
- package/dist/errors.mjs +1 -1
- package/dist/{issue-planner-BhWVYyE1.mjs → issue-planner-qalHRCI2.mjs} +179 -77
- package/dist/issue-planner-qalHRCI2.mjs.map +1 -0
- package/dist/issue-planner.d.mts +2 -2
- package/dist/issue-planner.d.mts.map +1 -1
- package/dist/issue-planner.mjs +1 -1
- package/dist/migration.d.mts +3 -3
- package/dist/migration.mjs +3 -3
- package/dist/{op-factory-call-c1zELk3U.d.mts → op-factory-call-Drccm_JD.d.mts} +3 -3
- package/dist/{op-factory-call-c1zELk3U.d.mts.map → op-factory-call-Drccm_JD.d.mts.map} +1 -1
- package/dist/{op-factory-call-DerP9BoT.mjs → op-factory-call-Zsrdty3k.mjs} +2 -2
- package/dist/{op-factory-call-DerP9BoT.mjs.map → op-factory-call-Zsrdty3k.mjs.map} +1 -1
- package/dist/op-factory-call.d.mts +1 -1
- package/dist/op-factory-call.mjs +1 -1
- package/dist/pack.d.mts +2 -2
- package/dist/pack.mjs +1 -1
- package/dist/{planner-DnzPpv1j.mjs → planner-C8yhbXOq.mjs} +84 -5
- package/dist/planner-C8yhbXOq.mjs.map +1 -0
- package/dist/{planner-ddl-builders-5QIyhBUF.mjs → planner-ddl-builders-DINYrbJ3.mjs} +4 -4
- package/dist/{planner-ddl-builders-5QIyhBUF.mjs.map → planner-ddl-builders-DINYrbJ3.mjs.map} +1 -1
- package/dist/planner-ddl-builders.d.mts +1 -1
- package/dist/planner-ddl-builders.mjs +1 -1
- package/dist/{planner-identity-values-BUYNOCwb.mjs → planner-identity-values-ojX-6cPV.mjs} +1 -1
- package/dist/{planner-identity-values-BUYNOCwb.mjs.map → planner-identity-values-ojX-6cPV.mjs.map} +1 -1
- package/dist/planner-identity-values.mjs +1 -1
- package/dist/{planner-produced-postgres-migration-FYsKh26I.mjs → planner-produced-postgres-migration-BqGLw7VT.mjs} +4 -4
- package/dist/{planner-produced-postgres-migration-FYsKh26I.mjs.map → planner-produced-postgres-migration-BqGLw7VT.mjs.map} +1 -1
- package/dist/{planner-produced-postgres-migration-D34ftfEK.d.mts → planner-produced-postgres-migration-c9lpjPv1.d.mts} +3 -3
- package/dist/{planner-produced-postgres-migration-D34ftfEK.d.mts.map → planner-produced-postgres-migration-c9lpjPv1.d.mts.map} +1 -1
- package/dist/planner-produced-postgres-migration.d.mts +1 -1
- package/dist/planner-produced-postgres-migration.mjs +1 -1
- package/dist/planner-schema-lookup-BGyukuzG.mjs +57 -0
- package/dist/planner-schema-lookup-BGyukuzG.mjs.map +1 -0
- package/dist/planner-schema-lookup.d.mts.map +1 -1
- package/dist/planner-schema-lookup.mjs +1 -1
- package/dist/{planner-sql-checks-Cd016Ycs.mjs → planner-sql-checks-BM4sD6Xc.mjs} +28 -11
- package/dist/planner-sql-checks-BM4sD6Xc.mjs.map +1 -0
- package/dist/planner-sql-checks.d.mts +11 -0
- package/dist/planner-sql-checks.d.mts.map +1 -1
- package/dist/planner-sql-checks.mjs +1 -1
- package/dist/{planner-target-details-iYJwzFHP.d.mts → planner-target-details-CIj61DUj.d.mts} +1 -1
- package/dist/{planner-target-details-iYJwzFHP.d.mts.map → planner-target-details-CIj61DUj.d.mts.map} +1 -1
- package/dist/planner-target-details.d.mts +1 -1
- package/dist/planner.d.mts +1 -1
- package/dist/planner.d.mts.map +1 -1
- package/dist/planner.mjs +1 -1
- package/dist/postgres-contract-serializer-CcZO9ukP.mjs +83 -0
- package/dist/postgres-contract-serializer-CcZO9ukP.mjs.map +1 -0
- package/dist/{postgres-enum-type-CrKq8au9.d.mts → postgres-enum-type-CNhPTDhy.d.mts} +1 -1
- package/dist/{postgres-enum-type-CrKq8au9.d.mts.map → postgres-enum-type-CNhPTDhy.d.mts.map} +1 -1
- package/dist/{postgres-migration-q4oWyNJE.mjs → postgres-migration-C5os-tkl.mjs} +3 -3
- package/dist/{postgres-migration-q4oWyNJE.mjs.map → postgres-migration-C5os-tkl.mjs.map} +1 -1
- package/dist/{postgres-migration-CiQzhcMe.d.mts → postgres-migration-jvsKgUDM.d.mts} +3 -3
- package/dist/{postgres-migration-CiQzhcMe.d.mts.map → postgres-migration-jvsKgUDM.d.mts.map} +1 -1
- package/dist/postgres-schema-BosNxhWq.mjs +163 -0
- package/dist/postgres-schema-BosNxhWq.mjs.map +1 -0
- package/dist/{render-ops-CkiuHSNj.mjs → render-ops-BC2PtCkj.mjs} +1 -1
- package/dist/{render-ops-CkiuHSNj.mjs.map → render-ops-BC2PtCkj.mjs.map} +1 -1
- package/dist/render-ops.d.mts +1 -1
- package/dist/render-ops.mjs +1 -1
- package/dist/{render-typescript-C9XWI8Ld.mjs → render-typescript-nRHbqLbI.mjs} +1 -1
- package/dist/{render-typescript-C9XWI8Ld.mjs.map → render-typescript-nRHbqLbI.mjs.map} +1 -1
- package/dist/render-typescript.mjs +1 -1
- package/dist/runtime.d.mts +7 -17
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +2 -2
- package/dist/{shared-DLYdmYo-.d.mts → shared-ByhSooBS.d.mts} +6 -4
- package/dist/shared-ByhSooBS.d.mts.map +1 -0
- package/dist/{statement-builders-BSIQMClE.mjs → statement-builders-vImtdfmM.mjs} +1 -1
- package/dist/{statement-builders-BSIQMClE.mjs.map → statement-builders-vImtdfmM.mjs.map} +1 -1
- package/dist/statement-builders.mjs +1 -1
- package/dist/{tables-Ce_Q0I8B.mjs → tables-DZ-5Yxi0.mjs} +3 -3
- package/dist/tables-DZ-5Yxi0.mjs.map +1 -0
- package/dist/{types-Dq74Z3eu.d.mts → types-D-XIpzHA.d.mts} +1 -1
- package/dist/types-D-XIpzHA.d.mts.map +1 -0
- package/dist/types.d.mts +125 -3
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +2 -1
- package/package.json +17 -17
- package/src/core/migrations/issue-planner.ts +131 -41
- package/src/core/migrations/operations/constraints.ts +1 -1
- package/src/core/migrations/operations/shared.ts +4 -2
- package/src/core/migrations/planner-ddl-builders.ts +2 -2
- package/src/core/migrations/planner-schema-lookup.ts +30 -6
- package/src/core/migrations/planner-sql-checks.ts +29 -11
- package/src/core/migrations/planner-strategies.ts +138 -43
- package/src/core/migrations/planner.ts +14 -1
- package/src/core/migrations/verify-postgres-namespaces.ts +87 -0
- package/src/core/postgres-contract-serializer.ts +139 -60
- package/src/core/postgres-schema.ts +208 -0
- package/src/exports/types.ts +5 -0
- package/dist/descriptor-meta-DFUCClk_.mjs +0 -124
- package/dist/issue-planner-BhWVYyE1.mjs.map +0 -1
- package/dist/planner-DnzPpv1j.mjs.map +0 -1
- package/dist/planner-schema-lookup--u9whY_Y.mjs +0 -29
- package/dist/planner-schema-lookup--u9whY_Y.mjs.map +0 -1
- package/dist/planner-sql-checks-Cd016Ycs.mjs.map +0 -1
- package/dist/postgres-contract-serializer-D5VJk6lo.mjs +0 -61
- package/dist/postgres-contract-serializer-D5VJk6lo.mjs.map +0 -1
- package/dist/shared-DLYdmYo-.d.mts.map +0 -1
- package/dist/tables-Ce_Q0I8B.mjs.map +0 -1
- package/dist/types-Dq74Z3eu.d.mts.map +0 -1
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { t as PostgresEnumType } from "./postgres-enum-type-DS-KLVRH.mjs";
|
|
2
2
|
import { r as readExistingEnumValues, t as determineEnumDiff } from "./enum-planning-Bqp96iIw.mjs";
|
|
3
3
|
import { i as quoteIdentifier } from "./sql-utils-BewXAnsG.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { n as
|
|
7
|
-
import { n as
|
|
8
|
-
import {
|
|
4
|
+
import { r as isPostgresSchema } from "./postgres-schema-BosNxhWq.mjs";
|
|
5
|
+
import { a as columnNullabilityCheck, c as qualifyTableName, i as columnHasNoDefaultCheck, r as columnExistsCheck, t as buildExpectedFormatType, u as tableIsEmptyCheck } from "./planner-sql-checks-BM4sD6Xc.mjs";
|
|
6
|
+
import { C as SetNotNullCall, S as SetDefaultCall, _ as DropIndexCall, a as AddUniqueCall, b as RawSqlCall, d as CreateTableCall, f as DataTransformCall, g as DropEnumTypeCall, h as DropDefaultCall, i as AddPrimaryKeyCall, l as CreateIndexCall, m as DropConstraintCall, n as AddEnumValuesCall, o as AlterColumnTypeCall, p as DropColumnCall, r as AddForeignKeyCall, s as CreateEnumTypeCall, t as AddColumnCall, u as CreateSchemaCall, v as DropNotNullCall, x as RenameTypeCall, y as DropTableCall } from "./op-factory-call-Zsrdty3k.mjs";
|
|
7
|
+
import { n as buildColumnDefaultSql, r as buildColumnTypeSql, t as buildAddColumnSql } from "./planner-ddl-builders-DINYrbJ3.mjs";
|
|
8
|
+
import { n as resolveIdentityValue } from "./planner-identity-values-ojX-6cPV.mjs";
|
|
9
|
+
import { i as hasUniqueConstraint, n as hasForeignKey, t as buildSchemaLookupMap } from "./planner-schema-lookup-BGyukuzG.mjs";
|
|
9
10
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
11
|
+
import { UNBOUND_NAMESPACE_ID } from "@prisma-next/framework-components/ir";
|
|
10
12
|
import { isPostgresEnumStorageEntry } from "@prisma-next/sql-contract/types";
|
|
11
13
|
import { arraysEqual } from "@prisma-next/family-sql/schema-verify";
|
|
12
14
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
@@ -86,8 +88,60 @@ function buildAddNotNullColumnWithTemporaryDefaultOperation(options) {
|
|
|
86
88
|
//#endregion
|
|
87
89
|
//#region src/core/migrations/planner-strategies.ts
|
|
88
90
|
const REBUILD_SUFFIX = "__prisma_next_new";
|
|
89
|
-
|
|
90
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Look up a storage table by its explicit namespace coordinate. Returns
|
|
93
|
+
* `undefined` when the namespace has no table by that name (or no such
|
|
94
|
+
* namespace exists). Callers that get `undefined` MUST treat it as an
|
|
95
|
+
* explicit conflict — never silently fall back to a global default
|
|
96
|
+
* schema or a name-only walk, because that footgun would resolve a
|
|
97
|
+
* stale or duplicate table name to whichever namespace the iteration
|
|
98
|
+
* order surfaced first (a real data-loss hazard in multi-namespace
|
|
99
|
+
* contracts where two namespaces can carry the same table name).
|
|
100
|
+
*/
|
|
101
|
+
function tableAt(storage, namespaceId, tableName) {
|
|
102
|
+
return storage.namespaces[namespaceId]?.tables[tableName];
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Default namespace coordinate for an issue that does not carry one
|
|
106
|
+
* explicitly. Hand-crafted unit-test issues and `extra_table` issues
|
|
107
|
+
* fall back to `__unbound__`, the only namespace any single-namespace
|
|
108
|
+
* contract carries — verifier-emitted issues for legacy
|
|
109
|
+
* single-namespace contracts already stamp this id explicitly. Typed
|
|
110
|
+
* structurally so issue variants without a `namespaceId` slot
|
|
111
|
+
* (e.g. `EnumValuesChangedIssue`) flow through to the same fallback.
|
|
112
|
+
*/
|
|
113
|
+
function resolveNamespaceIdForIssue(issue) {
|
|
114
|
+
return issue.namespaceId ?? UNBOUND_NAMESPACE_ID;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Resolve the DDL schema name for a namespace coordinate. Postgres-aware
|
|
118
|
+
* namespaces dispatch to their polymorphic `ddlSchemaName` override —
|
|
119
|
+
* named schemas return their own id and the unbound singleton projects
|
|
120
|
+
* to `'public'` (sibling-present) or the framework sentinel
|
|
121
|
+
* (sibling-absent). Legacy single-namespace contracts whose `__unbound__`
|
|
122
|
+
* slot is the framework-default `SqlUnboundNamespace` (rather than the
|
|
123
|
+
* Postgres-aware `PostgresUnboundSchema`) flow the coordinate through
|
|
124
|
+
* unchanged so downstream `qualifyTableName` resolves polymorphically.
|
|
125
|
+
*/
|
|
126
|
+
function resolveDdlSchemaForNamespace(ctx, namespaceId) {
|
|
127
|
+
const namespace = ctx.toContract.storage.namespaces[namespaceId];
|
|
128
|
+
if (isPostgresSchema(namespace)) return namespace.ddlSchemaName(ctx.toContract.storage);
|
|
129
|
+
return namespaceId;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Finds a type entry by name across all namespace type registries.
|
|
133
|
+
* Namespace types (e.g. Postgres enums) live under
|
|
134
|
+
* `storage.namespaces[nsId].types`, not under `storage.types`.
|
|
135
|
+
*/
|
|
136
|
+
function locateNamespaceType(storage, typeName) {
|
|
137
|
+
for (const ns of Object.values(storage.namespaces)) {
|
|
138
|
+
if (!("types" in ns) || ns.types == null) continue;
|
|
139
|
+
const entry = ns.types[typeName];
|
|
140
|
+
if (entry !== void 0) return entry;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function buildColumnSpec(namespaceId, table, column, ctx, overrides) {
|
|
144
|
+
const col = tableAt(ctx.toContract.storage, namespaceId, table)?.columns[column];
|
|
91
145
|
if (!col) throw new Error(`Column "${table}"."${column}" not found in destination contract`);
|
|
92
146
|
const mutableHooks = ctx.codecHooks;
|
|
93
147
|
const mutableTypes = ctx.storageTypes;
|
|
@@ -98,8 +152,8 @@ function buildColumnSpec(table, column, ctx, overrides) {
|
|
|
98
152
|
nullable: overrides?.nullable ?? col.nullable
|
|
99
153
|
};
|
|
100
154
|
}
|
|
101
|
-
function buildAlterTypeOptions(table, column, ctx, using) {
|
|
102
|
-
const col = ctx.toContract.storage
|
|
155
|
+
function buildAlterTypeOptions(namespaceId, table, column, ctx, using) {
|
|
156
|
+
const col = tableAt(ctx.toContract.storage, namespaceId, table)?.columns[column];
|
|
103
157
|
if (!col) throw new Error(`Column "${table}"."${column}" not found in destination contract`);
|
|
104
158
|
const mutableHooks = ctx.codecHooks;
|
|
105
159
|
const mutableTypes = ctx.storageTypes;
|
|
@@ -117,12 +171,14 @@ const notNullBackfillCallStrategy = (issues, ctx) => {
|
|
|
117
171
|
const calls = [];
|
|
118
172
|
for (const issue of issues) {
|
|
119
173
|
if (issue.kind !== "missing_column" || !issue.table || !issue.column) continue;
|
|
120
|
-
const
|
|
174
|
+
const namespaceId = resolveNamespaceIdForIssue(issue);
|
|
175
|
+
const column = tableAt(ctx.toContract.storage, namespaceId, issue.table)?.columns[issue.column];
|
|
121
176
|
if (!column) continue;
|
|
122
177
|
if (column.nullable === true || column.default !== void 0) continue;
|
|
123
178
|
matched.push(issue);
|
|
124
|
-
const spec = buildColumnSpec(issue.table, issue.column, ctx, { nullable: true });
|
|
125
|
-
|
|
179
|
+
const spec = buildColumnSpec(namespaceId, issue.table, issue.column, ctx, { nullable: true });
|
|
180
|
+
const schemaForTable = resolveDdlSchemaForNamespace(ctx, namespaceId);
|
|
181
|
+
calls.push(new AddColumnCall(schemaForTable, issue.table, spec), new DataTransformCall(`backfill-${issue.table}-${issue.column}`, `backfill-${issue.table}-${issue.column}:check`, `backfill-${issue.table}-${issue.column}:run`), new SetNotNullCall(schemaForTable, issue.table, issue.column));
|
|
126
182
|
}
|
|
127
183
|
if (matched.length === 0) return { kind: "no_match" };
|
|
128
184
|
return {
|
|
@@ -145,8 +201,9 @@ const typeChangeCallStrategy = (issues, ctx) => {
|
|
|
145
201
|
for (const issue of issues) {
|
|
146
202
|
if (issue.kind !== "type_mismatch") continue;
|
|
147
203
|
if (!issue.table || !issue.column) continue;
|
|
148
|
-
const
|
|
149
|
-
const
|
|
204
|
+
const namespaceId = resolveNamespaceIdForIssue(issue);
|
|
205
|
+
const fromColumn = ctx.fromContract ? tableAt(ctx.fromContract.storage, namespaceId, issue.table)?.columns[issue.column] : void 0;
|
|
206
|
+
const toColumn = tableAt(ctx.toContract.storage, namespaceId, issue.table)?.columns[issue.column];
|
|
150
207
|
if (!fromColumn || !toColumn) continue;
|
|
151
208
|
const fromType = fromColumn.nativeType;
|
|
152
209
|
const toType = toColumn.nativeType;
|
|
@@ -154,9 +211,10 @@ const typeChangeCallStrategy = (issues, ctx) => {
|
|
|
154
211
|
const isSafeWidening = SAFE_WIDENINGS.has(`${fromType}→${toType}`);
|
|
155
212
|
if (!isSafeWidening && !dataAllowed) continue;
|
|
156
213
|
matched.push(issue);
|
|
157
|
-
const alterOpts = buildAlterTypeOptions(issue.table, issue.column, ctx);
|
|
158
|
-
|
|
159
|
-
|
|
214
|
+
const alterOpts = buildAlterTypeOptions(namespaceId, issue.table, issue.column, ctx);
|
|
215
|
+
const schemaForTable = resolveDdlSchemaForNamespace(ctx, namespaceId);
|
|
216
|
+
if (isSafeWidening) calls.push(new AlterColumnTypeCall(schemaForTable, issue.table, issue.column, alterOpts));
|
|
217
|
+
else calls.push(new DataTransformCall(`typechange-${issue.table}-${issue.column}`, `typechange-${issue.table}-${issue.column}:check`, `typechange-${issue.table}-${issue.column}:run`), new AlterColumnTypeCall(schemaForTable, issue.table, issue.column, alterOpts));
|
|
160
218
|
}
|
|
161
219
|
if (matched.length === 0) return { kind: "no_match" };
|
|
162
220
|
return {
|
|
@@ -172,11 +230,13 @@ const nullableTighteningCallStrategy = (issues, ctx) => {
|
|
|
172
230
|
const calls = [];
|
|
173
231
|
for (const issue of issues) {
|
|
174
232
|
if (issue.kind !== "nullability_mismatch" || !issue.table || !issue.column) continue;
|
|
175
|
-
const
|
|
233
|
+
const namespaceId = resolveNamespaceIdForIssue(issue);
|
|
234
|
+
const column = tableAt(ctx.toContract.storage, namespaceId, issue.table)?.columns[issue.column];
|
|
176
235
|
if (!column) continue;
|
|
177
236
|
if (column.nullable === true) continue;
|
|
178
237
|
matched.push(issue);
|
|
179
|
-
|
|
238
|
+
const schemaForTable = resolveDdlSchemaForNamespace(ctx, namespaceId);
|
|
239
|
+
calls.push(new DataTransformCall(`handle-nulls-${issue.table}-${issue.column}`, `handle-nulls-${issue.table}-${issue.column}:check`, `handle-nulls-${issue.table}-${issue.column}:run`), new SetNotNullCall(schemaForTable, issue.table, issue.column));
|
|
180
240
|
}
|
|
181
241
|
if (matched.length === 0) return { kind: "no_match" };
|
|
182
242
|
return {
|
|
@@ -187,22 +247,26 @@ const nullableTighteningCallStrategy = (issues, ctx) => {
|
|
|
187
247
|
};
|
|
188
248
|
};
|
|
189
249
|
function enumRebuildCallRecipe(typeName, ctx) {
|
|
190
|
-
const toType = ctx.toContract.storage
|
|
250
|
+
const toType = locateNamespaceType(ctx.toContract.storage, typeName);
|
|
191
251
|
if (!toType) return [];
|
|
192
252
|
const isEnum = isPostgresEnumStorageEntry(toType);
|
|
193
253
|
const nativeType = toType.nativeType;
|
|
194
254
|
const desiredValues = isEnum ? toType.values : toType.typeParams["values"] ?? [];
|
|
195
255
|
const tempName = `${nativeType}${REBUILD_SUFFIX}`;
|
|
196
256
|
const columnRefs = [];
|
|
197
|
-
for (const [
|
|
198
|
-
table
|
|
199
|
-
column
|
|
200
|
-
|
|
257
|
+
for (const [nsId, ns] of Object.entries(ctx.toContract.storage.namespaces)) for (const [tableName, tableNode] of Object.entries(ns.tables)) {
|
|
258
|
+
const table = tableNode;
|
|
259
|
+
for (const [columnName, column] of Object.entries(table.columns)) if (column.typeRef === typeName) columnRefs.push({
|
|
260
|
+
namespaceId: nsId,
|
|
261
|
+
table: tableName,
|
|
262
|
+
column: columnName
|
|
263
|
+
});
|
|
264
|
+
}
|
|
201
265
|
return [
|
|
202
266
|
new CreateEnumTypeCall(ctx.schemaName, tempName, desiredValues),
|
|
203
267
|
...columnRefs.map((ref) => {
|
|
204
268
|
const using = `${ref.column}::text::${tempName}`;
|
|
205
|
-
return new AlterColumnTypeCall(ctx.
|
|
269
|
+
return new AlterColumnTypeCall(resolveDdlSchemaForNamespace(ctx, ref.namespaceId), ref.table, ref.column, {
|
|
206
270
|
qualifiedTargetType: tempName,
|
|
207
271
|
formatTypeExpected: tempName,
|
|
208
272
|
rawTargetTypeForLabel: tempName,
|
|
@@ -246,7 +310,7 @@ function enumRebuildCallRecipe(typeName, ctx) {
|
|
|
246
310
|
* `CreateTableCall` that references the new enum.
|
|
247
311
|
*/
|
|
248
312
|
const nativeEnumPlanCallStrategy = (issues, ctx) => {
|
|
249
|
-
const enumTypes = collectPostgresEnumTypes(ctx.toContract.storage
|
|
313
|
+
const enumTypes = collectPostgresEnumTypes(ctx.toContract.storage);
|
|
250
314
|
if (enumTypes.size === 0) return { kind: "no_match" };
|
|
251
315
|
const dataAllowed = ctx.policy.allowedOperationClasses.includes("data");
|
|
252
316
|
const calls = [];
|
|
@@ -289,9 +353,13 @@ const nativeEnumPlanCallStrategy = (issues, ctx) => {
|
|
|
289
353
|
recipe: emittedRebuildRecipe
|
|
290
354
|
};
|
|
291
355
|
};
|
|
292
|
-
function collectPostgresEnumTypes(
|
|
356
|
+
function collectPostgresEnumTypes(storage) {
|
|
293
357
|
const result = /* @__PURE__ */ new Map();
|
|
294
|
-
for (const
|
|
358
|
+
for (const ns of Object.values(storage.namespaces)) {
|
|
359
|
+
if (!("types" in ns) || ns.types == null) continue;
|
|
360
|
+
const nsTypes = ns.types;
|
|
361
|
+
for (const [name, instance] of Object.entries(nsTypes).sort(([a], [b]) => a.localeCompare(b))) if (instance instanceof PostgresEnumType) result.set(name, instance);
|
|
362
|
+
}
|
|
295
363
|
return result;
|
|
296
364
|
}
|
|
297
365
|
/**
|
|
@@ -362,7 +430,8 @@ const notNullAddColumnCallStrategy = (issues, ctx) => {
|
|
|
362
430
|
const mutableStorageTypes = ctx.storageTypes;
|
|
363
431
|
for (const issue of issues) {
|
|
364
432
|
if (issue.kind !== "missing_column" || !issue.table || !issue.column) continue;
|
|
365
|
-
const
|
|
433
|
+
const namespaceId = resolveNamespaceIdForIssue(issue);
|
|
434
|
+
const contractTable = tableAt(ctx.toContract.storage, namespaceId, issue.table);
|
|
366
435
|
const column = contractTable?.columns[issue.column];
|
|
367
436
|
if (!column) continue;
|
|
368
437
|
const notNull = column.nullable !== true;
|
|
@@ -379,9 +448,10 @@ const notNullAddColumnCallStrategy = (issues, ctx) => {
|
|
|
379
448
|
columnName: issue.column
|
|
380
449
|
});
|
|
381
450
|
matched.push(issue);
|
|
451
|
+
const schemaForTable = resolveDdlSchemaForNamespace(ctx, namespaceId);
|
|
382
452
|
if (canUseSharedTempDefault && temporaryDefault !== null) {
|
|
383
453
|
calls.push(new RawSqlCall(buildAddNotNullColumnWithTemporaryDefaultOperation({
|
|
384
|
-
schema:
|
|
454
|
+
schema: schemaForTable,
|
|
385
455
|
tableName: issue.table,
|
|
386
456
|
columnName: issue.column,
|
|
387
457
|
column,
|
|
@@ -391,14 +461,14 @@ const notNullAddColumnCallStrategy = (issues, ctx) => {
|
|
|
391
461
|
})));
|
|
392
462
|
continue;
|
|
393
463
|
}
|
|
394
|
-
const qualified = qualifyTableName(
|
|
464
|
+
const qualified = qualifyTableName(schemaForTable, issue.table);
|
|
395
465
|
calls.push(new RawSqlCall({
|
|
396
|
-
...buildAddColumnOperationIdentity(
|
|
466
|
+
...buildAddColumnOperationIdentity(schemaForTable, issue.table, issue.column),
|
|
397
467
|
operationClass: "additive",
|
|
398
468
|
precheck: [{
|
|
399
469
|
description: `ensure column "${issue.column}" is missing`,
|
|
400
470
|
sql: columnExistsCheck({
|
|
401
|
-
schema:
|
|
471
|
+
schema: schemaForTable,
|
|
402
472
|
table: issue.table,
|
|
403
473
|
column: issue.column,
|
|
404
474
|
exists: false
|
|
@@ -414,14 +484,14 @@ const notNullAddColumnCallStrategy = (issues, ctx) => {
|
|
|
414
484
|
postcheck: [{
|
|
415
485
|
description: `verify column "${issue.column}" exists`,
|
|
416
486
|
sql: columnExistsCheck({
|
|
417
|
-
schema:
|
|
487
|
+
schema: schemaForTable,
|
|
418
488
|
table: issue.table,
|
|
419
489
|
column: issue.column
|
|
420
490
|
})
|
|
421
491
|
}, {
|
|
422
492
|
description: `verify column "${issue.column}" is NOT NULL`,
|
|
423
493
|
sql: columnNullabilityCheck({
|
|
424
|
-
schema:
|
|
494
|
+
schema: schemaForTable,
|
|
425
495
|
table: issue.table,
|
|
426
496
|
column: issue.column,
|
|
427
497
|
nullable: false
|
|
@@ -444,7 +514,7 @@ function canUseSharedTemporaryDefaultStrategy(options) {
|
|
|
444
514
|
if (!schemaLookup || !hasUniqueConstraint(schemaLookup, unique.columns)) return false;
|
|
445
515
|
}
|
|
446
516
|
for (const foreignKey of table.foreignKeys) {
|
|
447
|
-
if (foreignKey.constraint === false || !foreignKey.columns.includes(columnName)) continue;
|
|
517
|
+
if (foreignKey.constraint === false || !foreignKey.source.columns.includes(columnName)) continue;
|
|
448
518
|
if (!schemaLookup || !hasForeignKey(schemaLookup, foreignKey)) return false;
|
|
449
519
|
}
|
|
450
520
|
return true;
|
|
@@ -489,7 +559,15 @@ const postgresPlannerStrategies = [
|
|
|
489
559
|
];
|
|
490
560
|
//#endregion
|
|
491
561
|
//#region src/core/migrations/issue-planner.ts
|
|
562
|
+
function locateNamespaceTypeInStorage(storage, typeName) {
|
|
563
|
+
for (const ns of Object.values(storage.namespaces)) {
|
|
564
|
+
if (!("types" in ns) || ns.types == null) continue;
|
|
565
|
+
const entry = ns.types[typeName];
|
|
566
|
+
if (entry !== void 0) return entry;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
492
569
|
const ISSUE_KIND_ORDER = {
|
|
570
|
+
missing_schema: 1,
|
|
493
571
|
type_missing: 2,
|
|
494
572
|
type_values_mismatch: 3,
|
|
495
573
|
enum_values_changed: 3,
|
|
@@ -536,79 +614,94 @@ function toColumnSpec(name, column, codecHooks, storageTypes) {
|
|
|
536
614
|
}
|
|
537
615
|
function mapIssueToCall(issue, ctx) {
|
|
538
616
|
const { schemaName, codecHooks, storageTypes } = ctx;
|
|
617
|
+
const tableSchema = (issue) => {
|
|
618
|
+
if (issue.kind === "extra_table") return schemaName;
|
|
619
|
+
if (!("table" in issue) || !issue.table) return schemaName;
|
|
620
|
+
return resolveDdlSchemaForNamespace(ctx, resolveNamespaceIdForIssue(issue));
|
|
621
|
+
};
|
|
539
622
|
switch (issue.kind) {
|
|
623
|
+
case "missing_schema": {
|
|
624
|
+
const namespaceId = issue.namespaceId;
|
|
625
|
+
if (!namespaceId) return notOk(issueConflict("unsupportedOperation", "Missing schema issue has no namespaceId"));
|
|
626
|
+
return ok([new CreateSchemaCall(resolveDdlSchemaForNamespace(ctx, namespaceId))]);
|
|
627
|
+
}
|
|
540
628
|
case "missing_table": {
|
|
541
629
|
if (!issue.table) return notOk(issueConflict("unsupportedOperation", "Missing table issue has no table name"));
|
|
542
|
-
const
|
|
543
|
-
|
|
630
|
+
const namespaceId = resolveNamespaceIdForIssue(issue);
|
|
631
|
+
const contractTable = tableAt(ctx.toContract.storage, namespaceId, issue.table);
|
|
632
|
+
if (!contractTable) return notOk(issueConflict("unsupportedOperation", `Table "${issue.table}" in namespace "${namespaceId}" reported missing but not found in destination contract`));
|
|
633
|
+
const schemaForTable = tableSchema(issue);
|
|
544
634
|
const columns = Object.entries(contractTable.columns).map(([name, column]) => toColumnSpec(name, column, codecHooks, storageTypes));
|
|
545
635
|
const primaryKey = contractTable.primaryKey ? { columns: contractTable.primaryKey.columns } : void 0;
|
|
546
|
-
const calls = [new CreateTableCall(
|
|
636
|
+
const calls = [new CreateTableCall(schemaForTable, issue.table, columns, primaryKey)];
|
|
547
637
|
for (const index of contractTable.indexes) {
|
|
548
638
|
const indexName = index.name ?? `${issue.table}_${index.columns.join("_")}_idx`;
|
|
549
639
|
const extras = {};
|
|
550
640
|
if (index.type !== void 0) extras.type = index.type;
|
|
551
641
|
if (index.options !== void 0) extras.options = index.options;
|
|
552
|
-
calls.push(new CreateIndexCall(
|
|
642
|
+
calls.push(new CreateIndexCall(schemaForTable, issue.table, indexName, [...index.columns], extras));
|
|
553
643
|
}
|
|
554
644
|
const explicitIndexColumnSets = new Set(contractTable.indexes.map((idx) => idx.columns.join(",")));
|
|
555
645
|
for (const fk of contractTable.foreignKeys) {
|
|
556
646
|
if (fk.constraint) {
|
|
557
647
|
const fkSpec = {
|
|
558
|
-
name: fk.name ?? `${issue.table}_${fk.columns.join("_")}_fkey`,
|
|
559
|
-
columns: fk.columns,
|
|
648
|
+
name: fk.name ?? `${issue.table}_${fk.source.columns.join("_")}_fkey`,
|
|
649
|
+
columns: fk.source.columns,
|
|
560
650
|
references: {
|
|
561
|
-
|
|
562
|
-
|
|
651
|
+
schema: fk.target.namespaceId,
|
|
652
|
+
table: fk.target.tableName,
|
|
653
|
+
columns: fk.target.columns
|
|
563
654
|
},
|
|
564
655
|
...fk.onDelete !== void 0 && { onDelete: fk.onDelete },
|
|
565
656
|
...fk.onUpdate !== void 0 && { onUpdate: fk.onUpdate }
|
|
566
657
|
};
|
|
567
|
-
calls.push(new AddForeignKeyCall(
|
|
658
|
+
calls.push(new AddForeignKeyCall(schemaForTable, issue.table, fkSpec));
|
|
568
659
|
}
|
|
569
|
-
if (fk.index && !explicitIndexColumnSets.has(fk.columns.join(","))) {
|
|
570
|
-
const indexName = `${issue.table}_${fk.columns.join("_")}_idx`;
|
|
571
|
-
calls.push(new CreateIndexCall(
|
|
660
|
+
if (fk.index && !explicitIndexColumnSets.has(fk.source.columns.join(","))) {
|
|
661
|
+
const indexName = `${issue.table}_${fk.source.columns.join("_")}_idx`;
|
|
662
|
+
calls.push(new CreateIndexCall(schemaForTable, issue.table, indexName, [...fk.source.columns]));
|
|
572
663
|
}
|
|
573
664
|
}
|
|
574
665
|
for (const unique of contractTable.uniques) {
|
|
575
666
|
const constraintName = unique.name ?? `${issue.table}_${unique.columns.join("_")}_key`;
|
|
576
|
-
calls.push(new AddUniqueCall(
|
|
667
|
+
calls.push(new AddUniqueCall(schemaForTable, issue.table, constraintName, [...unique.columns]));
|
|
577
668
|
}
|
|
578
669
|
return ok(calls);
|
|
579
670
|
}
|
|
580
671
|
case "missing_column":
|
|
581
672
|
if (!issue.table || !issue.column) return notOk(issueConflict("unsupportedOperation", "Missing column issue has no table/column name"));
|
|
582
673
|
{
|
|
583
|
-
const
|
|
674
|
+
const namespaceId = resolveNamespaceIdForIssue(issue);
|
|
675
|
+
const column = tableAt(ctx.toContract.storage, namespaceId, issue.table)?.columns[issue.column];
|
|
584
676
|
if (!column) return notOk(issueConflict("unsupportedOperation", `Column "${issue.table}"."${issue.column}" not in destination contract`));
|
|
585
|
-
return ok([new AddColumnCall(
|
|
677
|
+
return ok([new AddColumnCall(tableSchema(issue), issue.table, toColumnSpec(issue.column, column, codecHooks, storageTypes))]);
|
|
586
678
|
}
|
|
587
679
|
case "default_missing":
|
|
588
680
|
if (!issue.table || !issue.column) return notOk(issueConflict("unsupportedOperation", "Default missing issue has no table/column name"));
|
|
589
681
|
{
|
|
590
|
-
const
|
|
682
|
+
const namespaceId = resolveNamespaceIdForIssue(issue);
|
|
683
|
+
const column = tableAt(ctx.toContract.storage, namespaceId, issue.table)?.columns[issue.column];
|
|
591
684
|
if (!column?.default) return notOk(issueConflict("unsupportedOperation", `Column "${issue.table}"."${issue.column}" has no default in contract`));
|
|
592
685
|
const defaultSql = buildColumnDefaultSql(column.default, column);
|
|
593
686
|
if (!defaultSql) return ok([]);
|
|
594
|
-
return ok([new SetDefaultCall(
|
|
687
|
+
return ok([new SetDefaultCall(tableSchema(issue), issue.table, issue.column, defaultSql)]);
|
|
595
688
|
}
|
|
596
689
|
case "extra_table":
|
|
597
690
|
if (!issue.table) return notOk(issueConflict("unsupportedOperation", "Extra table issue has no table name"));
|
|
598
|
-
return ok([new DropTableCall(
|
|
691
|
+
return ok([new DropTableCall(tableSchema(issue), issue.table)]);
|
|
599
692
|
case "extra_column":
|
|
600
693
|
if (!issue.table || !issue.column) return notOk(issueConflict("unsupportedOperation", "Extra column issue has no table/column name"));
|
|
601
|
-
return ok([new DropColumnCall(
|
|
694
|
+
return ok([new DropColumnCall(tableSchema(issue), issue.table, issue.column)]);
|
|
602
695
|
case "extra_index":
|
|
603
696
|
if (!issue.table || !issue.indexOrConstraint) return notOk(issueConflict("unsupportedOperation", "Extra index issue has no table/index name"));
|
|
604
|
-
return ok([new DropIndexCall(
|
|
697
|
+
return ok([new DropIndexCall(tableSchema(issue), issue.table, issue.indexOrConstraint)]);
|
|
605
698
|
case "extra_unique_constraint":
|
|
606
699
|
case "extra_foreign_key":
|
|
607
700
|
case "extra_primary_key": {
|
|
608
701
|
if (!issue.table) return notOk(issueConflict("unsupportedOperation", "Extra constraint issue has no table/constraint name"));
|
|
609
702
|
const constraintName = issue.indexOrConstraint ?? (issue.kind === "extra_primary_key" ? `${issue.table}_pkey` : void 0);
|
|
610
703
|
if (!constraintName) return notOk(issueConflict("unsupportedOperation", "Extra constraint issue has no table/constraint name"));
|
|
611
|
-
return ok([new DropConstraintCall(
|
|
704
|
+
return ok([new DropConstraintCall(tableSchema(issue), issue.table, constraintName, {
|
|
612
705
|
extra_unique_constraint: "unique",
|
|
613
706
|
extra_foreign_key: "foreignKey",
|
|
614
707
|
extra_primary_key: "primaryKey"
|
|
@@ -616,23 +709,26 @@ function mapIssueToCall(issue, ctx) {
|
|
|
616
709
|
}
|
|
617
710
|
case "extra_default":
|
|
618
711
|
if (!issue.table || !issue.column) return notOk(issueConflict("unsupportedOperation", "Extra default issue has no table/column name"));
|
|
619
|
-
return ok([new DropDefaultCall(
|
|
712
|
+
return ok([new DropDefaultCall(tableSchema(issue), issue.table, issue.column)]);
|
|
620
713
|
case "nullability_mismatch": {
|
|
621
714
|
if (!issue.table || !issue.column) return notOk(issueConflict("nullabilityConflict", "Nullability mismatch has no table/column name"));
|
|
622
|
-
const
|
|
715
|
+
const namespaceId = resolveNamespaceIdForIssue(issue);
|
|
716
|
+
const column = tableAt(ctx.toContract.storage, namespaceId, issue.table)?.columns[issue.column];
|
|
623
717
|
if (!column) return notOk(issueConflict("nullabilityConflict", `Column "${issue.table}"."${issue.column}" not found in destination contract`));
|
|
624
|
-
|
|
718
|
+
const schemaForTable = tableSchema(issue);
|
|
719
|
+
return ok(column.nullable ? [new DropNotNullCall(schemaForTable, issue.table, issue.column)] : [new SetNotNullCall(schemaForTable, issue.table, issue.column)]);
|
|
625
720
|
}
|
|
626
721
|
case "type_mismatch":
|
|
627
722
|
if (!issue.table || !issue.column) return notOk(issueConflict("typeMismatch", "Type mismatch has no table/column name"));
|
|
628
723
|
{
|
|
629
|
-
const
|
|
724
|
+
const namespaceId = resolveNamespaceIdForIssue(issue);
|
|
725
|
+
const column = tableAt(ctx.toContract.storage, namespaceId, issue.table)?.columns[issue.column];
|
|
630
726
|
if (!column) return notOk(issueConflict("typeMismatch", `Column "${issue.table}"."${issue.column}" not in destination contract`));
|
|
631
727
|
const hooksMap = codecHooks;
|
|
632
728
|
const typesMap = storageTypes;
|
|
633
729
|
const qualifiedTargetType = buildColumnTypeSql(column, hooksMap, typesMap, false);
|
|
634
730
|
const formatTypeExpected = buildExpectedFormatType(column, hooksMap, typesMap);
|
|
635
|
-
return ok([new AlterColumnTypeCall(
|
|
731
|
+
return ok([new AlterColumnTypeCall(tableSchema(issue), issue.table, issue.column, {
|
|
636
732
|
qualifiedTargetType,
|
|
637
733
|
formatTypeExpected,
|
|
638
734
|
rawTargetTypeForLabel: qualifiedTargetType
|
|
@@ -641,19 +737,21 @@ function mapIssueToCall(issue, ctx) {
|
|
|
641
737
|
case "default_mismatch":
|
|
642
738
|
if (!issue.table || !issue.column) return notOk(issueConflict("unsupportedOperation", "Default mismatch has no table/column name"));
|
|
643
739
|
{
|
|
644
|
-
const
|
|
740
|
+
const namespaceId = resolveNamespaceIdForIssue(issue);
|
|
741
|
+
const column = tableAt(ctx.toContract.storage, namespaceId, issue.table)?.columns[issue.column];
|
|
645
742
|
if (!column?.default) return ok([]);
|
|
646
743
|
const defaultSql = buildColumnDefaultSql(column.default, column);
|
|
647
744
|
if (!defaultSql) return ok([]);
|
|
648
|
-
return ok([new SetDefaultCall(
|
|
745
|
+
return ok([new SetDefaultCall(tableSchema(issue), issue.table, issue.column, defaultSql, "widening")]);
|
|
649
746
|
}
|
|
650
747
|
case "primary_key_mismatch":
|
|
651
748
|
if (!issue.table) return notOk(issueConflict("indexIncompatible", "Primary key issue has no table name"));
|
|
652
749
|
if (isMissing(issue)) {
|
|
653
|
-
const
|
|
750
|
+
const namespaceId = resolveNamespaceIdForIssue(issue);
|
|
751
|
+
const pk = tableAt(ctx.toContract.storage, namespaceId, issue.table)?.primaryKey;
|
|
654
752
|
if (!pk) return notOk(issueConflict("indexIncompatible", `No primary key in contract for "${issue.table}"`));
|
|
655
753
|
const constraintName = pk.name ?? `${issue.table}_pkey`;
|
|
656
|
-
return ok([new AddPrimaryKeyCall(
|
|
754
|
+
return ok([new AddPrimaryKeyCall(tableSchema(issue), issue.table, constraintName, pk.columns)]);
|
|
657
755
|
}
|
|
658
756
|
return notOk(issueConflict("indexIncompatible", `Primary key on "${issue.table}" has different columns (expected: ${issue.expected}, actual: ${issue.actual})`, { table: issue.table }));
|
|
659
757
|
case "unique_constraint_mismatch":
|
|
@@ -661,19 +759,20 @@ function mapIssueToCall(issue, ctx) {
|
|
|
661
759
|
if (isMissing(issue) && issue.expected) {
|
|
662
760
|
const columns = issue.expected.split(", ");
|
|
663
761
|
const constraintName = `${issue.table}_${columns.join("_")}_key`;
|
|
664
|
-
return ok([new AddUniqueCall(
|
|
762
|
+
return ok([new AddUniqueCall(tableSchema(issue), issue.table, constraintName, columns)]);
|
|
665
763
|
}
|
|
666
764
|
return notOk(issueConflict("indexIncompatible", `Unique constraint on "${issue.table}" differs (expected: ${issue.expected}, actual: ${issue.actual})`, { table: issue.table }));
|
|
667
765
|
case "index_mismatch":
|
|
668
766
|
if (!issue.table) return notOk(issueConflict("indexIncompatible", "Index issue has no table name"));
|
|
669
767
|
if (isMissing(issue) && issue.expected) {
|
|
768
|
+
const namespaceId = resolveNamespaceIdForIssue(issue);
|
|
670
769
|
const columns = issue.expected.split(", ");
|
|
671
|
-
const contractIndex = ctx.toContract.storage
|
|
770
|
+
const contractIndex = tableAt(ctx.toContract.storage, namespaceId, issue.table)?.indexes.find((idx) => arraysEqual(idx.columns, columns));
|
|
672
771
|
const indexName = contractIndex?.name ?? `${issue.table}_${columns.join("_")}_idx`;
|
|
673
772
|
const extras = {};
|
|
674
773
|
if (contractIndex?.type !== void 0) extras.type = contractIndex.type;
|
|
675
774
|
if (contractIndex?.options !== void 0) extras.options = contractIndex.options;
|
|
676
|
-
return ok([new CreateIndexCall(
|
|
775
|
+
return ok([new CreateIndexCall(tableSchema(issue), issue.table, indexName, columns, extras)]);
|
|
677
776
|
}
|
|
678
777
|
return notOk(issueConflict("indexIncompatible", `Index on "${issue.table}" differs (expected: ${issue.expected}, actual: ${issue.actual})`, { table: issue.table }));
|
|
679
778
|
case "foreign_key_mismatch":
|
|
@@ -681,21 +780,23 @@ function mapIssueToCall(issue, ctx) {
|
|
|
681
780
|
if (isMissing(issue) && issue.expected) {
|
|
682
781
|
const arrowIdx = issue.expected.indexOf(" -> ");
|
|
683
782
|
if (arrowIdx >= 0) {
|
|
783
|
+
const namespaceId = resolveNamespaceIdForIssue(issue);
|
|
684
784
|
const columns = issue.expected.slice(0, arrowIdx).split(", ");
|
|
685
785
|
const fkName = `${issue.table}_${columns.join("_")}_fkey`;
|
|
686
|
-
const fk = ctx.toContract.storage
|
|
786
|
+
const fk = tableAt(ctx.toContract.storage, namespaceId, issue.table)?.foreignKeys.find((k) => k.source.columns.join(", ") === columns.join(", "));
|
|
687
787
|
if (fk) {
|
|
688
788
|
const fkSpec = {
|
|
689
789
|
name: fkName,
|
|
690
|
-
columns: fk.columns,
|
|
790
|
+
columns: fk.source.columns,
|
|
691
791
|
references: {
|
|
692
|
-
|
|
693
|
-
|
|
792
|
+
schema: fk.target.namespaceId,
|
|
793
|
+
table: fk.target.tableName,
|
|
794
|
+
columns: fk.target.columns
|
|
694
795
|
},
|
|
695
796
|
...fk.onDelete !== void 0 && { onDelete: fk.onDelete },
|
|
696
797
|
...fk.onUpdate !== void 0 && { onUpdate: fk.onUpdate }
|
|
697
798
|
};
|
|
698
|
-
return ok([new AddForeignKeyCall(
|
|
799
|
+
return ok([new AddForeignKeyCall(tableSchema(issue), issue.table, fkSpec)]);
|
|
699
800
|
}
|
|
700
801
|
return notOk(issueConflict("foreignKeyConflict", `Foreign key on "${issue.table}" (${columns.join(", ")}) not found in destination contract`, { table: issue.table }));
|
|
701
802
|
}
|
|
@@ -703,10 +804,11 @@ function mapIssueToCall(issue, ctx) {
|
|
|
703
804
|
return notOk(issueConflict("foreignKeyConflict", `Foreign key on "${issue.table}" differs (expected: ${issue.expected}, actual: ${issue.actual})`, { table: issue.table }));
|
|
704
805
|
case "type_missing": {
|
|
705
806
|
if (!issue.typeName) return notOk(issueConflict("unsupportedOperation", "Type missing issue has no typeName"));
|
|
706
|
-
const typeInstance = ctx.toContract.storage.types?.[issue.typeName];
|
|
807
|
+
const typeInstance = ctx.toContract.storage.types?.[issue.typeName] ?? locateNamespaceTypeInStorage(ctx.toContract.storage, issue.typeName);
|
|
707
808
|
if (!typeInstance) return notOk(issueConflict("unsupportedOperation", `Type "${issue.typeName}" reported missing but not found in destination contract`));
|
|
708
809
|
if (typeInstance instanceof PostgresEnumType) return ok([new CreateEnumTypeCall(schemaName, issue.typeName, typeInstance.values, typeInstance.nativeType)]);
|
|
709
|
-
|
|
810
|
+
const codecInstance = typeInstance;
|
|
811
|
+
return notOk(issueConflict("unsupportedOperation", `Type "${issue.typeName}" uses codec "${codecInstance.codecId}" — only enum types are supported`));
|
|
710
812
|
}
|
|
711
813
|
case "type_values_mismatch": return notOk(issueConflict("unsupportedOperation", `Type "${issue.typeName ?? "unknown"}" values differ — type alteration not yet supported`));
|
|
712
814
|
default: return notOk(issueConflict("unsupportedOperation", `Unhandled issue kind: ${issue.kind}`));
|
|
@@ -874,4 +976,4 @@ function planIssues(options) {
|
|
|
874
976
|
//#endregion
|
|
875
977
|
export { postgresPlannerStrategies as n, planIssues as t };
|
|
876
978
|
|
|
877
|
-
//# sourceMappingURL=issue-planner-
|
|
979
|
+
//# sourceMappingURL=issue-planner-qalHRCI2.mjs.map
|