Skip to content

Commit 54a9b21

Browse files
authored
fix(delegate): deleteMany fails when the model has compound id fields (#2004)
1 parent d42dc32 commit 54a9b21

File tree

2 files changed

+78
-2
lines changed

2 files changed

+78
-2
lines changed

packages/runtime/src/enhancements/node/delegate.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,15 +1106,32 @@ export class DelegateProxyHandler extends DefaultPrismaProxyHandler {
11061106
const entities = await db[model].findMany(findArgs);
11071107

11081108
// recursively delete base entities (they all have the same id values)
1109-
await Promise.all(entities.map((entity) => this.doDelete(db, model, { where: entity })));
1109+
1110+
await Promise.all(
1111+
entities.map((entity) => {
1112+
let deleteFilter = entity;
1113+
if (Object.keys(deleteFilter).length > 1) {
1114+
// if the model has compound id fields, we need to compose a compound key filter,
1115+
// otherwise calling Prisma's `delete` won't work
1116+
deleteFilter = this.queryUtils.composeCompoundUniqueField(model, deleteFilter);
1117+
}
1118+
return this.doDelete(db, model, { where: deleteFilter });
1119+
})
1120+
);
11101121

11111122
return { count: entities.length };
11121123
}
11131124

11141125
private async deleteBaseRecursively(db: CrudContract, model: string, idValues: any) {
11151126
let base = this.getBaseModel(model);
11161127
while (base) {
1117-
await db[base.name].delete({ where: idValues });
1128+
let deleteFilter = idValues;
1129+
if (Object.keys(idValues).length > 1) {
1130+
// if the model has compound id fields, we need to compose a compound key filter,
1131+
// otherwise calling Prisma's `delete` won't work
1132+
deleteFilter = this.queryUtils.composeCompoundUniqueField(base.name, deleteFilter);
1133+
}
1134+
await db[base.name].delete({ where: deleteFilter });
11181135
base = this.getBaseModel(base.name);
11191136
}
11201137
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { loadSchema } from '@zenstackhq/testtools';
2+
3+
describe('issue 1998', () => {
4+
it('regression', async () => {
5+
const { enhance } = await loadSchema(
6+
`
7+
model Entity {
8+
id String @id
9+
type String
10+
updatable Boolean
11+
children Relation[] @relation("children")
12+
parents Relation[] @relation("parents")
13+
14+
@@delegate(type)
15+
@@allow('create,read', true)
16+
@@allow('update', updatable)
17+
}
18+
19+
model A extends Entity {}
20+
21+
model B extends Entity {}
22+
23+
model Relation {
24+
parent Entity @relation("children", fields: [parentId], references: [id])
25+
parentId String
26+
child Entity @relation("parents", fields: [childId], references: [id])
27+
childId String
28+
29+
@@allow('create', true)
30+
@@allow('read', check(parent, 'read') && check(child, 'read'))
31+
@@allow('delete', check(parent, 'update') && check(child, 'update'))
32+
33+
@@id([parentId, childId])
34+
}
35+
`
36+
);
37+
38+
const db = enhance();
39+
40+
await db.a.create({ data: { id: '1', updatable: true } });
41+
await db.b.create({ data: { id: '2', updatable: true } });
42+
await db.relation.create({ data: { parentId: '1', childId: '2' } });
43+
44+
await expect(
45+
db.relation.deleteMany({
46+
where: { parentId: '1', childId: '2' },
47+
})
48+
).resolves.toEqual({ count: 1 });
49+
50+
await db.a.create({ data: { id: '3', updatable: false } });
51+
await db.b.create({ data: { id: '4', updatable: false } });
52+
await db.relation.create({ data: { parentId: '3', childId: '4' } });
53+
await expect(
54+
db.relation.deleteMany({
55+
where: { parentId: '3', childId: '4' },
56+
})
57+
).resolves.toEqual({ count: 0 });
58+
});
59+
});

0 commit comments

Comments
 (0)