Skip to content

Commit bad89fb

Browse files
committed
fix(delegate): nested create/connect in delegate model requires reference fields
fixes #1894
1 parent 7fce0f0 commit bad89fb

File tree

2 files changed

+90
-5
lines changed

2 files changed

+90
-5
lines changed

packages/schema/src/plugins/prisma/schema-generator.ts

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -640,17 +640,49 @@ export class PrismaSchemaGenerator {
640640
(attr) => (attr as PrismaFieldAttribute).name !== '@relation'
641641
);
642642

643+
const relKeyPairs = getRelationKeyPairs(f);
644+
643645
if (
644646
// array relation doesn't need FK
645647
f.type.array ||
648+
// FK field is defined on this side
649+
relKeyPairs.length > 0 ||
646650
// opposite relation already has FK, we don't need to generate on this side
647651
(oppositeRelationAttr && getAttributeArg(oppositeRelationAttr, 'fields'))
648652
) {
649-
prismaField.attributes.push(
650-
new PrismaFieldAttribute('@relation', [
651-
new PrismaAttributeArg(undefined, new AttributeArgValue('String', relName)),
652-
])
653-
);
653+
const relationArgs = [new PrismaAttributeArg(undefined, new AttributeArgValue('String', relName))];
654+
const isSelfRelation = f.type.reference.ref === (f.$inheritedFrom ?? f.$container);
655+
if (relKeyPairs.length > 0 && !isSelfRelation) {
656+
// carry over "fields" and "references" args if not a self-relation
657+
relationArgs.push(
658+
new PrismaAttributeArg(
659+
'fields',
660+
new AttributeArgValue(
661+
'Array',
662+
relKeyPairs.map(
663+
(pair) =>
664+
new AttributeArgValue(
665+
'FieldReference',
666+
new PrismaFieldReference(pair.foreignKey.name)
667+
)
668+
)
669+
)
670+
)
671+
);
672+
relationArgs.push(
673+
new PrismaAttributeArg(
674+
'references',
675+
new AttributeArgValue(
676+
'Array',
677+
relKeyPairs.map(
678+
(pair) =>
679+
new AttributeArgValue('FieldReference', new PrismaFieldReference(pair.id.name))
680+
)
681+
)
682+
)
683+
);
684+
}
685+
prismaField.attributes.push(new PrismaFieldAttribute('@relation', relationArgs));
654686
} else {
655687
// generate FK field
656688
const oppositeModelIds = getIdFields(oppositeRelationField.$container as DataModel);
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { loadSchema } from '@zenstackhq/testtools';
2+
3+
describe('issue 1894', () => {
4+
it('regression', async () => {
5+
const { enhance } = await loadSchema(
6+
`
7+
model A {
8+
id Int @id @default(autoincrement())
9+
b B[]
10+
}
11+
12+
model B {
13+
id Int @id @default(autoincrement())
14+
a A @relation(fields: [aId], references: [id])
15+
aId Int
16+
17+
type String
18+
@@delegate(type)
19+
}
20+
21+
model C extends B {
22+
f String?
23+
}
24+
`,
25+
{
26+
enhancements: ['delegate'],
27+
compile: true,
28+
extraSourceFiles: [
29+
{
30+
name: 'main.ts',
31+
content: `
32+
import { enhance } from '.zenstack/enhance';
33+
import { PrismaClient } from '@prisma/client';
34+
35+
async function main() {
36+
const db = enhance(new PrismaClient());
37+
await db.a.create({ data: { id: 0 } });
38+
await db.c.create({ data: { a: { connect: { id: 0 } } } });
39+
}
40+
41+
main();
42+
43+
`,
44+
},
45+
],
46+
}
47+
);
48+
49+
const db = enhance();
50+
await db.a.create({ data: { id: 0 } });
51+
await expect(db.c.create({ data: { a: { connect: { id: 0 } } } })).toResolveTruthy();
52+
});
53+
});

0 commit comments

Comments
 (0)