From f4fdb1ab6f50cc977552346c330384f48ae5f077 Mon Sep 17 00:00:00 2001 From: Dylan Lundy <4567380+diesal11@users.noreply.github.com> Date: Sat, 22 Feb 2025 12:43:50 +1030 Subject: [PATCH] fix(schema): Provide a truncated name for unique constraints --- .../src/plugins/prisma/schema-generator.ts | 15 ++++- tests/regression/tests/issue-1992.test.ts | 65 +++++++++++++++++++ 2 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 tests/regression/tests/issue-1992.test.ts diff --git a/packages/schema/src/plugins/prisma/schema-generator.ts b/packages/schema/src/plugins/prisma/schema-generator.ts index 3c28e78a2..8df59941c 100644 --- a/packages/schema/src/plugins/prisma/schema-generator.ts +++ b/packages/schema/src/plugins/prisma/schema-generator.ts @@ -27,7 +27,6 @@ import { LiteralExpr, Model, NumberLiteral, - ReferenceExpr, StringLiteral, } from '@zenstackhq/language/ast'; import { getIdFields } from '@zenstackhq/sdk'; @@ -529,9 +528,15 @@ export class PrismaSchemaGenerator { if (found) { // replicate the attribute and replace the field reference with the new FK field const args: PrismaAttributeArgValue[] = []; + const fieldNames: string[] = []; for (const arg of fields.items) { - if (isReferenceExpr(arg) && arg.target.ref === origForeignKey) { + if (!isReferenceExpr(arg)) { + throw new PluginError(name, 'Unexpected field reference in @@unique attribute'); + } + + if (arg.target.ref === origForeignKey) { // replace + fieldNames.push(addedFkField.name); args.push( new PrismaAttributeArgValue( 'FieldReference', @@ -540,17 +545,21 @@ export class PrismaSchemaGenerator { ); } else { // copy + fieldNames.push(arg.target.$refText); args.push( new PrismaAttributeArgValue( 'FieldReference', - new PrismaFieldReference((arg as ReferenceExpr).target.$refText) + new PrismaFieldReference(arg.target.$refText) ) ); } } + const constraintName = this.truncate(`${dataModel.name}_${fieldNames.join('_')}_unique`); + model.addAttribute('@@unique', [ new PrismaAttributeArg(undefined, new PrismaAttributeArgValue('Array', args)), + new PrismaAttributeArg('map', new PrismaAttributeArgValue('String', constraintName)), ]); } } diff --git a/tests/regression/tests/issue-1992.test.ts b/tests/regression/tests/issue-1992.test.ts new file mode 100644 index 000000000..51715c3a5 --- /dev/null +++ b/tests/regression/tests/issue-1992.test.ts @@ -0,0 +1,65 @@ +import { loadSchema } from '@zenstackhq/testtools'; + +describe('issue 1992', () => { + it('regression', async () => { + await loadSchema( + ` + enum MyAppUserType { + Local + Google + Microsoft + } + + model MyAppCompany { + id String @id @default(cuid()) + name String + users MyAppUser[] + + userFolders MyAppUserFolder[] + } + + model MyAppUser { + id String @id @default(cuid()) + companyId String + type MyAppUserType + + @@delegate(type) + + company MyAppCompany @relation(fields: [companyId], references: [id]) + userFolders MyAppUserFolder[] + } + + model MyAppUserLocal extends MyAppUser { + email String + password String + } + + model MyAppUserGoogle extends MyAppUser { + googleId String + } + + model MyAppUserMicrosoft extends MyAppUser { + microsoftId String + } + + model MyAppUserFolder { + id String @id @default(cuid()) + companyId String + userId String + path String + name String + + @@unique([companyId, userId, name]) + @@unique([companyId, userId, path]) + + company MyAppCompany @relation(fields: [companyId], references: [id]) + user MyAppUser @relation(fields: [userId], references: [id]) + } + `, + { + provider: 'postgresql', + pushDb: false, + } + ); + }); +});