@prisma/orm-family-sql 8.0.0-rc.17-dev.17 → 8.0.0-rc.17-dev.18
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.
|
@@ -36,10 +36,18 @@ function andList(items) {
|
|
|
36
36
|
function fieldList(modelName, fieldNames) {
|
|
37
37
|
return andList(fieldNames.map((name) => `"${modelName}.${name}"`));
|
|
38
38
|
}
|
|
39
|
-
|
|
39
|
+
/** An `@ignore` field in the model's primary key: without it the model has no field that identifies a row. */
|
|
40
|
+
function ignoredFieldInPrimaryKey(input) {
|
|
40
41
|
const fields = fieldList(input.modelName, input.fieldNames);
|
|
41
42
|
const one = input.fieldNames.length === 1;
|
|
42
|
-
return prisma7Diagnostic("PSL.PRISMA7_IGNORED_FIELD_REFERENCED", `${one ? "Field" : "Fields"} ${fields} ${one ? "is" : "are"} marked @ignore, but ${input.usedBy} uses ${one ? "it" : "them"}, and
|
|
43
|
+
return prisma7Diagnostic("PSL.PRISMA7_IGNORED_FIELD_REFERENCED", `${one ? "Field" : "Fields"} ${fields} ${one ? "is" : "are"} marked @ignore, but ${input.usedBy} uses ${one ? "it" : "them"}, and without ${one ? "it" : "them"} model "${input.modelName}" has no field that identifies a row, so Prisma 8 could not update, delete or relate its rows. Remove @ignore from ${fields}: Prisma 7's next migration is then empty, and ${one ? "the field appears" : "the fields appear"} in the Prisma 7 client again. Or replace ${one ? "it" : "them"} with @@ignore on model "${input.modelName}": Prisma 7 then requires @ignore on every relation field that points to the model, its next migration is empty, Prisma 8 keeps the model's table with its primary key, and the model disappears from both clients.`, input.sourceId, input.span);
|
|
44
|
+
}
|
|
45
|
+
/** A relation that is not `@ignore` joins on `@ignore` fields: Prisma 8 relations join on fields, and the domain has no ignored field. */
|
|
46
|
+
function ignoredFieldJoined(input) {
|
|
47
|
+
const fields = fieldList(input.modelName, input.fieldNames);
|
|
48
|
+
const one = input.fieldNames.length === 1;
|
|
49
|
+
const relation = `relation field "${input.relationField}"`;
|
|
50
|
+
return prisma7Diagnostic("PSL.PRISMA7_IGNORED_FIELD_REFERENCED", `${one ? "Field" : "Fields"} ${fields} ${one ? "is" : "are"} marked @ignore, but ${relation} joins on ${one ? "it" : "them"}, and Prisma 8 relations join on fields. Remove @ignore from ${fields}: Prisma 7's next migration is then empty, and ${one ? "the field appears" : "the fields appear"} in the Prisma 7 client again. Or mark ${relation} @ignore as well: Prisma 7's next migration is then empty, the relation field disappears from the Prisma 7 client, and Prisma 8 keeps its foreign key while leaving the relation out of the contract's models.`, input.sourceId, input.span);
|
|
43
51
|
}
|
|
44
52
|
function parseIndexAttribute(attribute, owner, sourceId, indexTypes, diagnostics) {
|
|
45
53
|
const unsupported = (what, span) => {
|
|
@@ -528,10 +536,25 @@ function parseRelationAttribute(attribute, label, sourceId, diagnostics) {
|
|
|
528
536
|
span: attribute.span
|
|
529
537
|
};
|
|
530
538
|
}
|
|
539
|
+
function storageColumn(model, fieldName) {
|
|
540
|
+
return model.columns.get(fieldName) ?? model.ignoredColumns.get(fieldName);
|
|
541
|
+
}
|
|
542
|
+
/** A foreign key reaches a table with a model through the model, and an `@@ignore` model's table by its name. */
|
|
543
|
+
function referenceTo(model, columns) {
|
|
544
|
+
const table = {
|
|
545
|
+
table: model.tableName,
|
|
546
|
+
columns,
|
|
547
|
+
namespaceId: model.namespaceId
|
|
548
|
+
};
|
|
549
|
+
return model.ignored ? table : {
|
|
550
|
+
model: model.modelName,
|
|
551
|
+
...table
|
|
552
|
+
};
|
|
553
|
+
}
|
|
531
554
|
function columnNames(model, fieldNames) {
|
|
532
555
|
const columns = [];
|
|
533
556
|
for (const fieldName of fieldNames) {
|
|
534
|
-
const column = model
|
|
557
|
+
const column = storageColumn(model, fieldName);
|
|
535
558
|
if (column === void 0) return void 0;
|
|
536
559
|
columns.push(column.columnName);
|
|
537
560
|
}
|
|
@@ -575,7 +598,7 @@ function referentialActionRejections(input) {
|
|
|
575
598
|
const { model, relationField, label, fieldNames, span } = input;
|
|
576
599
|
const anotherAction = "choose another action, which replaces the foreign key on Prisma 7's next migration and leaves the Prisma 7 client unchanged.";
|
|
577
600
|
const fieldsWhere = (predicate) => fieldNames.filter((name) => {
|
|
578
|
-
const column = model
|
|
601
|
+
const column = storageColumn(model, name);
|
|
579
602
|
return column !== void 0 && predicate(column);
|
|
580
603
|
});
|
|
581
604
|
const rejections = [];
|
|
@@ -614,6 +637,7 @@ function lowerRelations(models, naming, diagnostics) {
|
|
|
614
637
|
const invalidFkPairings = [];
|
|
615
638
|
const foreignKeys = /* @__PURE__ */ new Map();
|
|
616
639
|
const junctions = /* @__PURE__ */ new Map();
|
|
640
|
+
const ignoredJunctions = /* @__PURE__ */ new Map();
|
|
617
641
|
const reportedJunctionNames = /* @__PURE__ */ new Set();
|
|
618
642
|
const junctionRequests = [];
|
|
619
643
|
const addForeignKey = (modelName, node) => {
|
|
@@ -630,7 +654,7 @@ function lowerRelations(models, naming, diagnostics) {
|
|
|
630
654
|
relationName: effectiveRelationName(relationField.attribute, model.modelName, relationField.targetModelName)
|
|
631
655
|
});
|
|
632
656
|
};
|
|
633
|
-
for (const model of models.values()) for (const relationField of model.relationFields) {
|
|
657
|
+
for (const model of models.values()) for (const relationField of [...model.relationFields, ...model.ignoredRelationFields]) {
|
|
634
658
|
const { field, targetModelName } = relationField;
|
|
635
659
|
const label = `Relation field "${model.modelName}.${field.name}"`;
|
|
636
660
|
const target = models.get(targetModelName);
|
|
@@ -638,23 +662,32 @@ function lowerRelations(models, naming, diagnostics) {
|
|
|
638
662
|
if (isFkSide(relationField)) {
|
|
639
663
|
const attribute = relationField.attribute;
|
|
640
664
|
if (attribute === void 0 || attribute.fields === void 0) continue;
|
|
641
|
-
const
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
665
|
+
const ignoredRelation = model.ignoredRelationFields.includes(relationField);
|
|
666
|
+
const joinedIgnored = ignoredRelation ? [] : [{
|
|
667
|
+
owner: model,
|
|
668
|
+
names: attribute.fields
|
|
669
|
+
}, {
|
|
670
|
+
owner: target,
|
|
671
|
+
names: attribute.references ?? []
|
|
672
|
+
}].flatMap(({ owner, names }) => {
|
|
673
|
+
const ignored = names.filter((name) => owner.ignoredFields.has(name));
|
|
674
|
+
return ignored.length === 0 ? [] : [ignoredFieldJoined({
|
|
675
|
+
modelName: owner.modelName,
|
|
676
|
+
fieldNames: ignored,
|
|
677
|
+
relationField: `${model.modelName}.${field.name}`,
|
|
648
678
|
sourceId: model.sourceId,
|
|
649
679
|
span: attribute.span
|
|
650
|
-
})
|
|
680
|
+
})];
|
|
681
|
+
});
|
|
682
|
+
if (joinedIgnored.length > 0) {
|
|
683
|
+
rejectFkSide(model, relationField, ...joinedIgnored);
|
|
651
684
|
continue;
|
|
652
685
|
}
|
|
653
686
|
if (attribute.references === void 0) {
|
|
654
687
|
rejectFkSide(model, relationField, unresolved(label, "declares fields without references.", model.sourceId, attribute.span));
|
|
655
688
|
continue;
|
|
656
689
|
}
|
|
657
|
-
if (attribute.fields.some((name) => model.rejectedFields.has(name)) || attribute.references.some((name) => target.
|
|
690
|
+
if (attribute.fields.some((name) => model.rejectedFields.has(name)) || attribute.references.some((name) => target.rejectedFields.has(name))) {
|
|
658
691
|
rejectFkSide(model, relationField);
|
|
659
692
|
continue;
|
|
660
693
|
}
|
|
@@ -668,7 +701,7 @@ function lowerRelations(models, naming, diagnostics) {
|
|
|
668
701
|
rejectFkSide(model, relationField, unresolved(label, "must list as many fields as references.", model.sourceId, attribute.span));
|
|
669
702
|
continue;
|
|
670
703
|
}
|
|
671
|
-
const nullability = attribute.fields.map((name) => model
|
|
704
|
+
const nullability = attribute.fields.map((name) => storageColumn(model, name)?.nullable === true);
|
|
672
705
|
const anyNullable = nullability.includes(true);
|
|
673
706
|
if (anyNullable && !field.optional) {
|
|
674
707
|
rejectFkSide(model, relationField, unresolved(label, "must be optional because one of its fields is optional.", model.sourceId, field.span));
|
|
@@ -695,16 +728,12 @@ function lowerRelations(models, naming, diagnostics) {
|
|
|
695
728
|
addForeignKey(model.modelName, {
|
|
696
729
|
...ifDefined("name", foreignKeyName),
|
|
697
730
|
columns: localColumns,
|
|
698
|
-
references:
|
|
699
|
-
model: target.modelName,
|
|
700
|
-
table: target.tableName,
|
|
701
|
-
columns: referencedColumns,
|
|
702
|
-
namespaceId: target.namespaceId
|
|
703
|
-
},
|
|
731
|
+
references: referenceTo(target, referencedColumns),
|
|
704
732
|
onDelete,
|
|
705
733
|
onUpdate,
|
|
706
734
|
index: false
|
|
707
735
|
});
|
|
736
|
+
if (ignoredRelation) continue;
|
|
708
737
|
fkRelationMetadata.push({
|
|
709
738
|
declaringModelName: model.modelName,
|
|
710
739
|
declaringFieldName: field.name,
|
|
@@ -720,8 +749,10 @@ function lowerRelations(models, naming, diagnostics) {
|
|
|
720
749
|
});
|
|
721
750
|
continue;
|
|
722
751
|
}
|
|
723
|
-
|
|
724
|
-
|
|
752
|
+
const ignoredPair = model.ignoredRelationFields.includes(relationField) || target.ignoredRelationFields.some((other) => other.targetModelName === model.modelName && sameName(other, relationField));
|
|
753
|
+
const targetRelationFields = [...target.relationFields, ...target.ignoredRelationFields];
|
|
754
|
+
if (targetRelationFields.filter((other) => other.targetModelName === model.modelName && isFkSide(other) && sameName(other, relationField)).length > 0 || !field.list) {
|
|
755
|
+
if (ignoredPair) continue;
|
|
725
756
|
candidates.push({
|
|
726
757
|
modelName: model.modelName,
|
|
727
758
|
tableName: model.tableName,
|
|
@@ -732,7 +763,7 @@ function lowerRelations(models, naming, diagnostics) {
|
|
|
732
763
|
});
|
|
733
764
|
continue;
|
|
734
765
|
}
|
|
735
|
-
const partners =
|
|
766
|
+
const partners = targetRelationFields.filter((other) => other !== relationField && other.targetModelName === model.modelName && other.field.list && !isFkSide(other) && sameName(other, relationField));
|
|
736
767
|
const [partner] = partners;
|
|
737
768
|
if (partner === void 0) {
|
|
738
769
|
diagnostics.push(unresolved(label, `has no matching relation field on "${target.modelName}".`, model.sourceId, field.span));
|
|
@@ -764,7 +795,8 @@ function lowerRelations(models, naming, diagnostics) {
|
|
|
764
795
|
junctionRequests.push({
|
|
765
796
|
requester,
|
|
766
797
|
partner: partnerSide,
|
|
767
|
-
name: junctionName
|
|
798
|
+
name: junctionName,
|
|
799
|
+
ignored: ignoredPair
|
|
768
800
|
});
|
|
769
801
|
}
|
|
770
802
|
const requestsByJunction = groupBy(junctionRequests, (request) => junctionKey(orderJunctionSides(request.requester, request.partner)[0].model.namespaceId, request.name));
|
|
@@ -795,11 +827,15 @@ function lowerRelations(models, naming, diagnostics) {
|
|
|
795
827
|
diagnostics.push(prisma7Diagnostic("PSL.PRISMA7_TABLE_COLLISION", message, tableOwner.sourceId, tableOwner.tableSpan), prisma7Diagnostic("PSL.PRISMA7_TABLE_COLLISION", message, first.requester.model.sourceId, first.requester.field.field.span));
|
|
796
828
|
continue;
|
|
797
829
|
}
|
|
798
|
-
for (const { requester, partner } of requests) {
|
|
830
|
+
for (const { requester, partner, ignored } of requests) {
|
|
799
831
|
const junction = synthesizeJunction(requester, partner, naming, diagnostics);
|
|
800
832
|
if (junction === void 0) continue;
|
|
833
|
+
if (ignored) {
|
|
834
|
+
ignoredJunctions.set(junction.key, junction.table);
|
|
835
|
+
continue;
|
|
836
|
+
}
|
|
801
837
|
if (!junctions.has(junction.key)) {
|
|
802
|
-
junctions.set(junction.key, junction.
|
|
838
|
+
junctions.set(junction.key, junctionModel(junction.name, junction.table));
|
|
803
839
|
fkRelationMetadata.push(...junction.foreignKeys);
|
|
804
840
|
}
|
|
805
841
|
candidates.push({
|
|
@@ -863,10 +899,23 @@ function lowerRelations(models, naming, diagnostics) {
|
|
|
863
899
|
for (const [modelName, nodes] of modelRelations) relations.set(modelName, [...nodes].sort((left, right) => left.fieldName.localeCompare(right.fieldName)));
|
|
864
900
|
return {
|
|
865
901
|
junctions,
|
|
902
|
+
ignoredJunctions,
|
|
866
903
|
foreignKeys,
|
|
867
904
|
relations
|
|
868
905
|
};
|
|
869
906
|
}
|
|
907
|
+
/** The junction model over a junction table: a field for each of its columns. */
|
|
908
|
+
function junctionModel(name, table) {
|
|
909
|
+
const { columns, ...properties } = table;
|
|
910
|
+
return {
|
|
911
|
+
...properties,
|
|
912
|
+
modelName: name,
|
|
913
|
+
fields: columns.map((column) => ({
|
|
914
|
+
fieldName: column.columnName,
|
|
915
|
+
...column
|
|
916
|
+
}))
|
|
917
|
+
};
|
|
918
|
+
}
|
|
870
919
|
/**
|
|
871
920
|
* The id column a junction side contributes. The diagnostic names the
|
|
872
921
|
* requesting relation field, so it is located at that field, whichever side's
|
|
@@ -875,7 +924,7 @@ function lowerRelations(models, naming, diagnostics) {
|
|
|
875
924
|
function singleIdColumn(side, requester, diagnostics) {
|
|
876
925
|
if (side.model.idFields.some((name) => side.model.ignoredFields.has(name) || side.model.rejectedFields.has(name))) return;
|
|
877
926
|
const [idField, ...rest] = side.model.idFields;
|
|
878
|
-
const column = idField === void 0 ? void 0 : side.model
|
|
927
|
+
const column = idField === void 0 ? void 0 : storageColumn(side.model, idField);
|
|
879
928
|
if (column === void 0 || rest.length > 0) {
|
|
880
929
|
diagnostics.push(prisma7Diagnostic("PSL.PRISMA7_JUNCTION_ID_UNSUPPORTED", `Relation field "${requester.model.modelName}.${requester.field.field.name}" is an implicit many-to-many relation, but "${side.model.modelName}" ${column === void 0 ? "has no single-field @id" : "has a composite id"}; Prisma 7 requires a single-field @id on both models of an implicit many-to-many relation.`, requester.model.sourceId, requester.field.field.span));
|
|
881
930
|
return;
|
|
@@ -908,12 +957,7 @@ function synthesizeJunction(requester, partner, naming, diagnostics) {
|
|
|
908
957
|
const foreignKey = (column, side, id) => ({
|
|
909
958
|
...ifDefined("name", foreignKeyName(column)),
|
|
910
959
|
columns: [column],
|
|
911
|
-
references:
|
|
912
|
-
model: side.model.modelName,
|
|
913
|
-
table: side.model.tableName,
|
|
914
|
-
columns: [id.columnName],
|
|
915
|
-
namespaceId: side.model.namespaceId
|
|
916
|
-
},
|
|
960
|
+
references: referenceTo(side.model, [id.columnName]),
|
|
917
961
|
onDelete: "cascade",
|
|
918
962
|
onUpdate: "cascade",
|
|
919
963
|
index: false
|
|
@@ -942,18 +986,16 @@ function synthesizeJunction(requester, partner, naming, diagnostics) {
|
|
|
942
986
|
};
|
|
943
987
|
return {
|
|
944
988
|
key,
|
|
945
|
-
|
|
946
|
-
|
|
989
|
+
name,
|
|
990
|
+
table: {
|
|
947
991
|
tableName,
|
|
948
992
|
namespaceId,
|
|
949
|
-
|
|
950
|
-
fieldName: "A",
|
|
993
|
+
columns: [{
|
|
951
994
|
columnName: "A",
|
|
952
995
|
descriptor: idA.descriptor,
|
|
953
996
|
nullable: false,
|
|
954
997
|
many: false
|
|
955
998
|
}, {
|
|
956
|
-
fieldName: "B",
|
|
957
999
|
columnName: "B",
|
|
958
1000
|
descriptor: idB.descriptor,
|
|
959
1001
|
nullable: false,
|
|
@@ -1029,7 +1071,6 @@ function interpretPrisma7Documents(input) {
|
|
|
1029
1071
|
const datasources = [];
|
|
1030
1072
|
const enumBlocks = [];
|
|
1031
1073
|
const models = [];
|
|
1032
|
-
const ignoredModels = /* @__PURE__ */ new Set();
|
|
1033
1074
|
const declaredNames = /* @__PURE__ */ new Map();
|
|
1034
1075
|
const claimName = (kind, name, sourceId, span) => {
|
|
1035
1076
|
const previous = declaredNames.get(name);
|
|
@@ -1095,9 +1136,7 @@ function interpretPrisma7Documents(input) {
|
|
|
1095
1136
|
for (const namedType of Object.values(symbolTable.topLevel.namedTypes)) unsupported("types", namedType.span);
|
|
1096
1137
|
for (const symbol of Object.values(symbolTable.topLevel.models)) {
|
|
1097
1138
|
if (!claimName("model", symbol.name, sourceId, symbol.span)) continue;
|
|
1098
|
-
|
|
1099
|
-
if (declaration === void 0) ignoredModels.add(symbol.name);
|
|
1100
|
-
else models.push(declaration);
|
|
1139
|
+
models.push(readModelDeclaration(symbol, sourceId, sources, defaultNamespaceId, binding, diagnostics));
|
|
1101
1140
|
}
|
|
1102
1141
|
}
|
|
1103
1142
|
checkDatasource(datasources, input.documents[0]?.sourceId ?? "schema.prisma", binding, diagnostics);
|
|
@@ -1108,13 +1147,15 @@ function interpretPrisma7Documents(input) {
|
|
|
1108
1147
|
if (declaration !== void 0) enums.set(declaration.name, declaration);
|
|
1109
1148
|
}
|
|
1110
1149
|
const namespaceEntities = lowerNativeEnums(enums, input, diagnostics);
|
|
1111
|
-
const modelNames =
|
|
1150
|
+
const modelNames = new Set(models.map((model) => model.symbol.name));
|
|
1151
|
+
const ignoredModels = new Set(models.filter((model) => model.ignored).map((model) => model.symbol.name));
|
|
1112
1152
|
const composedExtensions = new Set(input.composedExtensions);
|
|
1113
1153
|
const builds = /* @__PURE__ */ new Map();
|
|
1114
1154
|
for (const declaration of models) {
|
|
1115
1155
|
const build = {
|
|
1116
1156
|
declaration,
|
|
1117
1157
|
columns: /* @__PURE__ */ new Map(),
|
|
1158
|
+
ignoredColumns: /* @__PURE__ */ new Map(),
|
|
1118
1159
|
ignoredFields: /* @__PURE__ */ new Set(),
|
|
1119
1160
|
ignoredRelationFields: [],
|
|
1120
1161
|
rejectedFields: /* @__PURE__ */ new Set(),
|
|
@@ -1136,7 +1177,7 @@ function interpretPrisma7Documents(input) {
|
|
|
1136
1177
|
input,
|
|
1137
1178
|
diagnostics
|
|
1138
1179
|
});
|
|
1139
|
-
if (diagnostics.length > reported && !build.columns.has(field.name) && !build.
|
|
1180
|
+
if (diagnostics.length > reported && !build.columns.has(field.name) && !build.ignoredColumns.has(field.name)) build.rejectedFields.add(field.name);
|
|
1140
1181
|
}
|
|
1141
1182
|
builds.set(declaration.symbol.name, build);
|
|
1142
1183
|
}
|
|
@@ -1144,11 +1185,13 @@ function interpretPrisma7Documents(input) {
|
|
|
1144
1185
|
for (const [modelName, build] of builds) relationModels.set(modelName, {
|
|
1145
1186
|
modelName,
|
|
1146
1187
|
tableName: build.declaration.tableName,
|
|
1188
|
+
ignored: build.declaration.ignored,
|
|
1147
1189
|
tableSpan: build.declaration.symbol.attributes.find((attribute) => attribute.name === "map")?.span ?? build.declaration.symbol.span,
|
|
1148
1190
|
namespaceId: build.declaration.namespaceId,
|
|
1149
1191
|
sourceId: build.declaration.sourceId,
|
|
1150
1192
|
sources: build.declaration.sources,
|
|
1151
1193
|
columns: build.columns,
|
|
1194
|
+
ignoredColumns: build.ignoredColumns,
|
|
1152
1195
|
ignoredFields: build.ignoredFields,
|
|
1153
1196
|
ignoredRelationFields: build.ignoredRelationFields,
|
|
1154
1197
|
rejectedFields: build.rejectedFields,
|
|
@@ -1158,17 +1201,17 @@ function interpretPrisma7Documents(input) {
|
|
|
1158
1201
|
});
|
|
1159
1202
|
const lowered = lowerRelations(relationModels, binding, diagnostics);
|
|
1160
1203
|
const modelNodes = [];
|
|
1204
|
+
const tables = [];
|
|
1161
1205
|
for (const [modelName, build] of builds) {
|
|
1162
1206
|
const model = relationModels.get(modelName);
|
|
1163
1207
|
if (model === void 0) continue;
|
|
1164
1208
|
const ignoredAmong = (fieldNames) => fieldNames?.filter((name) => build.ignoredFields.has(name)) ?? [];
|
|
1165
1209
|
const idAttribute = build.declaration.id;
|
|
1166
1210
|
const ignoredIdFields = ignoredAmong(idAttribute?.fields);
|
|
1167
|
-
if (idAttribute !== void 0 && ignoredIdFields.length > 0) diagnostics.push(
|
|
1211
|
+
if (idAttribute !== void 0 && ignoredIdFields.length > 0) diagnostics.push(ignoredFieldInPrimaryKey({
|
|
1168
1212
|
modelName,
|
|
1169
1213
|
fieldNames: ignoredIdFields,
|
|
1170
1214
|
usedBy: `@@id on model "${modelName}"`,
|
|
1171
|
-
constraint: "primary key",
|
|
1172
1215
|
sourceId: model.sourceId,
|
|
1173
1216
|
span: idAttribute.span
|
|
1174
1217
|
}));
|
|
@@ -1180,18 +1223,6 @@ function interpretPrisma7Documents(input) {
|
|
|
1180
1223
|
attribute,
|
|
1181
1224
|
unique: false
|
|
1182
1225
|
}))].flatMap(({ attribute, unique }) => {
|
|
1183
|
-
const ignoredIndexFields = ignoredAmong(attribute.fields);
|
|
1184
|
-
if (ignoredIndexFields.length > 0) {
|
|
1185
|
-
diagnostics.push(ignoredFieldReferenced({
|
|
1186
|
-
modelName,
|
|
1187
|
-
fieldNames: ignoredIndexFields,
|
|
1188
|
-
usedBy: `${unique ? "@@unique" : "@@index"} on model "${modelName}"`,
|
|
1189
|
-
constraint: unique ? "unique index" : "index",
|
|
1190
|
-
sourceId: model.sourceId,
|
|
1191
|
-
span: attribute.span
|
|
1192
|
-
}));
|
|
1193
|
-
return [];
|
|
1194
|
-
}
|
|
1195
1226
|
if (attribute.fields?.some((name) => build.rejectedFields.has(name))) return [];
|
|
1196
1227
|
const columns = attribute.fields === void 0 ? void 0 : keyColumns(model, attribute.fields);
|
|
1197
1228
|
if (columns === void 0) {
|
|
@@ -1203,20 +1234,38 @@ function interpretPrisma7Documents(input) {
|
|
|
1203
1234
|
const foreignKeys = lowered.foreignKeys.get(modelName);
|
|
1204
1235
|
const relations = lowered.relations.get(modelName);
|
|
1205
1236
|
const primaryKeyName = statedConstraintName(prisma7PrimaryKeyName(model.tableName, build.idMap, binding.identifierMaxBytes), binding.defaultConstraintNames.primaryKey(model.tableName));
|
|
1206
|
-
|
|
1207
|
-
modelName,
|
|
1237
|
+
const tableProperties = stateServedBackingIndexes({
|
|
1208
1238
|
tableName: model.tableName,
|
|
1209
|
-
namespaceId: model.namespaceId,
|
|
1210
|
-
fields: [...build.columns.values()],
|
|
1211
1239
|
...id !== void 0 && id.length > 0 ? { id: {
|
|
1212
1240
|
columns: id,
|
|
1213
1241
|
...ifDefined("name", primaryKeyName)
|
|
1214
1242
|
} } : {},
|
|
1215
1243
|
...indexes.length > 0 ? { indexes } : {},
|
|
1216
|
-
...foreignKeys !== void 0 ? { foreignKeys } : {}
|
|
1244
|
+
...foreignKeys !== void 0 ? { foreignKeys } : {}
|
|
1245
|
+
});
|
|
1246
|
+
const ignoredColumns = [...build.ignoredColumns.values()];
|
|
1247
|
+
if (model.ignored) {
|
|
1248
|
+
tables.push({
|
|
1249
|
+
...tableProperties,
|
|
1250
|
+
namespaceId: model.namespaceId,
|
|
1251
|
+
columns: ignoredColumns
|
|
1252
|
+
});
|
|
1253
|
+
continue;
|
|
1254
|
+
}
|
|
1255
|
+
modelNodes.push({
|
|
1256
|
+
...tableProperties,
|
|
1257
|
+
modelName,
|
|
1258
|
+
namespaceId: model.namespaceId,
|
|
1259
|
+
fields: [...build.columns.values()],
|
|
1217
1260
|
...relations !== void 0 ? { relations } : {}
|
|
1218
|
-
})
|
|
1261
|
+
});
|
|
1262
|
+
if (ignoredColumns.length > 0) tables.push({
|
|
1263
|
+
namespaceId: model.namespaceId,
|
|
1264
|
+
tableName: model.tableName,
|
|
1265
|
+
columns: ignoredColumns
|
|
1266
|
+
});
|
|
1219
1267
|
}
|
|
1268
|
+
tables.push(...[...lowered.ignoredJunctions.values()].map(stateServedBackingIndexes));
|
|
1220
1269
|
for (const [key, junction] of lowered.junctions) {
|
|
1221
1270
|
const relations = lowered.relations.get(key);
|
|
1222
1271
|
modelNodes.push(stateServedBackingIndexes(relations === void 0 ? junction : {
|
|
@@ -1249,7 +1298,8 @@ function interpretPrisma7Documents(input) {
|
|
|
1249
1298
|
warnings: void 0,
|
|
1250
1299
|
createNamespace,
|
|
1251
1300
|
...namespaceEntities.size > 0 ? { namespaces: [...namespaceEntities.keys()] } : {},
|
|
1252
|
-
models: modelNodes
|
|
1301
|
+
models: modelNodes,
|
|
1302
|
+
...tables.length > 0 ? { tables } : {}
|
|
1253
1303
|
}, input.codecLookup, input.dataTypes.lookup));
|
|
1254
1304
|
}
|
|
1255
1305
|
/**
|
|
@@ -1316,7 +1366,7 @@ function reportTableCollisions(models, diagnostics) {
|
|
|
1316
1366
|
function keyColumns(model, fieldNames) {
|
|
1317
1367
|
const columns = [];
|
|
1318
1368
|
for (const fieldName of fieldNames) {
|
|
1319
|
-
const column = model.columns.get(fieldName);
|
|
1369
|
+
const column = model.columns.get(fieldName) ?? model.ignoredColumns.get(fieldName);
|
|
1320
1370
|
if (column === void 0) return void 0;
|
|
1321
1371
|
columns.push(column.columnName);
|
|
1322
1372
|
}
|
|
@@ -1324,7 +1374,7 @@ function keyColumns(model, fieldNames) {
|
|
|
1324
1374
|
}
|
|
1325
1375
|
function readModelDeclaration(symbol, sourceId, sources, defaultNamespaceId, binding, diagnostics) {
|
|
1326
1376
|
const { indexTypes } = binding;
|
|
1327
|
-
|
|
1377
|
+
let ignored = false;
|
|
1328
1378
|
let tableName = symbol.name;
|
|
1329
1379
|
let namespaceId = defaultNamespaceId;
|
|
1330
1380
|
let id;
|
|
@@ -1364,6 +1414,9 @@ function readModelDeclaration(symbol, sourceId, sources, defaultNamespaceId, bin
|
|
|
1364
1414
|
if (parsed?.fields !== void 0) indexes.push(parsed);
|
|
1365
1415
|
break;
|
|
1366
1416
|
}
|
|
1417
|
+
case "ignore":
|
|
1418
|
+
ignored = true;
|
|
1419
|
+
break;
|
|
1367
1420
|
default: diagnostics.push(prisma7Diagnostic("PSL.PRISMA7_UNKNOWN_ATTRIBUTE", `Model "${symbol.name}": attribute "@@${attribute.name}" is not supported yet by the Prisma 7 contract source.`, sourceId, attribute.span));
|
|
1368
1421
|
}
|
|
1369
1422
|
}
|
|
@@ -1373,6 +1426,7 @@ function readModelDeclaration(symbol, sourceId, sources, defaultNamespaceId, bin
|
|
|
1373
1426
|
sources,
|
|
1374
1427
|
namespaceId,
|
|
1375
1428
|
tableName,
|
|
1429
|
+
ignored,
|
|
1376
1430
|
id,
|
|
1377
1431
|
uniqueIndexes,
|
|
1378
1432
|
indexes
|
|
@@ -1492,75 +1546,8 @@ function lowerNativeEnums(enums, input, diagnostics) {
|
|
|
1492
1546
|
}
|
|
1493
1547
|
return result;
|
|
1494
1548
|
}
|
|
1495
|
-
function
|
|
1496
|
-
|
|
1497
|
-
const uses = [];
|
|
1498
|
-
for (const attribute of field.attributes) {
|
|
1499
|
-
if (attribute.name === "id") uses.push({
|
|
1500
|
-
usedBy: "its @id",
|
|
1501
|
-
constraint: "primary key"
|
|
1502
|
-
});
|
|
1503
|
-
if (attribute.name === "unique") uses.push({
|
|
1504
|
-
usedBy: "its @unique",
|
|
1505
|
-
constraint: "unique index"
|
|
1506
|
-
});
|
|
1507
|
-
}
|
|
1508
|
-
if (model.id?.fields?.includes(field.name)) uses.push({
|
|
1509
|
-
usedBy: `@@id on model "${modelName}"`,
|
|
1510
|
-
constraint: "primary key"
|
|
1511
|
-
});
|
|
1512
|
-
for (const unique of model.uniqueIndexes) if (unique.fields?.includes(field.name)) uses.push({
|
|
1513
|
-
usedBy: `@@unique on model "${modelName}"`,
|
|
1514
|
-
constraint: "unique index"
|
|
1515
|
-
});
|
|
1516
|
-
for (const index of model.indexes) if (index.fields?.includes(field.name)) uses.push({
|
|
1517
|
-
usedBy: `@@index on model "${modelName}"`,
|
|
1518
|
-
constraint: "index"
|
|
1519
|
-
});
|
|
1520
|
-
for (const other of Object.values(model.symbol.fields)) {
|
|
1521
|
-
if (other.attributes.some((attribute) => attribute.name === "ignore")) continue;
|
|
1522
|
-
const relation = other.attributes.find((attribute) => attribute.name === "relation");
|
|
1523
|
-
if ((relation === void 0 ? void 0 : parseRelationAttribute(relation, other.name, model.sourceId, []))?.fields?.includes(field.name)) uses.push({
|
|
1524
|
-
usedBy: `relation field "${modelName}.${other.name}"`,
|
|
1525
|
-
constraint: "foreign key"
|
|
1526
|
-
});
|
|
1527
|
-
}
|
|
1528
|
-
return uses;
|
|
1529
|
-
}
|
|
1530
|
-
function nativeTypeMessage(input) {
|
|
1531
|
-
const { label, nativeType, field, model } = input;
|
|
1532
|
-
const uses = keysUsingField(field, model);
|
|
1533
|
-
if (uses.length > 0) {
|
|
1534
|
-
const constraints = [...new Set(uses.map((use) => `the ${use.constraint}`))];
|
|
1535
|
-
return `${label}: native type "@db.${nativeType}" has no Prisma 8 codec, and ${andList(uses.map((use) => use.usedBy))} ${uses.length === 1 ? "uses" : "use"} the field, so @ignore on the field does not help: Prisma 7 still creates ${andList(constraints)} over the column. Add @@ignore to model "${model.symbol.name}" to keep the model out of the contract: Prisma 7's next migration is empty, but the model disappears from the Prisma 7 client too, and every relation field in another model that points to it needs @ignore, which removes that field from the Prisma 7 client as well. Changing the field's type instead changes the column type on Prisma 7's next migration.`;
|
|
1536
|
-
}
|
|
1537
|
-
return `${label}: native type "@db.${nativeType}" has no Prisma 8 codec. Add @ignore to the field to keep its column out of the contract: Prisma 7's next migration is empty, and the field disappears from the Prisma 7 client too${!field.optional && !field.list && !givesColumnDefault(input.defaultAttribute) ? "; because the field is required and its column has no default, neither client can then insert rows" : ""}. Changing the field's type instead changes the column type on Prisma 7's next migration.`;
|
|
1538
|
-
}
|
|
1539
|
-
function readIgnoredField(field, isRelationField, args) {
|
|
1540
|
-
const { build, diagnostics } = args;
|
|
1541
|
-
const model = build.declaration;
|
|
1542
|
-
if (isRelationField) {
|
|
1543
|
-
if (args.ignoredModels.has(field.typeName)) return;
|
|
1544
|
-
const relation = field.attributes.find((attribute) => attribute.name === "relation");
|
|
1545
|
-
build.ignoredRelationFields.push({
|
|
1546
|
-
field,
|
|
1547
|
-
targetModelName: field.typeName,
|
|
1548
|
-
attribute: relation === void 0 ? void 0 : parseRelationAttribute(relation, field.name, model.sourceId, [])
|
|
1549
|
-
});
|
|
1550
|
-
return;
|
|
1551
|
-
}
|
|
1552
|
-
for (const attribute of field.attributes) {
|
|
1553
|
-
if (attribute.name !== "id" && attribute.name !== "unique") continue;
|
|
1554
|
-
if (attribute.name === "id") build.idFields = [field.name];
|
|
1555
|
-
diagnostics.push(ignoredFieldReferenced({
|
|
1556
|
-
modelName: model.symbol.name,
|
|
1557
|
-
fieldNames: [field.name],
|
|
1558
|
-
usedBy: `its @${attribute.name}`,
|
|
1559
|
-
constraint: attribute.name === "id" ? "primary key" : "unique index",
|
|
1560
|
-
sourceId: model.sourceId,
|
|
1561
|
-
span: attribute.span
|
|
1562
|
-
}));
|
|
1563
|
-
}
|
|
1549
|
+
function nativeTypeMessage(label, nativeType) {
|
|
1550
|
+
return `${label}: native type "@db.${nativeType}" has no Prisma 8 codec yet, and Prisma 8 cannot read this schema until it supports the column type. @ignore on the field or @@ignore on the model does not help: Prisma 8 keeps the columns of ignored fields and models in the contract. Changing the field's type to one Prisma 8 supports changes the column type on Prisma 7's next migration.`;
|
|
1564
1551
|
}
|
|
1565
1552
|
function readField(args) {
|
|
1566
1553
|
const { field, build, diagnostics, input } = args;
|
|
@@ -1569,11 +1556,9 @@ function readField(args) {
|
|
|
1569
1556
|
const sourceId = model.sourceId;
|
|
1570
1557
|
const label = `Field "${model.symbol.name}.${field.name}"`;
|
|
1571
1558
|
const isRelationField = args.modelNames.has(field.typeName) && field.typeConstructor === void 0;
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
return;
|
|
1576
|
-
}
|
|
1559
|
+
const fieldIgnored = field.attributes.some((attribute) => attribute.name === "ignore") || isRelationField && args.ignoredModels.has(field.typeName);
|
|
1560
|
+
if (fieldIgnored) build.ignoredFields.add(field.name);
|
|
1561
|
+
const ignored = fieldIgnored || model.ignored;
|
|
1577
1562
|
let columnName = field.name;
|
|
1578
1563
|
let nativeType;
|
|
1579
1564
|
let relation;
|
|
@@ -1598,6 +1583,13 @@ function readField(args) {
|
|
|
1598
1583
|
build.idFields = [field.name];
|
|
1599
1584
|
build.idMap = parsed.map;
|
|
1600
1585
|
}
|
|
1586
|
+
if (fieldIgnored) diagnostics.push(ignoredFieldInPrimaryKey({
|
|
1587
|
+
modelName: model.symbol.name,
|
|
1588
|
+
fieldNames: [field.name],
|
|
1589
|
+
usedBy: "its @id",
|
|
1590
|
+
sourceId,
|
|
1591
|
+
span: attribute.span
|
|
1592
|
+
}));
|
|
1601
1593
|
} else if (attribute.name === "unique" && !isRelationField) {
|
|
1602
1594
|
const parsed = parseIndexAttribute(attribute, label, sourceId, binding.indexTypes, diagnostics);
|
|
1603
1595
|
if (parsed !== void 0) build.uniqueIndexes.push({
|
|
@@ -1607,18 +1599,17 @@ function readField(args) {
|
|
|
1607
1599
|
} else if (attribute.name === "default" && !isRelationField) defaultAttribute = attribute;
|
|
1608
1600
|
else if (attribute.name === "updatedAt" && !isRelationField) updatedAt = attribute;
|
|
1609
1601
|
else if (attribute.name === "relation" && isRelationField) relation = attribute;
|
|
1610
|
-
else diagnostics.push(prisma7Diagnostic("PSL.PRISMA7_UNKNOWN_ATTRIBUTE", `${label}: attribute "@${attribute.name}" is not supported yet by the Prisma 7 contract source.`, sourceId, attribute.span));
|
|
1602
|
+
else if (attribute.name === "ignore") {} else diagnostics.push(prisma7Diagnostic("PSL.PRISMA7_UNKNOWN_ATTRIBUTE", `${label}: attribute "@${attribute.name}" is not supported yet by the Prisma 7 contract source.`, sourceId, attribute.span));
|
|
1611
1603
|
}
|
|
1612
1604
|
if (field.malformedType) return;
|
|
1613
1605
|
if (field.typeConstructor !== void 0) {
|
|
1614
|
-
diagnostics.push(prisma7Diagnostic("PSL.PRISMA7_UNSUPPORTED_TYPE", `${label} has type "${field.typeConstructor.path.join(".")}(...)", which has no Prisma 8 codec,
|
|
1606
|
+
diagnostics.push(prisma7Diagnostic("PSL.PRISMA7_UNSUPPORTED_TYPE", `${label} has type "${field.typeConstructor.path.join(".")}(...)", which has no Prisma 8 codec yet, and Prisma 8 cannot read this schema until it supports the column type. @@ignore on model "${model.symbol.name}" does not help: Prisma 8 keeps the columns of ignored models in the contract. Removing the field drops its column on Prisma 7's next migration.`, sourceId, field.typeConstructor.span));
|
|
1615
1607
|
return;
|
|
1616
1608
|
}
|
|
1617
|
-
if (args.ignoredModels.has(field.typeName)) return;
|
|
1618
1609
|
if (isRelationField) {
|
|
1619
1610
|
const attribute = relation === void 0 ? void 0 : parseRelationAttribute(relation, label, sourceId, diagnostics);
|
|
1620
1611
|
if (relation !== void 0 && attribute === void 0) return;
|
|
1621
|
-
build.relationFields.push({
|
|
1612
|
+
(ignored ? build.ignoredRelationFields : build.relationFields).push({
|
|
1622
1613
|
field,
|
|
1623
1614
|
targetModelName: field.typeName,
|
|
1624
1615
|
attribute
|
|
@@ -1652,13 +1643,7 @@ function readField(args) {
|
|
|
1652
1643
|
if (nativeType !== void 0) {
|
|
1653
1644
|
const native = prisma7NativeTypeMapping(binding.typeMap, nativeType.name, nativeType.attribute.args.map((arg) => arg.value));
|
|
1654
1645
|
if (native === void 0) {
|
|
1655
|
-
diagnostics.push(prisma7Diagnostic("PSL.PRISMA7_NATIVE_TYPE_UNSUPPORTED", nativeTypeMessage(
|
|
1656
|
-
label,
|
|
1657
|
-
nativeType: nativeType.name,
|
|
1658
|
-
field,
|
|
1659
|
-
model,
|
|
1660
|
-
defaultAttribute
|
|
1661
|
-
}), sourceId, nativeType.attribute.span));
|
|
1646
|
+
diagnostics.push(prisma7Diagnostic("PSL.PRISMA7_NATIVE_TYPE_UNSUPPORTED", nativeTypeMessage(label, nativeType.name), sourceId, nativeType.attribute.span));
|
|
1662
1647
|
return;
|
|
1663
1648
|
}
|
|
1664
1649
|
mapping = native;
|
|
@@ -1697,13 +1682,13 @@ function readField(args) {
|
|
|
1697
1682
|
dataTypeLookup: input.dataTypes.lookup
|
|
1698
1683
|
};
|
|
1699
1684
|
const columnTypeName = unquotedSqlBaseNameOfCodec(resolved.descriptor.codecId, resolved.descriptor.typeParams, typeLookups);
|
|
1700
|
-
const updatedAtGeneratorId = updatedAt === void 0 ? void 0 : binding.updatedAtGeneratorId(resolved.descriptor.codecId);
|
|
1701
|
-
if (updatedAt !== void 0 && updatedAtGeneratorId === void 0) {
|
|
1685
|
+
const updatedAtGeneratorId = updatedAt === void 0 || ignored ? void 0 : binding.updatedAtGeneratorId(resolved.descriptor.codecId);
|
|
1686
|
+
if (updatedAt !== void 0 && !ignored && updatedAtGeneratorId === void 0) {
|
|
1702
1687
|
const withoutUpdatedAt = defaultAttribute !== void 0 && givesColumnDefault(defaultAttribute) ? `. Its ${attributeText(defaultAttribute)} still sets the value on create, and neither client changes it on update.` : field.optional ? ", but neither client then fills the value, so it stays empty unless a client writes it, and updates leave it unchanged." : ", but neither client then fills the value, so both require it on create and leave it unchanged on update.";
|
|
1703
1688
|
diagnostics.push(prisma7Diagnostic("PSL.PRISMA7_UPDATED_AT_TYPE_UNSUPPORTED", `${label}: @updatedAt is not supported on this column, because Prisma 8 has no generator for column type "${columnTypeName}" yet. Remove @updatedAt: Prisma 7's next migration is empty${withoutUpdatedAt}`, sourceId, updatedAt.span));
|
|
1704
1689
|
return;
|
|
1705
1690
|
}
|
|
1706
|
-
if (updatedAt !== void 0 && defaultAttribute !== void 0) {
|
|
1691
|
+
if (updatedAt !== void 0 && !ignored && defaultAttribute !== void 0) {
|
|
1707
1692
|
const written = attributeText(defaultAttribute);
|
|
1708
1693
|
diagnostics.push(prisma7Diagnostic("PSL.PRISMA7_UPDATED_AT_WITH_DEFAULT_UNSUPPORTED", `${label} combines @updatedAt with ${written}, which Prisma 8 cannot express yet. Remove ${written}: @updatedAt still sets the value on create and on update, and Prisma 7's next migration removes the column default.`, sourceId, defaultAttribute.span));
|
|
1709
1694
|
return;
|
|
@@ -1727,6 +1712,21 @@ function readField(args) {
|
|
|
1727
1712
|
diagnostics
|
|
1728
1713
|
});
|
|
1729
1714
|
if (defaultAttribute !== void 0 && lowered === void 0) return;
|
|
1715
|
+
const column = {
|
|
1716
|
+
columnName,
|
|
1717
|
+
descriptor: resolved.descriptor,
|
|
1718
|
+
nullable: field.optional || field.list,
|
|
1719
|
+
many: field.list,
|
|
1720
|
+
...field.list ? {
|
|
1721
|
+
elementNullable: false,
|
|
1722
|
+
noCheck: ["elementNotNull"]
|
|
1723
|
+
} : {},
|
|
1724
|
+
...ifDefined("default", lowered?.storage)
|
|
1725
|
+
};
|
|
1726
|
+
if (ignored) {
|
|
1727
|
+
build.ignoredColumns.set(field.name, column);
|
|
1728
|
+
return;
|
|
1729
|
+
}
|
|
1730
1730
|
const updatedAtGenerator = updatedAtGeneratorId === void 0 ? void 0 : {
|
|
1731
1731
|
kind: "generator",
|
|
1732
1732
|
id: updatedAtGeneratorId
|
|
@@ -1744,15 +1744,7 @@ function readField(args) {
|
|
|
1744
1744
|
} : generator !== void 0 ? { onCreate: generator } : void 0;
|
|
1745
1745
|
build.columns.set(field.name, {
|
|
1746
1746
|
fieldName: field.name,
|
|
1747
|
-
|
|
1748
|
-
descriptor: resolved.descriptor,
|
|
1749
|
-
nullable: field.optional || field.list,
|
|
1750
|
-
many: field.list,
|
|
1751
|
-
...field.list ? {
|
|
1752
|
-
elementNullable: false,
|
|
1753
|
-
noCheck: ["elementNotNull"]
|
|
1754
|
-
} : {},
|
|
1755
|
-
...ifDefined("default", lowered?.storage),
|
|
1747
|
+
...column,
|
|
1756
1748
|
...ifDefined("executionDefaults", executionDefaults)
|
|
1757
1749
|
});
|
|
1758
1750
|
}
|