Closed spencerbull closed 1 year ago
I had a quick update I wanted to provide. In my relationResolvers. I found that replacing the following findUnique
to findUniqueOrThrow
is now returning values. For a temporary fix, I'm updating the generated code.
Example of the change...
Generated Relation Resolvers
@TypeGraphQL.FieldResolver(_type => DimJobRole, {
nullable: false
})
async DimJobRole(@TypeGraphQL.Root() factJobRoleEvent: FactJobRoleEvent, @TypeGraphQL.Ctx() ctx: any, @TypeGraphQL.Info() info: GraphQLResolveInfo): Promise<DimJobRole> {
const { _count } = transformInfoIntoPrismaArgs(info);
return getPrismaFromContext(ctx).factJobRoleEvent.findUnique({
where: {
FactJobEventId: factJobRoleEvent.jobRoleEventId,
},
}).DimCalendar({
...(_count && transformCountFieldIntoSelectRelationsCount(_count)),
});
}
Updated Relation Resolvers
@TypeGraphQL.FieldResolver(_type => DimJobRole, {
nullable: false
})
async DimJobRole(@TypeGraphQL.Root() factJobRoleEvent: FactJobRoleEvent, @TypeGraphQL.Ctx() ctx: any, @TypeGraphQL.Info() info: GraphQLResolveInfo): Promise<DimJobRole> {
const { _count } = transformInfoIntoPrismaArgs(info);
return getPrismaFromContext(ctx).factJobRoleEvent.findUniqueOrThrow({
where: {
FactJobEventId: factJobRoleEvent.jobRoleEventId,
},
}).DimCalendar({
...(_count && transformCountFieldIntoSelectRelationsCount(_count)),
});
}
I would recommend not marking this issue as fixed, but I did want to highlight a path forward here with an update.
I am able to reproduce the issue ๐
However, after digging a bit I think you've discovered an issue in Prisma Client built-in data-loader ๐
Let's reproduce the issue:
Schema:
model DimJobRole {
JobRoleId BigInt @id @default(autoincrement())
JobFunctionName String @db.VarChar(128)
JobRoleEvents FactJobRoleEvent[]
}
model FactJobRoleEvent {
JobRoleEventId BigInt @id(map: "PK__1832492348")
JobRoleId BigInt
DimJobRole DimJobRole @relation(fields: [JobRoleId], references: [JobRoleId], onUpdate: NoAction, map: "FK_FactJobRoleEvents_DimJobRole")
}
Seed:
const [job1, job2, job3] = await Promise.all([
prisma.dimJobRole.create({
data: { JobFunctionName: "JobFunctionName 1" },
}),
prisma.dimJobRole.create({
data: { JobFunctionName: "JobFunctionName 2" },
}),
prisma.dimJobRole.create({
data: { JobFunctionName: "JobFunctionName 3" },
}),
]);
await Promise.all([
prisma.factJobRoleEvent.create({
data: {
JobRoleEventId: 1,
DimJobRole: {
connect: { JobRoleId: job1.JobRoleId },
},
},
}),
prisma.factJobRoleEvent.create({
data: {
JobRoleEventId: 2,
DimJobRole: {
connect: { JobRoleId: job1.JobRoleId },
},
},
}),
prisma.factJobRoleEvent.create({
data: {
JobRoleEventId: 3,
DimJobRole: {
connect: { JobRoleId: job2.JobRoleId },
},
},
}),
]);
Script 1 - await one by one:
const factJobRoleEvents = await prisma.factJobRoleEvent.findMany({
take: 3,
});
console.log(factJobRoleEvents);
for (const factJobRoleEvent of factJobRoleEvents) {
const dimJobRole = await prisma.factJobRoleEvent
.findUnique({
where: {
JobRoleEventId: factJobRoleEvent.JobRoleEventId,
},
})
.DimJobRole({});
console.log({dimJobRole});
}
Logs:
[
{ JobRoleEventId: 1n, JobRoleId: 23n },
{ JobRoleEventId: 2n, JobRoleId: 23n },
{ JobRoleEventId: 3n, JobRoleId: 22n }
]
{
dimJobRole: { JobRoleId: 23n, JobFunctionName: 'JobFunctionName 1' }
}
{
dimJobRole: { JobRoleId: 23n, JobFunctionName: 'JobFunctionName 1' }
}
{
dimJobRole: { JobRoleId: 22n, JobFunctionName: 'JobFunctionName 2' }
}
Script 2 - await Promise.all (like paralel field resolvers execution):
const factJobRoleEvents = await prisma.factJobRoleEvent.findMany({
take: 3,
});
console.log(factJobRoleEvents);
await Promise.all(
factJobRoleEvents.map(async factJobRoleEvent => {
const dimJobRole = await prisma.factJobRoleEvent
.findUnique({
where: {
JobRoleEventId: factJobRoleEvent.JobRoleEventId,
},
})
.DimJobRole({});
console.log({ dimJobRole });
}),
);
Logs:
[
{ JobRoleEventId: 1n, JobRoleId: 19n },
{ JobRoleEventId: 2n, JobRoleId: 19n },
{ JobRoleEventId: 3n, JobRoleId: 21n }
]
{ dimJobRole: null }
{ dimJobRole: null }
{ dimJobRole: null }
Script 3 - promise all + OrThrow:
const factJobRoleEvents = await prisma.factJobRoleEvent.findMany({
take: 3,
});
console.log(factJobRoleEvents);
await Promise.all(
factJobRoleEvents.map(async factJobRoleEvent => {
const dimJobRole = await prisma.factJobRoleEvent
.findUniqueOrThrow({
where: {
JobRoleEventId: factJobRoleEvent.JobRoleEventId,
},
})
.DimJobRole({});
console.log({ dimJobRole });
}),
);
Logs:
[
{ JobRoleEventId: 1n, JobRoleId: 25n },
{ JobRoleEventId: 2n, JobRoleId: 25n },
{ JobRoleEventId: 3n, JobRoleId: 26n }
]
{
dimJobRole: { JobRoleId: 25n, JobFunctionName: 'JobFunctionName 1' }
}
{
dimJobRole: { JobRoleId: 25n, JobFunctionName: 'JobFunctionName 1' }
}
{
dimJobRole: { JobRoleId: 26n, JobFunctionName: 'JobFunctionName 2' }
}
Reported in Prisma: https://github.com/prisma/prisma/issues/18326
But I will fix this issue by just using findUniqueOrThrow
- it's a proper way anyway, as the record has to exist as it was returned from a parent db query ๐
Fixed in 3ea20f6 - @spencerbull let me know if the fix does not work for you ๐
This looks great thanks!
Describe the Bug FindMany nested object queries are returning NULL for the Many-to-One query use case. For the example below, I have a database in a star schema with fact and dimension tables. The FindMany queries return valid children when making queries in a One-to-Many direction, but return NULL in a Many-to-one Direction.
To Reproduce Using typegraphql generator with basic configuration and simplified data model
Example query FindMany queries are returning null.
This query results in an error since DimJobRole cannot be null. I did confirm by making the following generated relations resolver nullable set to true. If the
take
parameter is set to1
, then the query resolves, if the query is set to>1
, then the query returns null for all children.Attached below in the logs section are the Prisma queries that are being run with verbose debug logs.
Expected Behavior When making a GraphQL findMany query in the direction of Many-to-One, the children should return valid objects corresponding the to the table.
Logs For
take
set to 1For
take
set to 2Environment:
typegraphql-prisma
version 0.24.2Aditional Context
Possibly similar to #248