Skip to content

Compound primary key + abstract models issue #1129

Closed
@Liam-Scott-Russell

Description

@Liam-Scott-Russell

Description

I cannot create an instance of a model when it has a compound primary key that is sourced from two abstract models. At runtime it fails to generate a valid select key for the create call, and then Prisma errors.

schema.zmodel

plugin prisma {
  provider = '@core/prisma'
  output = './schema.prisma'
  format = true
}

generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["metrics", "tracing", "views", "relationJoins"]
}

datasource db {
  provider = "postgresql"
  url      = env("PRISMA_DATABASE_URL")
}

model Relation1 {
  id String @db.Uuid @id @default(dbgenerated("gen_random_uuid()"))
  field1 String
  concrete Concrete[]
  @@allow('all', true)
}

model Relation2 {
  id String @db.Uuid @id @default(dbgenerated("gen_random_uuid()"))
  field2 String
  concrete Concrete[]
  @@allow('all', true)
}

abstract model WithRelation1 {
  relation1Id String @db.Uuid
  relation1 Relation1 @relation(fields: [relation1Id], references: [id])
}
abstract model WithRelation2 {
  relation2Id String @db.Uuid
  relation2 Relation2 @relation(fields: [relation2Id], references: [id])
}

model Concrete extends WithRelation1, WithRelation2 {
  concreteField String
  @@id([relation1Id, relation2Id])
  @@allow('all', true)
}

Script

import { PrismaClient } from '@prisma/client';
import { enhance } from '@zenstackhq/runtime';

const prisma = new PrismaClient({
  log: ['info'],
});

const db = enhance(prisma, {}, { logPrismaQuery: true });

db.$transaction(async (tx) => {
  await tx.relation2.createMany({
    data: [
      {
        field2: 'field2Value1',
      },
      {
        field2: 'field2Value2',
      },
    ],
  }),
    await tx.relation1.create({
      data: {
        field1: 'field1Value',
        concrete: {
          createMany: {
            data: [
              {
                concreteField: 'concreteFieldValue1',
                relation2Id: 'relation2Id1',
              },
              {
                concreteField: 'concreteFieldValue2',
                relation2Id: 'relation2Id2',
              },
            ],
          },
        },
      },
    });
}).then(console.log, console.error);

Logs

prisma:info Starting a postgresql pool with 17 connections.
prisma:info [policy] `create` relation1: {
  data: {
    field1: 'field1Value',
    concrete: {
      createMany: {
        data: [
          {
            concreteField: 'concreteFieldValue1',
            relation2Id: 'relation2Id1'
          },
          {
            concreteField: 'concreteFieldValue2',
            relation2Id: 'relation2Id2'
          }
        ]
      }
    }
  },
  select: { id: true, concrete: { select: {} } }
}
Error calling enhanced Prisma method `create`:
Invalid `prisma.relation1.create()` invocation:

{
  data: {
    field1: "field1Value",
    concrete: {
      createMany: {
        data: [
          {
            concreteField: "concreteFieldValue1",
            relation2Id: "relation2Id1"
          },
          {
            concreteField: "concreteFieldValue2",
            relation2Id: "relation2Id2"
          }
        ]
      }
    }
  },
  select: {
    id: true,
    concrete: {
      select: {
?       relation1Id?: true,
?       relation2Id?: true,
?       concreteField?: true,
?       relation1?: true,
?       relation2?: true
      }
    }
  }
}

The `select` statement for type Concrete must not be empty. Available options are marked with ?.
    at <anonymous> (<src>/repro.ts:21:24),
    at async Proxy._transactionWithCallback (<node_modules>/@prisma/client/runtime/library.js:128:9534) {
  name: 'PrismaClientValidationError',
  clientVersion: '5.10.2',
  internalStack: 'PrismaClientValidationError: \n' +
    'Invalid `prisma.relation1.create()` invocation:\n' +
    '\n' +
    '{\n' +
    '  data: {\n' +
    '    field1: "field1Value",\n' +
    '    concrete: {\n' +
    '      createMany: {\n' +
    '        data: [\n' +
    '          {\n' +
    '            concreteField: "concreteFieldValue1",\n' +
    '            relation2Id: "relation2Id1"\n' +
    '          },\n' +
    '          {\n' +
    '            concreteField: "concreteFieldValue2",\n' +
    '            relation2Id: "relation2Id2"\n' +
    '          }\n' +
    '        ]\n' +
    '      }\n' +
    '    }\n' +
    '  },\n' +
    '  select: {\n' +
    '    id: true,\n' +
    '    concrete: {\n' +
    '      select: {\n' +
    '?       relation1Id?: true,\n' +
    '?       relation2Id?: true,\n' +
    '?       concreteField?: true,\n' +
    '?       relation1?: true,\n' +
    '?       relation2?: true\n' +
    '      }\n' +
    '    }\n' +
    '  }\n' +
    '}\n' +
    '\n' +
    'The `select` statement for type Concrete must not be empty. Available options are marked with ?.\n' +
    '    at Cn (<node_modules>/@prisma/client/runtime/library.js:116:5888)\n' +
    '    at _n.handleRequestError (<node_modules>/@prisma/client/runtime/library.js:123:6510)\n' +
    '    at _n.handleAndLogRequestError (<node_modules>/@prisma/client/runtime/library.js:123:6188)\n' +
    '    at _n.request (<node_modules>/library.js:123:5896)\n' +
    '    at async l (<node_modules>/@prisma/client/runtime/library.js:128:10871)'

Expected

It should be sending:

relation1: {
  data: {
    field1: 'field1Value',
    concrete: {
      createMany: {
        data: [
          {
            concreteField: 'concreteFieldValue1',
            relation2Id: 'relation2Id1'
          },
          {
            concreteField: 'concreteFieldValue2',
            relation2Id: 'relation2Id2'
          }
        ]
      }
    }
  },
  select: { id: true, concrete: { select: { relation1Id: true, relation2Id: true } } }
}

Ideas

Computed ID Fields

I think that the error comes from these lines, specifically when generating the IDs for each model.

These are the ID fields from here

Relation1

[{"name":"id","type":"String","isId":true,"attributes":[{"name":"@db.Uuid","args":[]},{"name":"@id","args":[]},{"name":"@default","args":[]}]}]

ConcreteModel

[]

For some reason, there are no IDs here.

Environment

  • ZenStack version: zenstack 1.10.3 @zenstackhq/runtime 1.10.3 @zenstackhq/sdk 1.10.3
  • Prisma version: prisma 5.10.2 @prisma/client 5.8.1
  • Database type: Postgresql

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions