question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

P2016 since 2.11.0 when nested create and reference to same are within same query graph

See original GitHub issue

Bug description

With Prisma 2.10.0, it was possible to, within a single query graph, both create a nested record, and, make reference to the newly created record. With Prisma 2.11.0 and 2.12.0, this is broken.

How to reproduce

I created a sample on github that’s based on the TypeScript ‘scripts’ example within the prisma-samples project.

https://github.com/pbelbin/2020-11-25-Prisma-P2016-Bug

Check out the project, at the command line, use:

npm install
npm run dev

and you will see the error being reported.

eg:

Invalid `prisma.group.create()` invocation:


  Query interpretation error. Error for binding '4': AssertionError("[Query Graph] Expected a valid parent ID to be present for a nested connect on a one-to-many relation.")
    at PrismaClientFetcher.request (./node_modules/@prisma/client/runtime/index.js:79353:15)
    at processTicksAndRejections (internal/process/task_queues.js:93:5) {
  code: 'P2016',
  clientVersion: '2.12.0',
  meta: {
    details: `Error for binding '4': AssertionError("[Query Graph] Expected a valid parent ID to be present for a nested connect on a one-to-many relation.")`
  }
}

If you like, go into the package.json and change the version of Prisma back to 2.10.0, then use:

rm -rf node_modules
npm install
npm run dev

and you will see that there is no error.

Expected behavior

There should not be an error thrown, and, the records in the database should all get created.

Prisma information

schema.prisma:

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "sqlite"
  url      = "file:./dev.db"
}

model Group {
  id Int @id
  name String
  
  posts Post[]
}

model Post {
  id        Int     @default(autoincrement()) @id
  title     String
  content   String?
  published Boolean @default(false)
  author    User?   @relation(fields: [authorId], references: [id])
  authorId  Int?
  
  group Group? @relation(fields: [groupId], references: [id])
  groupId Int?
}

model User {
  id    Int     @id
  email String  @unique
  name  String?
  posts Post[]
}

sample code:

import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

// A `main` function so that we can use async/await
async function main() {
  // Delete existing data
  await prisma.user.deleteMany({});
  await prisma.post.deleteMany({});
  await prisma.group.deleteMany({});
  
  
  // Determine high# for authorID
  const newAuthorID = 1;
  
  
  // Create 2 posts by new user
  await prisma.group.create({
    data: {
      id: 20,
      name: 'Grp1',
      posts: {
        create: [
          {
            title: 'post x-1',
            content: 'Yabba dabba do!',
            author: {
              create: {
                id: newAuthorID,
                email: 'author1@testing.com',
                name: 'Fred Flintstone',
              }
            }
          },
          {
            title: 'post x-1',
            content: 'Yabba dabba do!',
            author: {
              connect: {
                id: newAuthorID,
              }
            }
          }
        ]
      }
    }
  });
}

main()
  .catch((e) => {
    console.error(e)
    process.exit(1)
  })
  .finally(async () => {
    await prisma.$disconnect()
  })

Environment & setup

  • OS: Mac OS 11.0.1
  • Database: SQLLite, MySQL
  • Node.js version: 14.15.1
  • Prisma version:
@prisma/cli          : 2.12.0
@prisma/client       : 2.12.0
Current platform     : darwin
Query Engine         : query-engine cf0680a1bfe8d5e743dc659cc7f08009f9587d58 (at node_modules/@prisma/engines/query-engine-darwin)
Migration Engine     : migration-engine-cli cf0680a1bfe8d5e743dc659cc7f08009f9587d58 (at node_modules/@prisma/engines/migration-engine-darwin)
Introspection Engine : introspection-core cf0680a1bfe8d5e743dc659cc7f08009f9587d58 (at node_modules/@prisma/engines/introspection-engine-darwin)
Format Binary        : prisma-fmt cf0680a1bfe8d5e743dc659cc7f08009f9587d58 (at node_modules/@prisma/engines/prisma-fmt-darwin)
Studio               : 0.322.0

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:3
  • Comments:8 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
pantharshit00commented, Dec 24, 2020

Prisma Engine is the internal component written in Rust used by Prisma Clients(Javascript and Go clients right now). You can find its code here: https://github.com/prisma/prisma-engines. You can find the compiled engine binary in the node_modules/.prisma/client/query-engine-xxx-xxx. Query engine is one of the engine components, migration and introspection is handled by other engine components which is in the @prisma/engines package.

image

So essentially the Prisma Client is just a wrapper around this engine. Clients send a wire protocol call to the engine over UDS right now and the engine decides how to execute the query, generate the relevant sql and return the executed result. The engine generates a query graph of your call and decides then it walks that graph generating sql and executing them over the database pool it has initialize during the startup. Right now in the graph, order of execution of connect and create is not guaranteed.

1reaction
mavileincommented, Dec 1, 2020

Yes the Engine has a responsibility to put the operations into the right order. But only within our defined semantics. There’s no concept of ordering creates before connects or so. That would significantly complicate our semantics imo.

The way to deal with the repetition is to extract it into a variable e.g.:

const theAuthor = {
    where: {
        id: newAuthorID,
    },
    create: {
        id: newAuthorID,
        email: "author1@testing.com",
        name: "Fred Flintstone",
    },
}

await prisma.group.create({
  data: {
    id: 20,
    name: "Grp1",
    posts: {
      create: [
        {
          title: "post x-1",
          content: "Yabba dabba do!",
          author: {
            connectOrCreate: theAuthor
          },
        },
        {
          title: "post x-2",
          content: "Yabba dabba do!",
          author: {
            connectOrCreate: theAuthor
          },
        },
      ],
    },
  },
});
Read more comments on GitHub >

github_iconTop Results From Across the Web

BigQuery release notes - Google Cloud
This page lists the latest release notes for features and updates to BigQuery.
Read more >
AWS X-Ray segment documents
Generate segment documents to send tracing information directly to X-Ray without using an SDK.
Read more >
The Graph on Twitter: "Querying subgraphs just got more ...
Querying subgraphs just got more powerful A highly-requested query feature is now live: Nested Queries. Subgraph devs can now filter by ...
Read more >
RDF Semantic Graph Developer's Guide - Oracle Help Center
Equivalent Property Graph and RDF Representations of the Same Graph ... SERVICE_JPDWN=T is a query optimizer hint for using nested loop join in...
Read more >
Release Notes — OSATE 2.11.0 documentation
Newly created instance model references elements in other resource set(s) (2241). Having the same property association as a contained ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found