Skip to content

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

Closed
@piscopancer

Description

@piscopancer

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions