Closed
Description
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