Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] extended tables do not preserve @id's @default(autoincrement()) #1520

Closed
piscopancer opened this issue Jun 18, 2024 · 5 comments
Closed

Comments

@piscopancer
Copy link

piscopancer commented Jun 18, 2024

Bug

This operation fails (prisma throws an error)...

const res = await db.course.create({
  data: {
    title: 'English classes',
    tutorId: 2,
    students: {
      connect: [
        {
          id: 1,
        },
      ],
    },
    addedToNotifications: {
      createMany: {
        data: [
          {
            // fails here because due to a mismatch `id` is expected by prisma but typescript marks it as optional
            receiverId: 1,
            senderId: 2,
          },
        ],
      },
    },
  },
})
PrismaClientValidationError: 
Invalid `prisma.course.create()` invocation:

{
  data: {
    title: "English classes",
    tutorId: 2,
    students: {
      connect: [
        {
          id: 1
        }
      ]
    },
    addedToNotifications: {
      createMany: {
        data: [
          {
            delegate_aux_notification: {
              create: {
                type: "AddedToCourseNotification",
                receiverId: 1,
                senderId: 2
              }
            }
          }
        ]
      }
    }
  }
}

Argument `id` is missing.

... because generated prisma schema wrongly replicates id from the table it extends from. See the model for my MTI relations

schema.zmodel

model Notification {
  id         Int              @id @default(autoincrement())
  createdAt  DateTime         @default(now())
  type       NotificationType

  senderId   Int
  sender     User             @relation("user-notification-sent", fields: [senderId], references: [id], onDelete: Cascade)
  receiverId Int
  receiver   User             @relation("user-notification-received", fields: [receiverId], references: [id], onDelete: Cascade)

  @@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)
}

now take a look at the generated prisma.schema

prisma.schema

/// @@delegate(type)
model Notification {
  id                                     Int                        @id() @default(autoincrement())
  createdAt                              DateTime                   @default(now())
  type                                   NotificationType
  senderId                               Int
  sender                                 User                       @relation("user-notification-sent", fields: [senderId], references: [id], onDelete: Cascade)
  receiverId                             Int
  receiver                               User                       @relation("user-notification-received", fields: [receiverId], references: [id], onDelete: Cascade)
  delegate_aux_addedToGroupNotification  AddedToGroupNotification?
  delegate_aux_addedToCourseNotification AddedToCourseNotification?
}

model AddedToGroupNotification {
  id                        Int          @id()
  groupId                   Int          
  group                     Group        @relation(fields: [groupId], references: [id], onDelete: Cascade)
  delegate_aux_notification Notification @relation(fields: [id], references: [id], onDelete: Cascade, onUpdate: Cascade)
}

model AddedToCourseNotification {
  id                        Int          @id()
  courseId                  Int          
  course                    Course       @relation(fields: [courseId], references: [id], onDelete: Cascade)
  delegate_aux_notification Notification @relation(fields: [id], references: [id], onDelete: Cascade, onUpdate: Cascade)
}

As you can clearly see, id columns of AddedToGroupNotification and AddedToCourseNotification do not have parent's properties/functions, namely @default(autoincrement()). Because of this, the operation from the first code block fails even though typescript, generated by zenstack allows omitting id which is obviously an unexpected behavior and mismatch:

  • generated id does not have @default(autoincrement()) which means it is expected to be provided directly by me from the code,
  • typescript however displays id column as optional indicating that it is auto-generated, see the picture below

image

Here is a small video to give you a view from my perspective

Spotify_b1Qqq9RHPS.mp4

An attempt to fix it

Trying to explicitly provide the create operation with an id results in broken code

const res = await db.course.create({
  data: {
    title: 'English classes',
    tutorId: 2,
    students: {
      connect: [
        {
          id: 1,
        },
      ],
    },
    addedToNotifications: {
      createMany: {
        data: [
          {
            id: 1, // adding an explicit id, no typescript error though
            receiverId: 1,
            senderId: 2,
          },
        ],
      },
    },
  },
})

throws the following error

PrismaClientValidationError:
Invalid `prisma.course.create()` invocation:

{
  data: {
    title: "English classes",
    tutorId: 2,
    students: {
      connect: [
        {
          id: 1
        }
      ]
    },
    addedToNotifications: {
      createMany: {
        data: [
          {
            id: 1, 
            delegate_aux_notification: {
              create: {
                type: "AddedToCourseNotification",
                receiverId: 1,
                senderId: 2
              }
            }
          }
        ]
      }
    }
  }
}

Unknown argument `delegate_aux_notification`. Available options are marked with ?.

As you can see, id was not inserted where it was supposed to go, inside create object to join other fields like type, receiverId and senderId. I have no idea how to fix it atm

Setup

  • "@prisma/client": "^5.15.0",
  • "@zenstackhq/runtime": "^2.2.2",
  • Postgresql
@piscopancer
Copy link
Author

piscopancer commented Jun 19, 2024

Must be the duplicate of/similar to #1518.

@ymc9
Copy link
Member

ymc9 commented Jun 19, 2024

Hi @piscopancer , do you mind sharing the definition of the Course model in ZModel? I'd like to understand how it uses the polymorphic models.

@piscopancer
Copy link
Author

@ymc9 sure

model Course {
  id                   Int                         @id @default(autoincrement())
  createdAt            DateTime                    @default(now())
  title                String
  description          String?

  tutorId              Int
  tutor                User                        @relation("created-courses", fields: [tutorId], references: [id], onDelete: Cascade)
  groups               Group[]
  works                Work[]                      @relation("courses-works")
  students             User[]                      @relation("participated-courses")
  addedToNotifications AddedToCourseNotification[]
  worksStates          WorkState[]
  attempts             Attempt[]
}

@ymc9
Copy link
Member

ymc9 commented Jun 20, 2024

Hi @piscopancer , it should have been fixed in the v2.2.4 release. Could you upgrade and give it a try?

@ymc9 ymc9 closed this as completed Jun 20, 2024
@piscopancer
Copy link
Author

@ymc9 incredible! the command from above works now, thank you for maintaining this project winks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants