@prisma/orm-family-sql 8.0.0-rc.16-dev.5 → 8.0.0-rc.16-dev.7
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-type-constructors-dihiQslc-S4oVeeaO.mjs → authoring-type-constructors-0Iv2zdwS-CVl4womm.mjs} +14 -4
- package/dist/authoring-type-constructors-0Iv2zdwS-CVl4womm.mjs.map +1 -0
- package/dist/{config-types-C-fKlHmB.mjs → config-types-DeIF6WyF.mjs} +2 -2
- package/dist/{config-types-C-fKlHmB.mjs.map → config-types-DeIF6WyF.mjs.map} +1 -1
- package/dist/{contract-builder-BxkBHQir.mjs → contract-builder-BlFrYr97.mjs} +2 -2
- package/dist/{contract-builder-BxkBHQir.mjs.map → contract-builder-BlFrYr97.mjs.map} +1 -1
- package/dist/contract-prisma7__provider.mjs +3 -3
- package/dist/contract-psl.mjs +1 -1
- package/dist/contract-psl__attribute-specs.mjs +1 -1
- package/dist/contract-psl__provider.mjs +2 -2
- package/dist/contract-ts.mjs +3 -3
- package/dist/contract-ts__config-types.mjs +1 -1
- package/dist/contract-ts__contract-builder.mjs +2 -2
- package/dist/{control-DCt08EpW.d.mts → control-BT0wr9QC.d.mts} +193 -56
- package/dist/{control-DCt08EpW.d.mts.map → control-BT0wr9QC.d.mts.map} +1 -1
- package/dist/{control-0kB6FkCn.mjs → control-C4VZIU-L.mjs} +457 -123
- package/dist/control-C4VZIU-L.mjs.map +1 -0
- package/dist/{derived-checks-DAbro9yn-BNuE2QEm.mjs → derived-checks-DdguQPYm-BP57ljP8.mjs} +16 -10
- package/dist/{derived-checks-DAbro9yn-BNuE2QEm.mjs.map → derived-checks-DdguQPYm-BP57ljP8.mjs.map} +1 -1
- package/dist/{diff-3tfqwWS7.d.mts → diff-DMOqiT2h.d.mts} +2 -2
- package/dist/{diff-3tfqwWS7.d.mts.map → diff-DMOqiT2h.d.mts.map} +1 -1
- package/dist/family.d.mts +5 -5
- package/dist/family.mjs +3 -3
- package/dist/family__control.d.mts +3 -3
- package/dist/family__control.mjs +2 -2
- package/dist/family__diff.d.mts +1 -1
- package/dist/family__migration.d.mts +1 -1
- package/dist/family__migration.mjs +1 -1
- package/dist/family__pack.mjs +2 -2
- package/dist/family__pack.mjs.map +1 -1
- package/dist/{interpreter-BF5Xrf3W-DOTOXsEr.mjs → interpreter-BF5Xrf3W-bdklH78q.mjs} +3 -3
- package/dist/{interpreter-BF5Xrf3W-DOTOXsEr.mjs.map → interpreter-BF5Xrf3W-bdklH78q.mjs.map} +1 -1
- package/dist/{migration-D6NJlA6-.d.mts → migration-C5HGygKM.d.mts} +3 -3
- package/dist/{migration-D6NJlA6-.d.mts.map → migration-C5HGygKM.d.mts.map} +1 -1
- package/dist/{migration-CK4oePIo.mjs → migration-Dy_4Wmiy.mjs} +3 -3
- package/dist/{migration-CK4oePIo.mjs.map → migration-Dy_4Wmiy.mjs.map} +1 -1
- package/dist/{psl-field-resolution-DUCrDnuq-BYapcETh.mjs → psl-field-resolution-DUCrDnuq-DSxPrd-4.mjs} +2 -2
- package/dist/{psl-field-resolution-DUCrDnuq-BYapcETh.mjs.map → psl-field-resolution-DUCrDnuq-DSxPrd-4.mjs.map} +1 -1
- package/dist/{types-CvuS68sy-ReNXbgpE.d.mts → types-CzxOObSY-CNWyrf87.d.mts} +12 -8
- package/dist/{types-CvuS68sy-ReNXbgpE.d.mts.map → types-CzxOObSY-CNWyrf87.d.mts.map} +1 -1
- package/package.json +18 -18
- package/dist/authoring-type-constructors-dihiQslc-S4oVeeaO.mjs.map +0 -1
- package/dist/control-0kB6FkCn.mjs.map +0 -1
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { u as namingOf } from "./naming-DkG_OegU-DpENNdZX.mjs";
|
|
2
2
|
import { t as sqlContractCanonicalizationHooks } from "./canonicalization-hooks-dmXkOR4a.mjs";
|
|
3
3
|
import { a as renderSqlTypeName, l as sqlDataTypeOfCodec, t as dataTypeParams, u as unquotedSqlBaseName } from "./data-type-CAPmGXg9.mjs";
|
|
4
|
-
import { c as StorageTable
|
|
4
|
+
import { c as StorageTable } from "./storage-table-CyL4CNMi-ByGZXmzd.mjs";
|
|
5
5
|
import { a as sqlExpressionAuthoringEntry, o as sqlExpressionDataType, t as SQL_EXPRESSION_DATA_TYPE_ID } from "./sql-expression-D7GsLgDM.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import { u as isStorageTypeInstance } from "./types-DDHgx581.mjs";
|
|
7
7
|
import { m as valueObjectStorageTypeMissingMessage } from "./validators-Xx-TKcx3.mjs";
|
|
8
8
|
import { c as SqlSchemaIR, n as RelationalSchemaNodeKind, u as SqlTableIR } from "./types-Cz_bcUWN-CC3lFQOi.mjs";
|
|
9
|
-
import { a as describeUnsupportedSqlAttribute, b as sqlAttributeSpecs } from "./psl-field-resolution-DUCrDnuq-
|
|
9
|
+
import { a as describeUnsupportedSqlAttribute, b as sqlAttributeSpecs } from "./psl-field-resolution-DUCrDnuq-DSxPrd-4.mjs";
|
|
10
10
|
import { t as sqlEmission } from "./dist-7hmkNQGd.mjs";
|
|
11
|
-
import { i as sqlFamilyPslBlockDescriptors, n as sqlFamilyAuthoringTypes, r as sqlFamilyEntityTypes, t as sqlFamilyAuthoringFieldPresets } from "./authoring-type-constructors-
|
|
11
|
+
import { i as sqlFamilyPslBlockDescriptors, n as sqlFamilyAuthoringTypes, r as sqlFamilyEntityTypes, t as sqlFamilyAuthoringFieldPresets } from "./authoring-type-constructors-0Iv2zdwS-CVl4womm.mjs";
|
|
12
12
|
import { c as verifySqlSchemaByDiff, n as classifyDiffSubjectGranularity, o as enforceSqlDataTypeInvariants, t as classifyDiffEntityKind } from "./schema-verify-DIfHSB4I-CjYnmUuD.mjs";
|
|
13
13
|
import { t as sqlFamilyError } from "./errors-B5g0xWro-mWH2C07F.mjs";
|
|
14
14
|
import { t as SqlContractSerializer } from "./sql-contract-serializer-DDaAVCQr-CLDkZLXO.mjs";
|
|
@@ -22,7 +22,7 @@ import { blindCast } from "@prisma/orm-framework/utils/casts";
|
|
|
22
22
|
import { ifDefined } from "@prisma/orm-framework/utils/defined";
|
|
23
23
|
import { InternalError } from "@prisma/orm-framework/utils/internal-error";
|
|
24
24
|
import { effectiveControlPolicy } from "@prisma/orm-framework/contract/types";
|
|
25
|
-
import { APP_SPACE_ID, SchemaTreeNode, VERIFY_CODE_HASH_MISMATCH, VERIFY_CODE_MARKER_MISSING, VERIFY_CODE_TARGET_MISMATCH, assembleAuthoringContributions, extractCodecLookup, issueOutcome, sameMarkerHashes } from "@prisma/orm-framework/components/control";
|
|
25
|
+
import { APP_SPACE_ID, SchemaTreeNode, VERIFY_CODE_HASH_MISMATCH, VERIFY_CODE_MARKER_MISSING, VERIFY_CODE_TARGET_MISMATCH, assembleAuthoringContributions, describeMigrationStatement, extractCodecLookup, issueOutcome, modelDisplayName, sameMarkerHashes } from "@prisma/orm-framework/components/control";
|
|
26
26
|
import { notOk, ok } from "@prisma/orm-framework/utils/result";
|
|
27
27
|
import { assertDescriptorSelfConsistency } from "@prisma/orm-toolchain/migration-tools/spaces";
|
|
28
28
|
//#region ../../../2-sql/9-family/dist/control.mjs
|
|
@@ -652,118 +652,6 @@ var SqlFamilyDescriptor = class {
|
|
|
652
652
|
return createSqlFamilyInstance(stack);
|
|
653
653
|
}
|
|
654
654
|
};
|
|
655
|
-
const TABLE_RENAME_UNMATCHED_CODE = "MIGRATION.TABLE_RENAME_UNMATCHED";
|
|
656
|
-
function tableLabel(namespaceId, tableName) {
|
|
657
|
-
return namespaceId === void 0 || namespaceId === UNBOUND_NAMESPACE_ID ? tableName : `${namespaceId}.${tableName}`;
|
|
658
|
-
}
|
|
659
|
-
function namespacesDeclaring(contract, tableName) {
|
|
660
|
-
return Object.values(contract.storage.namespaces).filter((namespace) => Object.hasOwn(namespace.entries.table ?? {}, tableName)).map((namespace) => namespace.id);
|
|
661
|
-
}
|
|
662
|
-
function declares(contract, namespaceId, tableName) {
|
|
663
|
-
return Object.hasOwn(contract.storage.namespaces[namespaceId]?.entries.table ?? {}, tableName);
|
|
664
|
-
}
|
|
665
|
-
function unmatched(rename, reason) {
|
|
666
|
-
return sqlFamilyError(TABLE_RENAME_UNMATCHED_CODE, `renameTable "${tableLabel(rename.namespaceId, rename.from)}" to "${rename.to}" does not match the migration's contracts: ${reason}.`, {
|
|
667
|
-
why: "renameTable must name a table of the migration's start contract and a new name that the end contract has and the start contract does not. Make the rename its own schema change, so the migration's start contract is the schema before the rename and its end contract the schema after it, and check the spelling and the namespace.",
|
|
668
|
-
meta: {
|
|
669
|
-
from: rename.from,
|
|
670
|
-
to: rename.to
|
|
671
|
-
}
|
|
672
|
-
});
|
|
673
|
-
}
|
|
674
|
-
function resolveTableRename(rename, startContract, endContract) {
|
|
675
|
-
const namespaceIds = rename.namespaceId === void 0 ? namespacesDeclaring(startContract, rename.from) : declares(startContract, rename.namespaceId, rename.from) ? [rename.namespaceId] : [];
|
|
676
|
-
const [namespaceId, ...others] = namespaceIds;
|
|
677
|
-
if (namespaceId === void 0) return notOk(unmatched(rename, `table "${tableLabel(rename.namespaceId, rename.from)}" does not exist in the start contract`));
|
|
678
|
-
if (others.length > 0) return notOk(unmatched(rename, `table "${rename.from}" is declared in more than one namespace (${namespaceIds.join(", ")}); name its namespace`));
|
|
679
|
-
if (declares(startContract, namespaceId, rename.to)) return notOk(unmatched(rename, `table "${tableLabel(namespaceId, rename.to)}" already exists in the start contract`));
|
|
680
|
-
if (!declares(endContract, namespaceId, rename.to)) return notOk(unmatched(rename, `table "${tableLabel(namespaceId, rename.to)}" does not exist in the end contract`));
|
|
681
|
-
return ok({
|
|
682
|
-
namespaceId,
|
|
683
|
-
from: rename.from,
|
|
684
|
-
to: rename.to
|
|
685
|
-
});
|
|
686
|
-
}
|
|
687
|
-
function renamedReference(reference, rename) {
|
|
688
|
-
if (!(reference.spaceId === void 0) || reference.namespaceId !== rename.namespaceId || reference.tableName !== rename.from) return reference;
|
|
689
|
-
return {
|
|
690
|
-
...reference,
|
|
691
|
-
tableName: rename.to
|
|
692
|
-
};
|
|
693
|
-
}
|
|
694
|
-
function renameForeignKeys(table, rename) {
|
|
695
|
-
if (!table.foreignKeys.some((fk) => renamedReference(fk.source, rename) !== fk.source || renamedReference(fk.target, rename) !== fk.target)) return table;
|
|
696
|
-
return new StorageTable({
|
|
697
|
-
...table,
|
|
698
|
-
foreignKeys: table.foreignKeys.map((fk) => new ForeignKey({
|
|
699
|
-
...fk,
|
|
700
|
-
source: renamedReference(fk.source, rename),
|
|
701
|
-
target: renamedReference(fk.target, rename)
|
|
702
|
-
}))
|
|
703
|
-
});
|
|
704
|
-
}
|
|
705
|
-
/**
|
|
706
|
-
* The same namespace instance with only `entries` replaced: every own
|
|
707
|
-
* property, including the non-enumerable `kind`, is carried over onto the
|
|
708
|
-
* same prototype, so the target's namespace class (its `qualifyTable`,
|
|
709
|
-
* `ddlSchemaName`, entity getters) keeps working on the copy. This is the
|
|
710
|
-
* one place a frozen contract node is rebuilt without its constructor: the
|
|
711
|
-
* constructors re-hydrate `entries` from raw input, which the already
|
|
712
|
-
* hydrated entities here do not need.
|
|
713
|
-
*/
|
|
714
|
-
function withEntries(namespace, entries) {
|
|
715
|
-
const copy = Object.create(Object.getPrototypeOf(namespace), {
|
|
716
|
-
...Object.getOwnPropertyDescriptors(namespace),
|
|
717
|
-
entries: {
|
|
718
|
-
value: Object.freeze(entries),
|
|
719
|
-
enumerable: true,
|
|
720
|
-
writable: false,
|
|
721
|
-
configurable: false
|
|
722
|
-
}
|
|
723
|
-
});
|
|
724
|
-
return Object.freeze(copy);
|
|
725
|
-
}
|
|
726
|
-
function renameTableInNamespace(namespace, rename, renameTableReferences) {
|
|
727
|
-
const ownsTable = rename.namespaceId === namespace.id;
|
|
728
|
-
const tables = Object.entries(namespace.entries.table ?? {}).map(([name, table]) => [ownsTable && name === rename.from ? rename.to : name, renameForeignKeys(table, rename)]);
|
|
729
|
-
if (tables.every(([name, table]) => namespace.entries.table?.[name] === table)) return namespace;
|
|
730
|
-
if (!isMaterializedSqlNamespace(namespace)) throw new InternalError(`applyTableRename: namespace "${namespace.id}" is not a materialized SQL namespace`);
|
|
731
|
-
const renamedTables = {
|
|
732
|
-
...namespace.entries,
|
|
733
|
-
table: Object.fromEntries(tables)
|
|
734
|
-
};
|
|
735
|
-
return withEntries(namespace, renameTableReferences === void 0 || !ownsTable ? renamedTables : renameTableReferences(renamedTables, rename));
|
|
736
|
-
}
|
|
737
|
-
function renameTableInContract(contract, rename, renameTableReferences) {
|
|
738
|
-
const namespaces = Object.fromEntries(Object.entries(contract.storage.namespaces).map(([id, namespace]) => [id, renameTableInNamespace(namespace, rename, renameTableReferences)]));
|
|
739
|
-
const materialized = {};
|
|
740
|
-
for (const [id, namespace] of Object.entries(namespaces)) {
|
|
741
|
-
if (!isMaterializedSqlNamespace(namespace)) throw new InternalError(`applyTableRename: namespace "${id}" is not a materialized SQL namespace`);
|
|
742
|
-
materialized[id] = namespace;
|
|
743
|
-
}
|
|
744
|
-
return {
|
|
745
|
-
...contract,
|
|
746
|
-
storage: new SqlStorage({
|
|
747
|
-
storageHash: contract.storage.storageHash,
|
|
748
|
-
...contract.storage.types === void 0 ? {} : { types: contract.storage.types },
|
|
749
|
-
namespaces: materialized
|
|
750
|
-
})
|
|
751
|
-
};
|
|
752
|
-
}
|
|
753
|
-
/**
|
|
754
|
-
* Resolves the table a migration renames against its start and end contracts and returns the start contract with that table under its new name, so a diff against the end contract sees the table under one name. The table must exist in the start contract (in exactly one namespace when the namespace is not given), and the new name must exist in the end contract and not in the start contract; otherwise the rename is refused with `MIGRATION.TABLE_RENAME_UNMATCHED`.
|
|
755
|
-
*
|
|
756
|
-
* Foreign keys that name the renamed table on either side are retargeted. Index, unique, check and primary-key names are carried unchanged. Target entity kinds that name the table are renamed by the target's `renameTableReferences`.
|
|
757
|
-
*/
|
|
758
|
-
function applyTableRename(input) {
|
|
759
|
-
if (input.startContract === null) return notOk(unmatched(input.rename, "the migration has no start contract"));
|
|
760
|
-
const resolved = resolveTableRename(input.rename, input.startContract, input.endContract);
|
|
761
|
-
if (!resolved.ok) return resolved;
|
|
762
|
-
return ok({
|
|
763
|
-
contract: renameTableInContract(input.startContract, resolved.value, input.renameTableReferences),
|
|
764
|
-
rename: resolved.value
|
|
765
|
-
});
|
|
766
|
-
}
|
|
767
655
|
function convertColumn(name, column, storageTypes, types, renderDefault, resolveDefault) {
|
|
768
656
|
const resolved = resolveColumnTypeMetadata(column, storageTypes);
|
|
769
657
|
const dataType = sqlDataTypeOfCodec(resolved.codecId, types);
|
|
@@ -1207,6 +1095,9 @@ function subjectKey(subject) {
|
|
|
1207
1095
|
function planFieldEventOperations(options) {
|
|
1208
1096
|
const priorContract = options.priorContract;
|
|
1209
1097
|
const newContract = options.newContract;
|
|
1098
|
+
const renamedTo = new Map(options.tableRenames.map((rename) => [renameKey(rename.namespaceId, rename.from), rename.to]));
|
|
1099
|
+
const newNameOf = (namespaceId, tableName) => renamedTo.get(renameKey(namespaceId, tableName));
|
|
1100
|
+
const columnRenamedTo = new Map(options.columnRenames.map((rename) => [renameKey(rename.namespaceId, rename.table, rename.from), rename.to]));
|
|
1210
1101
|
const added = [];
|
|
1211
1102
|
const dropped = [];
|
|
1212
1103
|
const altered = [];
|
|
@@ -1214,7 +1105,7 @@ function planFieldEventOperations(options) {
|
|
|
1214
1105
|
for (const namespaceId of namespaceIds) {
|
|
1215
1106
|
const priorNs = priorContract?.storage.namespaces[namespaceId];
|
|
1216
1107
|
const newNs = newContract.storage.namespaces[namespaceId];
|
|
1217
|
-
const priorTables = priorNs?.entries.table;
|
|
1108
|
+
const priorTables = underNewNames(priorNs?.entries.table, (tableName) => newNameOf(namespaceId, tableName));
|
|
1218
1109
|
const newTables = newNs?.entries.table;
|
|
1219
1110
|
const tableNames = unionSorted(priorTables ? Object.keys(priorTables) : [], newTables ? Object.keys(newTables) : []);
|
|
1220
1111
|
for (const tableName of tableNames) {
|
|
@@ -1222,9 +1113,10 @@ function planFieldEventOperations(options) {
|
|
|
1222
1113
|
const newTableRaw = newTables?.[tableName];
|
|
1223
1114
|
const priorTable = StorageTable.is(priorTableRaw) ? priorTableRaw : void 0;
|
|
1224
1115
|
const newTable = StorageTable.is(newTableRaw) ? newTableRaw : void 0;
|
|
1225
|
-
const
|
|
1116
|
+
const priorColumns = underNewNames(priorTable?.columns, (columnName) => columnRenamedTo.get(renameKey(namespaceId, tableName, columnName)));
|
|
1117
|
+
const fieldNames = unionSorted(priorColumns ? Object.keys(priorColumns) : [], newTable ? Object.keys(newTable.columns) : []);
|
|
1226
1118
|
for (const fieldName of fieldNames) {
|
|
1227
|
-
const priorField =
|
|
1119
|
+
const priorField = priorColumns?.[fieldName];
|
|
1228
1120
|
const newField = newTable?.columns[fieldName];
|
|
1229
1121
|
const entry = {
|
|
1230
1122
|
namespaceId,
|
|
@@ -1249,6 +1141,13 @@ function planFieldEventOperations(options) {
|
|
|
1249
1141
|
appendCalls("altered", altered, options.codecHooks, calls, (e) => e.newField?.codecId);
|
|
1250
1142
|
return calls;
|
|
1251
1143
|
}
|
|
1144
|
+
function renameKey(...parts) {
|
|
1145
|
+
return JSON.stringify(parts);
|
|
1146
|
+
}
|
|
1147
|
+
function underNewNames(tables, newNameOf) {
|
|
1148
|
+
if (tables === void 0) return void 0;
|
|
1149
|
+
return Object.fromEntries(Object.entries(tables).map(([tableName, table]) => [newNameOf(tableName) ?? tableName, table]));
|
|
1150
|
+
}
|
|
1252
1151
|
function appendCalls(event, entries, codecHooks, calls, pickCodecId) {
|
|
1253
1152
|
for (const entry of entries) {
|
|
1254
1153
|
const codecId = pickCodecId(entry);
|
|
@@ -1381,15 +1280,18 @@ function createMigrationPlan(options) {
|
|
|
1381
1280
|
...options.meta ? { meta: cloneRecord(options.meta) } : {}
|
|
1382
1281
|
});
|
|
1383
1282
|
}
|
|
1384
|
-
function plannerSuccess(plan, warnings) {
|
|
1283
|
+
function plannerSuccess(plan, appliedStatements, warnings) {
|
|
1385
1284
|
return Object.freeze({
|
|
1386
1285
|
kind: "success",
|
|
1387
1286
|
plan,
|
|
1287
|
+
appliedStatements: Object.freeze([...appliedStatements]),
|
|
1388
1288
|
...warnings && warnings.length > 0 ? { warnings: Object.freeze(warnings.map((conflict) => Object.freeze({
|
|
1389
1289
|
kind: conflict.kind,
|
|
1390
1290
|
summary: conflict.summary,
|
|
1391
1291
|
...conflict.why ? { why: conflict.why } : {},
|
|
1392
1292
|
...conflict.location ? { location: Object.freeze({ ...conflict.location }) } : {},
|
|
1293
|
+
...conflict.refusedStatement ? { refusedStatement: conflict.refusedStatement } : {},
|
|
1294
|
+
...conflict.refusedOperationClass ? { refusedOperationClass: conflict.refusedOperationClass } : {},
|
|
1393
1295
|
...conflict.meta ? { meta: cloneRecord(conflict.meta) } : {}
|
|
1394
1296
|
}))) } : {}
|
|
1395
1297
|
});
|
|
@@ -1402,6 +1304,8 @@ function plannerFailure(conflicts) {
|
|
|
1402
1304
|
summary: conflict.summary,
|
|
1403
1305
|
...conflict.why ? { why: conflict.why } : {},
|
|
1404
1306
|
...conflict.location ? { location: Object.freeze({ ...conflict.location }) } : {},
|
|
1307
|
+
...conflict.refusedStatement ? { refusedStatement: conflict.refusedStatement } : {},
|
|
1308
|
+
...conflict.refusedOperationClass ? { refusedOperationClass: conflict.refusedOperationClass } : {},
|
|
1405
1309
|
...conflict.meta ? { meta: cloneRecord(conflict.meta) } : {}
|
|
1406
1310
|
})))
|
|
1407
1311
|
});
|
|
@@ -1430,6 +1334,150 @@ function runnerFailure(code, summary, options) {
|
|
|
1430
1334
|
* Policy used by `db init`: additive-only operations, no widening/destructive steps.
|
|
1431
1335
|
*/
|
|
1432
1336
|
const INIT_ADDITIVE_POLICY = Object.freeze({ allowedOperationClasses: Object.freeze(["additive"]) });
|
|
1337
|
+
const COLUMN_RENAME_UNMATCHED_CODE = "MIGRATION.COLUMN_RENAME_UNMATCHED";
|
|
1338
|
+
function tableLabel$1(namespaceId, table) {
|
|
1339
|
+
return namespaceId === void 0 || namespaceId === UNBOUND_NAMESPACE_ID ? table : `${namespaceId}.${table}`;
|
|
1340
|
+
}
|
|
1341
|
+
function columnLabel(namespaceId, table, column) {
|
|
1342
|
+
return `"${tableLabel$1(namespaceId, table)}"."${column}"`;
|
|
1343
|
+
}
|
|
1344
|
+
function declaresColumn(contract, namespaceId, table, column) {
|
|
1345
|
+
const columns = contract.storage.namespaces[namespaceId]?.entries.table?.[table]?.columns;
|
|
1346
|
+
return columns !== void 0 && Object.hasOwn(columns, column);
|
|
1347
|
+
}
|
|
1348
|
+
/**
|
|
1349
|
+
* Refuses a `renameColumn` call that does not match the migration's contracts, with
|
|
1350
|
+
* `MIGRATION.COLUMN_RENAME_UNMATCHED`.
|
|
1351
|
+
*/
|
|
1352
|
+
function unmatchedColumnRename(rename, reason) {
|
|
1353
|
+
return sqlFamilyError(COLUMN_RENAME_UNMATCHED_CODE, `renameColumn ${columnLabel(rename.namespaceId, rename.table, rename.from)} to "${rename.to}" does not match the migration's contracts: ${reason}.`, {
|
|
1354
|
+
why: "renameColumn must name a table and a column as the migration's earlier rename operations leave them, and a new column name that the end contract has on that table and that the table does not have yet. Order the rename calls in the sequence the renames happen, and check the names of the table, the column and the namespace.",
|
|
1355
|
+
meta: {
|
|
1356
|
+
table: rename.table,
|
|
1357
|
+
from: rename.from,
|
|
1358
|
+
to: rename.to
|
|
1359
|
+
}
|
|
1360
|
+
});
|
|
1361
|
+
}
|
|
1362
|
+
/**
|
|
1363
|
+
* Checks a column rename: the table must exist in `previous` (in exactly one namespace when the
|
|
1364
|
+
* namespace is not given) with the old column and without the new one, and the end contract must
|
|
1365
|
+
* have the new column on that table.
|
|
1366
|
+
*/
|
|
1367
|
+
function checkColumnRename(previous, endContract, rename) {
|
|
1368
|
+
const namespaceIds = rename.namespaceId === void 0 ? previous.namespacesWithTable(rename.table) : previous.hasTable(rename.namespaceId, rename.table) ? [rename.namespaceId] : [];
|
|
1369
|
+
const [namespaceId, ...others] = namespaceIds;
|
|
1370
|
+
if (namespaceId === void 0) return notOk({ kind: "tableMissing" });
|
|
1371
|
+
if (others.length > 0) return notOk({
|
|
1372
|
+
kind: "tableInManyNamespaces",
|
|
1373
|
+
namespaceIds
|
|
1374
|
+
});
|
|
1375
|
+
if (!previous.hasColumn(namespaceId, rename.table, rename.from)) return notOk({
|
|
1376
|
+
kind: "columnMissing",
|
|
1377
|
+
namespaceId
|
|
1378
|
+
});
|
|
1379
|
+
const [taken] = previous.columnsNamed(namespaceId, rename.table, rename.to).filter((column) => column !== rename.from);
|
|
1380
|
+
if (taken !== void 0) return notOk({
|
|
1381
|
+
kind: "nameTaken",
|
|
1382
|
+
namespaceId,
|
|
1383
|
+
taken
|
|
1384
|
+
});
|
|
1385
|
+
if (!declaresColumn(endContract, namespaceId, rename.table, rename.to)) return notOk({
|
|
1386
|
+
kind: "notInEndContract",
|
|
1387
|
+
namespaceId
|
|
1388
|
+
});
|
|
1389
|
+
return ok({
|
|
1390
|
+
namespaceId,
|
|
1391
|
+
table: rename.table,
|
|
1392
|
+
from: rename.from,
|
|
1393
|
+
to: rename.to
|
|
1394
|
+
});
|
|
1395
|
+
}
|
|
1396
|
+
/** The reason `MIGRATION.COLUMN_RENAME_UNMATCHED` gives for a mismatch. */
|
|
1397
|
+
function columnRenameMismatchReason(rename, mismatch) {
|
|
1398
|
+
switch (mismatch.kind) {
|
|
1399
|
+
case "tableMissing": return `table "${tableLabel$1(rename.namespaceId, rename.table)}" does not exist at this point of the migration`;
|
|
1400
|
+
case "tableInManyNamespaces": return `table "${rename.table}" is declared in more than one namespace (${mismatch.namespaceIds.join(", ")}); name its namespace`;
|
|
1401
|
+
case "columnMissing": return `column ${columnLabel(mismatch.namespaceId, rename.table, rename.from)} does not exist at this point of the migration`;
|
|
1402
|
+
case "nameTaken": return `column ${columnLabel(mismatch.namespaceId, rename.table, rename.to)} already exists at this point of the migration${mismatch.taken === rename.to ? "" : ` as "${mismatch.taken}"`}`;
|
|
1403
|
+
case "notInEndContract": return `column ${columnLabel(mismatch.namespaceId, rename.table, rename.to)} does not exist in the end contract`;
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
/**
|
|
1407
|
+
* Resolves a column a migration renames with {@link checkColumnRename}, refusing a mismatch with
|
|
1408
|
+
* `MIGRATION.COLUMN_RENAME_UNMATCHED`.
|
|
1409
|
+
*/
|
|
1410
|
+
function resolveColumnRenameAgainst(previous, endContract, rename) {
|
|
1411
|
+
const checked = checkColumnRename(previous, endContract, rename);
|
|
1412
|
+
if (!checked.ok) return notOk(unmatchedColumnRename(rename, columnRenameMismatchReason(rename, checked.failure)));
|
|
1413
|
+
return ok(checked.value);
|
|
1414
|
+
}
|
|
1415
|
+
const TABLE_RENAME_UNMATCHED_CODE = "MIGRATION.TABLE_RENAME_UNMATCHED";
|
|
1416
|
+
function tableLabel(namespaceId, tableName) {
|
|
1417
|
+
return namespaceId === void 0 || namespaceId === UNBOUND_NAMESPACE_ID ? tableName : `${namespaceId}.${tableName}`;
|
|
1418
|
+
}
|
|
1419
|
+
function declares(contract, namespaceId, tableName) {
|
|
1420
|
+
return Object.hasOwn(contract.storage.namespaces[namespaceId]?.entries.table ?? {}, tableName);
|
|
1421
|
+
}
|
|
1422
|
+
/**
|
|
1423
|
+
* Refuses a `renameTable` call that does not match the migration's contracts, with
|
|
1424
|
+
* `MIGRATION.TABLE_RENAME_UNMATCHED`.
|
|
1425
|
+
*/
|
|
1426
|
+
function unmatchedTableRename(rename, reason) {
|
|
1427
|
+
return sqlFamilyError(TABLE_RENAME_UNMATCHED_CODE, `renameTable "${tableLabel(rename.namespaceId, rename.from)}" to "${rename.to}" does not match the migration's contracts: ${reason}.`, {
|
|
1428
|
+
why: "renameTable must name a table as the migration's earlier rename operations leave it, and a new name that the end contract has and that no earlier rename operation has already produced. Order the renameTable calls in the sequence the renames happen, make the rename its own schema change, and check the spelling, the table and the namespace.",
|
|
1429
|
+
meta: {
|
|
1430
|
+
from: rename.from,
|
|
1431
|
+
to: rename.to
|
|
1432
|
+
}
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1435
|
+
/**
|
|
1436
|
+
* Checks a table rename: the table must exist in `previous` (in exactly one namespace when the
|
|
1437
|
+
* namespace is not given), and the new name must exist in the end contract and not in `previous`.
|
|
1438
|
+
*/
|
|
1439
|
+
function checkTableRename(previous, endContract, rename) {
|
|
1440
|
+
const namespaceIds = rename.namespaceId === void 0 ? previous.namespacesWithTable(rename.from) : previous.hasTable(rename.namespaceId, rename.from) ? [rename.namespaceId] : [];
|
|
1441
|
+
const [namespaceId, ...others] = namespaceIds;
|
|
1442
|
+
if (namespaceId === void 0) return notOk({ kind: "tableMissing" });
|
|
1443
|
+
if (others.length > 0) return notOk({
|
|
1444
|
+
kind: "tableInManyNamespaces",
|
|
1445
|
+
namespaceIds
|
|
1446
|
+
});
|
|
1447
|
+
const [taken] = previous.tablesNamed(namespaceId, rename.to).filter((table) => table !== rename.from);
|
|
1448
|
+
if (taken !== void 0) return notOk({
|
|
1449
|
+
kind: "nameTaken",
|
|
1450
|
+
namespaceId,
|
|
1451
|
+
taken
|
|
1452
|
+
});
|
|
1453
|
+
if (!declares(endContract, namespaceId, rename.to)) return notOk({
|
|
1454
|
+
kind: "notInEndContract",
|
|
1455
|
+
namespaceId
|
|
1456
|
+
});
|
|
1457
|
+
return ok({
|
|
1458
|
+
namespaceId,
|
|
1459
|
+
from: rename.from,
|
|
1460
|
+
to: rename.to
|
|
1461
|
+
});
|
|
1462
|
+
}
|
|
1463
|
+
/** The reason `MIGRATION.TABLE_RENAME_UNMATCHED` gives for a mismatch. */
|
|
1464
|
+
function tableRenameMismatchReason(rename, mismatch) {
|
|
1465
|
+
switch (mismatch.kind) {
|
|
1466
|
+
case "tableMissing": return `table "${tableLabel(rename.namespaceId, rename.from)}" does not exist at this point of the migration`;
|
|
1467
|
+
case "tableInManyNamespaces": return `table "${rename.from}" is declared in more than one namespace (${mismatch.namespaceIds.join(", ")}); name its namespace`;
|
|
1468
|
+
case "nameTaken": return `table "${tableLabel(mismatch.namespaceId, rename.to)}" already exists at this point of the migration${mismatch.taken === rename.to ? "" : ` as "${mismatch.taken}"`}`;
|
|
1469
|
+
case "notInEndContract": return `table "${tableLabel(mismatch.namespaceId, rename.to)}" does not exist in the end contract`;
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
/**
|
|
1473
|
+
* Resolves a table a migration renames with {@link checkTableRename}, refusing a mismatch with
|
|
1474
|
+
* `MIGRATION.TABLE_RENAME_UNMATCHED`.
|
|
1475
|
+
*/
|
|
1476
|
+
function resolveTableRenameAgainst(previous, endContract, rename) {
|
|
1477
|
+
const checked = checkTableRename(previous, endContract, rename);
|
|
1478
|
+
if (!checked.ok) return notOk(unmatchedTableRename(rename, tableRenameMismatchReason(rename, checked.failure)));
|
|
1479
|
+
return ok(checked.value);
|
|
1480
|
+
}
|
|
1433
1481
|
/** The codecs and data types a set of composed components registers. */
|
|
1434
1482
|
function sqlTypeLookupsOf(frameworkComponents) {
|
|
1435
1483
|
return {
|
|
@@ -1437,6 +1485,292 @@ function sqlTypeLookupsOf(frameworkComponents) {
|
|
|
1437
1485
|
dataTypeLookup: assembleDataTypes(frameworkComponents).lookup
|
|
1438
1486
|
};
|
|
1439
1487
|
}
|
|
1488
|
+
function isSqlModelStorage(storage) {
|
|
1489
|
+
return typeof storage["table"] === "string" && typeof storage["namespaceId"] === "string" && typeof storage["fields"] === "object" && storage["fields"] !== null;
|
|
1490
|
+
}
|
|
1491
|
+
/** The storage of a model the contract stores in a table, or `undefined` for any other model. */
|
|
1492
|
+
function sqlModelStorage(contract, coordinate) {
|
|
1493
|
+
const storage = contract.domain.namespaces[coordinate.namespaceId]?.models[coordinate.model]?.storage;
|
|
1494
|
+
return storage !== void 0 && isSqlModelStorage(storage) ? storage : void 0;
|
|
1495
|
+
}
|
|
1496
|
+
function modelTable(contract, coordinate) {
|
|
1497
|
+
const storage = sqlModelStorage(contract, coordinate);
|
|
1498
|
+
return storage === void 0 ? void 0 : {
|
|
1499
|
+
namespaceId: storage.namespaceId,
|
|
1500
|
+
table: storage.table
|
|
1501
|
+
};
|
|
1502
|
+
}
|
|
1503
|
+
/**
|
|
1504
|
+
* The storage effect of a model rename: the origin model's table compared with the destination
|
|
1505
|
+
* model's. Equal tables mean the rename needs no storage change.
|
|
1506
|
+
*/
|
|
1507
|
+
function modelRenameStorageEffect(statement, fromContract, contract) {
|
|
1508
|
+
const from = modelTable(fromContract, statement.from);
|
|
1509
|
+
if (from === void 0) return notOk({
|
|
1510
|
+
kind: "noTable",
|
|
1511
|
+
model: statement.from
|
|
1512
|
+
});
|
|
1513
|
+
const to = modelTable(contract, statement.to);
|
|
1514
|
+
if (to === void 0) return notOk({
|
|
1515
|
+
kind: "noTable",
|
|
1516
|
+
model: statement.to
|
|
1517
|
+
});
|
|
1518
|
+
if (from.namespaceId !== to.namespaceId) return ok({
|
|
1519
|
+
kind: "moveNamespace",
|
|
1520
|
+
from,
|
|
1521
|
+
to
|
|
1522
|
+
});
|
|
1523
|
+
if (from.table === to.table) return ok({ kind: "unchanged" });
|
|
1524
|
+
return ok({
|
|
1525
|
+
kind: "renameTable",
|
|
1526
|
+
rename: {
|
|
1527
|
+
namespaceId: from.namespaceId,
|
|
1528
|
+
from: from.table,
|
|
1529
|
+
to: to.table
|
|
1530
|
+
}
|
|
1531
|
+
});
|
|
1532
|
+
}
|
|
1533
|
+
function fieldColumn(contract, coordinate) {
|
|
1534
|
+
const fields = sqlModelStorage(contract, coordinate)?.fields;
|
|
1535
|
+
return fields !== void 0 && Object.hasOwn(fields, coordinate.field) ? fields[coordinate.field]?.column : void 0;
|
|
1536
|
+
}
|
|
1537
|
+
/**
|
|
1538
|
+
* The storage effect of a field rename: the origin field's column compared with the destination
|
|
1539
|
+
* field's. A relation field has no column on either side, and equal columns need no change.
|
|
1540
|
+
*/
|
|
1541
|
+
function fieldRenameStorageEffect(statement, fromContract, contract) {
|
|
1542
|
+
const table = modelTable(fromContract, statement.from);
|
|
1543
|
+
if (table === void 0) return notOk({
|
|
1544
|
+
kind: "noTable",
|
|
1545
|
+
model: statement.from
|
|
1546
|
+
});
|
|
1547
|
+
const from = fieldColumn(fromContract, statement.from);
|
|
1548
|
+
const to = fieldColumn(contract, statement.to);
|
|
1549
|
+
if (from === void 0 && to === void 0) return ok({ kind: "unchanged" });
|
|
1550
|
+
if (from === void 0 || to === void 0) return notOk({ kind: "columnOnOneSide" });
|
|
1551
|
+
if (from === to) return ok({ kind: "unchanged" });
|
|
1552
|
+
return ok({
|
|
1553
|
+
kind: "renameColumn",
|
|
1554
|
+
table,
|
|
1555
|
+
from,
|
|
1556
|
+
to
|
|
1557
|
+
});
|
|
1558
|
+
}
|
|
1559
|
+
function operationsOf(call) {
|
|
1560
|
+
return [call, ...call.companions];
|
|
1561
|
+
}
|
|
1562
|
+
const DRIFTED = "so the database has drifted from that contract. Inspect it with prisma db schema, or leave out this statement.";
|
|
1563
|
+
const UNMATCHED = "A statement plans the rename a hand-written rename call makes, and that call does not match the contracts. Leave out this statement.";
|
|
1564
|
+
function statementRefused(statement, summary, why, location, refusedOperationClass) {
|
|
1565
|
+
return {
|
|
1566
|
+
kind: "statementRefused",
|
|
1567
|
+
summary,
|
|
1568
|
+
why,
|
|
1569
|
+
refusedStatement: statement,
|
|
1570
|
+
...refusedOperationClass === void 0 ? {} : { refusedOperationClass },
|
|
1571
|
+
...location === void 0 ? {} : { location: {
|
|
1572
|
+
namespaceId: location.namespaceId,
|
|
1573
|
+
entityKind: "table",
|
|
1574
|
+
entityName: location.table,
|
|
1575
|
+
...location.column === void 0 ? {} : { column: location.column }
|
|
1576
|
+
} }
|
|
1577
|
+
};
|
|
1578
|
+
}
|
|
1579
|
+
function tableControlPolicy(contract, table) {
|
|
1580
|
+
const node = contract.storage.namespaces[table.namespaceId]?.entries.table?.[table.table];
|
|
1581
|
+
return controlPolicyForCall({
|
|
1582
|
+
namespaceId: table.namespaceId,
|
|
1583
|
+
entityKind: "table",
|
|
1584
|
+
entityName: table.table,
|
|
1585
|
+
...StorageTable.is(node) && node.control !== void 0 ? { explicitNodeControlPolicy: node.control } : {},
|
|
1586
|
+
createsNewObject: false
|
|
1587
|
+
}, contract.defaultControlPolicy);
|
|
1588
|
+
}
|
|
1589
|
+
function tableKey(table) {
|
|
1590
|
+
return JSON.stringify([table.namespaceId, table.table]);
|
|
1591
|
+
}
|
|
1592
|
+
function tableRenameRefused(statement, label, rename, mismatch) {
|
|
1593
|
+
switch (mismatch.kind) {
|
|
1594
|
+
case "tableMissing": return statementRefused(statement, `${label}: the schema being planned from has no table "${rename.from}"`, `The database has no table "${rename.from}", although the contract it was last updated to names it, ${DRIFTED}`, {
|
|
1595
|
+
namespaceId: rename.namespaceId,
|
|
1596
|
+
table: rename.from
|
|
1597
|
+
});
|
|
1598
|
+
case "nameTaken": return statementRefused(statement, `${label}: the schema being planned from already has a table "${rename.to}"${mismatch.taken === rename.to ? "" : `, as "${mismatch.taken}"`}`, `A rename cannot replace a table that already exists. Rename or drop table "${mismatch.taken}" first, or leave out this statement.`, {
|
|
1599
|
+
namespaceId: rename.namespaceId,
|
|
1600
|
+
table: rename.to
|
|
1601
|
+
});
|
|
1602
|
+
case "tableInManyNamespaces":
|
|
1603
|
+
case "notInEndContract": return statementRefused(statement, `${label}: ${tableRenameMismatchReason(rename, mismatch)}`, UNMATCHED, {
|
|
1604
|
+
namespaceId: rename.namespaceId,
|
|
1605
|
+
table: rename.from
|
|
1606
|
+
});
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
function columnRenameRefused(statement, label, rename, mismatch) {
|
|
1610
|
+
const table = {
|
|
1611
|
+
namespaceId: rename.namespaceId,
|
|
1612
|
+
table: rename.table
|
|
1613
|
+
};
|
|
1614
|
+
switch (mismatch.kind) {
|
|
1615
|
+
case "tableMissing": return statementRefused(statement, `${label}: the schema being planned from has no table "${rename.table}"`, `The database has no table "${rename.table}", although the contract it was last updated to names it, ${DRIFTED}`, table);
|
|
1616
|
+
case "columnMissing": return statementRefused(statement, `${label}: the schema being planned from has no column "${rename.from}" on table "${rename.table}"`, `The database has no column "${rename.from}" on table "${rename.table}", although the contract it was last updated to names it, ${DRIFTED}`, {
|
|
1617
|
+
...table,
|
|
1618
|
+
column: rename.from
|
|
1619
|
+
});
|
|
1620
|
+
case "nameTaken": return statementRefused(statement, `${label}: the schema being planned from already has a column "${mismatch.taken}" on table "${rename.table}"`, `A rename cannot replace a column that already exists. Rename or drop column "${mismatch.taken}" of table "${rename.table}" first, or leave out this statement.`, {
|
|
1621
|
+
...table,
|
|
1622
|
+
column: rename.to
|
|
1623
|
+
});
|
|
1624
|
+
case "tableInManyNamespaces":
|
|
1625
|
+
case "notInEndContract": return statementRefused(statement, `${label}: ${columnRenameMismatchReason(rename, mismatch)}`, UNMATCHED, {
|
|
1626
|
+
...table,
|
|
1627
|
+
column: rename.from
|
|
1628
|
+
});
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
var StatementPlanner = class {
|
|
1632
|
+
#fromContract;
|
|
1633
|
+
#contract;
|
|
1634
|
+
#policy;
|
|
1635
|
+
#target;
|
|
1636
|
+
/** The name each table renamed so far has in the working schema, keyed by its origin name. */
|
|
1637
|
+
#renamedTables = /* @__PURE__ */ new Map();
|
|
1638
|
+
calls = [];
|
|
1639
|
+
/** How many operations the calls planned so far lower to. */
|
|
1640
|
+
#operationCount = 0;
|
|
1641
|
+
tableRenames = [];
|
|
1642
|
+
columnRenames = [];
|
|
1643
|
+
constructor(input) {
|
|
1644
|
+
this.#fromContract = input.fromContract;
|
|
1645
|
+
this.#contract = input.contract;
|
|
1646
|
+
this.#policy = input.policy;
|
|
1647
|
+
this.#target = input.target;
|
|
1648
|
+
}
|
|
1649
|
+
/** Plans one statement; the result is the positions of the operations it accounts for. */
|
|
1650
|
+
plan(statement) {
|
|
1651
|
+
return statement.entity === "model" ? this.#planModel(statement) : this.#planField(statement);
|
|
1652
|
+
}
|
|
1653
|
+
#controlPolicyRefusal(statement, label, destinationTable) {
|
|
1654
|
+
const controlPolicy = tableControlPolicy(this.#contract, destinationTable);
|
|
1655
|
+
if (controlPolicy === "managed") return void 0;
|
|
1656
|
+
return statementRefused(statement, `${label}: the table's control policy is "${controlPolicy}"`, `Statements rename only tables, and columns of tables, whose control policy is "managed"; table "${destinationTable.table}" is "${controlPolicy}". Make the change in the database yourself and leave out this statement.`, destinationTable);
|
|
1657
|
+
}
|
|
1658
|
+
#emit(statement, label, location, call) {
|
|
1659
|
+
const refused = operationsOf(call).map((operation) => operation.operationClass).find((operationClass) => !this.#policy.allowedOperationClasses.includes(operationClass));
|
|
1660
|
+
if (refused !== void 0) return notOk(statementRefused(statement, `${label}: the plan does not allow "${refused}" operations`, `The rename produces a "${refused}" operation, and this command plans only ${this.#policy.allowedOperationClasses.map((c) => `"${c}"`).join(", ")} operations. Leave out this statement, or make the change with a command that allows "${refused}" operations, such as migration plan.`, location, refused));
|
|
1661
|
+
this.#target.apply(call);
|
|
1662
|
+
this.calls.push(call);
|
|
1663
|
+
const first = this.#operationCount;
|
|
1664
|
+
this.#operationCount += operationsOf(call).length;
|
|
1665
|
+
return ok(operationsOf(call).map((_, offset) => first + offset));
|
|
1666
|
+
}
|
|
1667
|
+
#planModel(statement) {
|
|
1668
|
+
const worked = modelRenameStorageEffect(statement, this.#fromContract, this.#contract);
|
|
1669
|
+
if (!worked.ok) return notOk(statementRefused(statement, `Model "${modelDisplayName(worked.failure.model)}" has no table in its contract`, `A model rename renames the model's table, and model "${modelDisplayName(worked.failure.model)}" has none in its contract. Leave out this statement.`, void 0));
|
|
1670
|
+
const effect = worked.value;
|
|
1671
|
+
if (effect.kind === "unchanged") return ok([]);
|
|
1672
|
+
if (effect.kind === "moveNamespace") return notOk(statementRefused(statement, `Moving a model to another namespace is not supported in this release: "${modelDisplayName(statement.from)}" to "${modelDisplayName(statement.to)}"`, `The model's table would move from namespace "${effect.from.namespaceId}" to namespace "${effect.to.namespaceId}". Leave out this statement and move the table yourself in a hand-written migration, or keep the model in namespace "${effect.from.namespaceId}".`, effect.from));
|
|
1673
|
+
const { rename } = effect;
|
|
1674
|
+
const destinationTable = {
|
|
1675
|
+
namespaceId: rename.namespaceId,
|
|
1676
|
+
table: rename.to
|
|
1677
|
+
};
|
|
1678
|
+
const label = `Cannot rename table "${rename.from}" to "${rename.to}"`;
|
|
1679
|
+
const policyRefusal = this.#controlPolicyRefusal(statement, label, destinationTable);
|
|
1680
|
+
if (policyRefusal !== void 0) return notOk(policyRefusal);
|
|
1681
|
+
const checked = checkTableRename(this.#target.tables(), this.#contract, rename);
|
|
1682
|
+
if (!checked.ok) return notOk(tableRenameRefused(statement, label, rename, checked.failure));
|
|
1683
|
+
const planned = this.#emit(statement, label, destinationTable, this.#target.renameTableCall(rename));
|
|
1684
|
+
if (planned.ok) {
|
|
1685
|
+
this.tableRenames.push(rename);
|
|
1686
|
+
this.#renamedTables.set(tableKey({
|
|
1687
|
+
namespaceId: rename.namespaceId,
|
|
1688
|
+
table: rename.from
|
|
1689
|
+
}), rename.to);
|
|
1690
|
+
}
|
|
1691
|
+
return planned;
|
|
1692
|
+
}
|
|
1693
|
+
#planField(statement) {
|
|
1694
|
+
const worked = fieldRenameStorageEffect(statement, this.#fromContract, this.#contract);
|
|
1695
|
+
if (!worked.ok && worked.failure.kind === "noTable") return notOk(statementRefused(statement, `Model "${modelDisplayName(worked.failure.model)}" has no table in its contract`, `A field rename renames the field's column, and model "${modelDisplayName(worked.failure.model)}" has no table in its contract. Leave out this statement.`, void 0));
|
|
1696
|
+
if (!worked.ok) return notOk(statementRefused(statement, `Field "${modelDisplayName(statement.from)}.${statement.from.field}" has a column on one side only of ${describeMigrationStatement(statement, this.#fromContract, this.#contract)}`, "A field rename renames a column or changes nothing in storage, and this field gains or loses its column. Leave out this statement and plan the change without it.", void 0));
|
|
1697
|
+
const effect = worked.value;
|
|
1698
|
+
if (effect.kind === "unchanged") return ok([]);
|
|
1699
|
+
const table = this.#renamedTables.get(tableKey(effect.table)) ?? effect.table.table;
|
|
1700
|
+
const destinationTable = modelTable(this.#contract, statement.to);
|
|
1701
|
+
if (destinationTable !== void 0 && (destinationTable.namespaceId !== effect.table.namespaceId || destinationTable.table !== table)) {
|
|
1702
|
+
const tableRename = {
|
|
1703
|
+
namespaceId: effect.table.namespaceId,
|
|
1704
|
+
from: table,
|
|
1705
|
+
to: destinationTable.table
|
|
1706
|
+
};
|
|
1707
|
+
const model = modelDisplayName(statement.to);
|
|
1708
|
+
const fieldText = `${model}.${statement.from.field}:${model}.${statement.to.field}`;
|
|
1709
|
+
return notOk(statementRefused(statement, `Cannot rename column "${table}"."${effect.from}": the model's table changes from "${table}" to "${destinationTable.table}", and no statement renames the table`, `The column would be renamed on a table the plan then drops and creates under the new name, and a migration that only changes the table name is planned the same way. With migration plan, rename the table by hand in its own migration first. Change the contract so that only the table name changes, and run prisma contract emit. Run prisma migration new --name <name> --from <hash of the migration the database is at>, add ${this.#target.renderTableRename(tableRename)} to the operations of its migration.ts, and run node on that migration.ts to write its ops.json. Then change the contract to its final form, emit it, and plan the field rename with --from that migration. With db update, change the contract so that only the table name changes, and run prisma contract emit. Rename the table in the database yourself with ${this.#target.tableRenameByHand(tableRename).join("; ")}, check that prisma db update --dry-run plans no drop of a table or column, and run prisma db update to store that contract. Then emit the final contract and run prisma db update --rename ${fieldText}.`, {
|
|
1710
|
+
namespaceId: effect.table.namespaceId,
|
|
1711
|
+
table,
|
|
1712
|
+
column: effect.from
|
|
1713
|
+
}));
|
|
1714
|
+
}
|
|
1715
|
+
const rename = {
|
|
1716
|
+
namespaceId: effect.table.namespaceId,
|
|
1717
|
+
table,
|
|
1718
|
+
from: effect.from,
|
|
1719
|
+
to: effect.to
|
|
1720
|
+
};
|
|
1721
|
+
const tableLocation = {
|
|
1722
|
+
namespaceId: rename.namespaceId,
|
|
1723
|
+
table
|
|
1724
|
+
};
|
|
1725
|
+
const label = `Cannot rename column "${table}"."${rename.from}" to "${rename.to}"`;
|
|
1726
|
+
const policyRefusal = this.#controlPolicyRefusal(statement, label, tableLocation);
|
|
1727
|
+
if (policyRefusal !== void 0) return notOk(policyRefusal);
|
|
1728
|
+
const checked = checkColumnRename(this.#target.tables(), this.#contract, rename);
|
|
1729
|
+
if (!checked.ok) return notOk(columnRenameRefused(statement, label, rename, checked.failure));
|
|
1730
|
+
const planned = this.#emit(statement, label, {
|
|
1731
|
+
...tableLocation,
|
|
1732
|
+
column: rename.from
|
|
1733
|
+
}, this.#target.renameColumnCall(rename));
|
|
1734
|
+
if (planned.ok) this.columnRenames.push(rename);
|
|
1735
|
+
return planned;
|
|
1736
|
+
}
|
|
1737
|
+
};
|
|
1738
|
+
/**
|
|
1739
|
+
* Plans the statements in order against a target's working schema: each model rename becomes a
|
|
1740
|
+
* table rename and each field rename a column rename, computed against the schema earlier
|
|
1741
|
+
* statements left, then applied to it. The first statement that cannot be planned fails the whole
|
|
1742
|
+
* plan with a `statementRefused` conflict that carries the statement.
|
|
1743
|
+
*/
|
|
1744
|
+
function planStatements(input) {
|
|
1745
|
+
const { fromContract } = input;
|
|
1746
|
+
const [first] = input.statements;
|
|
1747
|
+
if (first === void 0) return ok({
|
|
1748
|
+
calls: [],
|
|
1749
|
+
tableRenames: [],
|
|
1750
|
+
columnRenames: [],
|
|
1751
|
+
appliedStatements: []
|
|
1752
|
+
});
|
|
1753
|
+
if (fromContract === null) return notOk(statementRefused(first, "Statements need an origin contract, and this plan has none", "A statement names models and fields of the origin contract, and this plan has none. Plan from a contract that has the old names, or leave out the statement.", void 0));
|
|
1754
|
+
const planner = new StatementPlanner({
|
|
1755
|
+
...input,
|
|
1756
|
+
fromContract
|
|
1757
|
+
});
|
|
1758
|
+
const appliedStatements = [];
|
|
1759
|
+
for (const statement of input.statements) {
|
|
1760
|
+
const operationIndexes = planner.plan(statement);
|
|
1761
|
+
if (!operationIndexes.ok) return operationIndexes;
|
|
1762
|
+
appliedStatements.push({
|
|
1763
|
+
statement,
|
|
1764
|
+
operationIndexes: operationIndexes.value
|
|
1765
|
+
});
|
|
1766
|
+
}
|
|
1767
|
+
return ok({
|
|
1768
|
+
calls: planner.calls,
|
|
1769
|
+
tableRenames: planner.tableRenames,
|
|
1770
|
+
columnRenames: planner.columnRenames,
|
|
1771
|
+
appliedStatements
|
|
1772
|
+
});
|
|
1773
|
+
}
|
|
1440
1774
|
const TABLE_NAME_CASE_CHANGED_CODE = "MIGRATION.TABLE_NAME_CASE_CHANGED";
|
|
1441
1775
|
function lowerFirst(value) {
|
|
1442
1776
|
return value.charAt(0).toLowerCase() + value.slice(1);
|
|
@@ -1551,6 +1885,6 @@ function temporalCodecPresetWithPrecision(input) {
|
|
|
1551
1885
|
}
|
|
1552
1886
|
var control_default = new SqlFamilyDescriptor();
|
|
1553
1887
|
//#endregion
|
|
1554
|
-
export { runnerFailure as _, contractNamespaceToSchemaIR as a,
|
|
1888
|
+
export { runnerSuccess as C, unmatchedColumnRename as D, temporalStringAuthoringPresets as E, unmatchedTableRename as O, runnerFailure as S, temporalCodecPresetWithPrecision as T, planStatements as _, contractNamespaceToSchemaIR as a, resolveColumnRenameAgainst as b, control_default as c, detectTableNameCaseChanges as d, fieldRenameStorageEffect as f, planFieldEventOperations as g, partitionIssuesByControlPolicy as h, assembleAuthoringContributions as i, createMigrationPlan as l, partitionCallsByControlPolicy as m, INIT_ADDITIVE_POLICY as n, contractToSchemaIR as o, modelRenameStorageEffect as p, TABLE_NAME_CASE_CHANGED_CODE as r, controlPolicyForCall as s, COLUMN_RENAME_UNMATCHED_CODE as t, detectDestructiveChanges as u, plannerFailure as v, sqlTypeLookupsOf as w, resolveTableRenameAgainst as x, plannerSuccess as y };
|
|
1555
1889
|
|
|
1556
|
-
//# sourceMappingURL=control-
|
|
1890
|
+
//# sourceMappingURL=control-C4VZIU-L.mjs.map
|