Skip to content

Commit

Permalink
fix(delegate): make sure nested createMany is converted into regula…
Browse files Browse the repository at this point in the history
…r `create`

Fixes #1520
  • Loading branch information
ymc9 committed Jun 20, 2024
1 parent 09ebea0 commit b039974
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 12 deletions.
43 changes: 31 additions & 12 deletions packages/runtime/src/enhancements/delegate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,11 @@ export class DelegateProxyHandler extends DefaultPrismaProxyHandler {
);
}

// note that we can't call `createMany` directly because it doesn't support
// nested created, which is needed for creating base entities
// `createMany` doesn't support nested create, which is needed for creating entities
// inheriting a delegate base, so we need to convert it to a regular `create` here.
// Note that the main difference is `create` doesn't support `skipDuplicates` as
// `createMany` does.

return this.queryUtils.transaction(this.prisma, async (tx) => {
const r = await Promise.all(
enumerate(args.data).map(async (item) => {
Expand Down Expand Up @@ -423,17 +426,33 @@ export class DelegateProxyHandler extends DefaultPrismaProxyHandler {
this.doProcessCreatePayload(model, args);
},

createMany: (model, args, _context) => {
if (args.skipDuplicates) {
throw prismaClientValidationError(
this.prisma,
this.options.prismaModule,
'`createMany` with `skipDuplicates` set to true is not supported for delegated models'
);
}
createMany: (model, args, context) => {
// `createMany` doesn't support nested create, which is needed for creating entities
// inheriting a delegate base, so we need to convert it to a regular `create` here.
// Note that the main difference is `create` doesn't support `skipDuplicates` as
// `createMany` does.

for (const item of enumerate(args?.data)) {
this.doProcessCreatePayload(model, item);
if (this.isDelegateOrDescendantOfDelegate(model)) {
if (args.skipDuplicates) {
throw prismaClientValidationError(
this.prisma,
this.options.prismaModule,
'`createMany` with `skipDuplicates` set to true is not supported for delegated models'
);
}

// convert to regular `create`
let createPayload = context.parent.create ?? [];
if (!Array.isArray(createPayload)) {
createPayload = [createPayload];
}

for (const item of enumerate(args.data)) {
this.doProcessCreatePayload(model, item);
createPayload.push(item);
}
context.parent.create = createPayload;
delete context.parent['createMany'];
}
},
});
Expand Down
70 changes: 70 additions & 0 deletions tests/regression/tests/issue-1520.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { loadSchema } from '@zenstackhq/testtools';

describe('issue 1520', () => {
it('regression', async () => {
const { enhance } = await loadSchema(
`
model Course {
id Int @id @default(autoincrement())
title String
addedToNotifications AddedToCourseNotification[]
}
model Group {
id Int @id @default(autoincrement())
addedToNotifications AddedToGroupNotification[]
}
model Notification {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
type String
senderId Int
receiverId Int
@@delegate (type)
}
model AddedToGroupNotification extends Notification {
groupId Int
group Group @relation(fields: [groupId], references: [id], onDelete: Cascade)
}
model AddedToCourseNotification extends Notification {
courseId Int
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
}
`,
{ enhancements: ['delegate'] }
);

const db = enhance();
const r = await db.course.create({
data: {
title: 'English classes',
addedToNotifications: {
createMany: {
data: [
{
id: 1,
receiverId: 1,
senderId: 2,
},
],
},
},
},
include: { addedToNotifications: true },
});

expect(r.addedToNotifications).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: 1,
courseId: 1,
receiverId: 1,
senderId: 2,
}),
])
);
});
});

0 comments on commit b039974

Please sign in to comment.