Skip to content

Commit

Permalink
fix: prioritise foreign keys over primary keys in pg-schema-print-typ…
Browse files Browse the repository at this point in the history
…es (#250)

If a key was both a foreign key and a primary key, we would incorrectly generate a branded type for it, rather than referencing the column being referenced by the foreign key.
  • Loading branch information
ForbesLindesay authored Aug 2, 2022
1 parent 97938d4 commit 61043da
Showing 1 changed file with 31 additions and 28 deletions.
59 changes: 31 additions & 28 deletions packages/pg-schema-print-types/src/printers/printClassDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,38 +119,41 @@ function getAttributeType(
return columnTypeOverride;
}

for (const constraint of type.constraints) {
if (constraint.tableAttributeNumbers.includes(attribute.attributeNumber)) {
if (
constraint.constraintType === ConstraintType.ForeignKey &&
constraint.referencedClassID !== type.classID
) {
const referencedClass = context.getClass(constraint.referencedClassID);
if (referencedClass) {
const referencedAttributeNumber =
constraint.referencedAttributeNumbers[
constraint.tableAttributeNumbers.indexOf(
attribute.attributeNumber,
)
];
const referencedAttribute = referencedClass.attributes.find(
(a) => a.attributeNumber === referencedAttributeNumber,
);
if (referencedAttribute) {
const {DatabaseRecord} = printClassDetails(
referencedClass,
context,
);
return `${file.getImport(DatabaseRecord)}['${
referencedAttribute.attributeName
}']`;
}
const constraints = type.constraints.filter((c) =>
c.tableAttributeNumbers.includes(attribute.attributeNumber),
);
// First check if this attribute is a foreign key. If it is, write the type
// as a reference to that other table's attribute
for (const constraint of constraints) {
if (
constraint.constraintType === ConstraintType.ForeignKey &&
constraint.referencedClassID !== type.classID
) {
const referencedClass = context.getClass(constraint.referencedClassID);
if (referencedClass) {
const referencedAttributeNumber =
constraint.referencedAttributeNumbers[
constraint.tableAttributeNumbers.indexOf(attribute.attributeNumber)
];
const referencedAttribute = referencedClass.attributes.find(
(a) => a.attributeNumber === referencedAttributeNumber,
);
if (referencedAttribute) {
const {DatabaseRecord} = printClassDetails(referencedClass, context);
return `${file.getImport(DatabaseRecord)}['${
referencedAttribute.attributeName
}']`;
}
} else if (constraint.constraintType === ConstraintType.PrimaryKey) {
return handleBrand(type.className, attribute, context, file);
}
}
}
// If it's not a foreign key, check if it's a primary key.
// If it is a primary key, we may want to use a branded type.
for (const constraint of constraints) {
if (constraint.constraintType === ConstraintType.PrimaryKey) {
return handleBrand(type.className, attribute, context, file);
}
}
return context.getTypeScriptType(attribute.typeID, file);
}

Expand Down

0 comments on commit 61043da

Please sign in to comment.