diff --git a/packages/schema/src/plugins/prisma/schema-generator.ts b/packages/schema/src/plugins/prisma/schema-generator.ts index cdc37cc81..96a3b15f5 100644 --- a/packages/schema/src/plugins/prisma/schema-generator.ts +++ b/packages/schema/src/plugins/prisma/schema-generator.ts @@ -640,17 +640,49 @@ export class PrismaSchemaGenerator { (attr) => (attr as PrismaFieldAttribute).name !== '@relation' ); + const relKeyPairs = getRelationKeyPairs(f); + if ( // array relation doesn't need FK f.type.array || + // FK field is defined on this side + relKeyPairs.length > 0 || // opposite relation already has FK, we don't need to generate on this side (oppositeRelationAttr && getAttributeArg(oppositeRelationAttr, 'fields')) ) { - prismaField.attributes.push( - new PrismaFieldAttribute('@relation', [ - new PrismaAttributeArg(undefined, new AttributeArgValue('String', relName)), - ]) - ); + const relationArgs = [new PrismaAttributeArg(undefined, new AttributeArgValue('String', relName))]; + const isSelfRelation = f.type.reference.ref === (f.$inheritedFrom ?? f.$container); + if (relKeyPairs.length > 0 && !isSelfRelation) { + // carry over "fields" and "references" args if not a self-relation + relationArgs.push( + new PrismaAttributeArg( + 'fields', + new AttributeArgValue( + 'Array', + relKeyPairs.map( + (pair) => + new AttributeArgValue( + 'FieldReference', + new PrismaFieldReference(pair.foreignKey.name) + ) + ) + ) + ) + ); + relationArgs.push( + new PrismaAttributeArg( + 'references', + new AttributeArgValue( + 'Array', + relKeyPairs.map( + (pair) => + new AttributeArgValue('FieldReference', new PrismaFieldReference(pair.id.name)) + ) + ) + ) + ); + } + prismaField.attributes.push(new PrismaFieldAttribute('@relation', relationArgs)); } else { // generate FK field const oppositeModelIds = getIdFields(oppositeRelationField.$container as DataModel); diff --git a/tests/regression/tests/issue-1894.test.ts b/tests/regression/tests/issue-1894.test.ts new file mode 100644 index 000000000..e0ca79030 --- /dev/null +++ b/tests/regression/tests/issue-1894.test.ts @@ -0,0 +1,53 @@ +import { loadSchema } from '@zenstackhq/testtools'; + +describe('issue 1894', () => { + it('regression', async () => { + const { enhance } = await loadSchema( + ` + model A { + id Int @id @default(autoincrement()) + b B[] + } + + model B { + id Int @id @default(autoincrement()) + a A @relation(fields: [aId], references: [id]) + aId Int + + type String + @@delegate(type) + } + + model C extends B { + f String? + } + `, + { + enhancements: ['delegate'], + compile: true, + extraSourceFiles: [ + { + name: 'main.ts', + content: ` + import { enhance } from '.zenstack/enhance'; + import { PrismaClient } from '@prisma/client'; + + async function main() { + const db = enhance(new PrismaClient()); + await db.a.create({ data: { id: 0 } }); + await db.c.create({ data: { a: { connect: { id: 0 } } } }); + } + + main(); + + `, + }, + ], + } + ); + + const db = enhance(); + await db.a.create({ data: { id: 0 } }); + await expect(db.c.create({ data: { a: { connect: { id: 0 } } } })).toResolveTruthy(); + }); +});