Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prisma Client upsert returns count instead of data #10935

Closed
Tracked by #11441
gt-codes opened this issue Jan 3, 2022 · 42 comments
Closed
Tracked by #11441

Prisma Client upsert returns count instead of data #10935

gt-codes opened this issue Jan 3, 2022 · 42 comments
Assignees
Labels
bug/2-confirmed Bug has been reproduced and confirmed. kind/bug A reported bug. team/client Issue for team Client. topic: client api topic: database-provider/planetscale topic: relationMode formerly `referentialIntegrity` topic: upsert()

Comments

@gt-codes
Copy link

gt-codes commented Jan 3, 2022

Bug description

When using the upsert method to do a findOrCreate implementation, count: { 1 } is returned rather than the data itself.

How to reproduce

Using the following code returns count rather than the user object

const user = await prisma.user.upsert({
  where: { email: emails[0].value },
  update: { lastLoggedIn: new Date() },
  create: {
    email: emails[0].value,
    name: displayName,
    avi: photos[0].value,
    profile: {
      create: {
        name: displayName,
        avi: photos[0].value,
        email: emails[0].value,
      },
    },
  },
});

console.log({ user });

Expected behavior

I expect the user's data to be returned.

Prisma information

model User {
  id           String   @id @default(uuid())
  email        String   @unique
  name         String
  avi          String?
  createdAt    DateTime @default(now())
  updatedAt    DateTime @updatedAt
  lastLoggedIn DateTime @default(now())

  log           Log[]
  items         Item[]
  rsvps         Rsvp[]   @relation("rsvp_user")
  createdEvents Event[]  @relation(name: "created_event")
  profile       Profile? @relation("profile_user")
}

Environment & setup

  • OS: Mac OS
  • Database: MySQL
  • Node.js version: v14.17.3

Prisma Version

prisma                  : 3.6.0
@prisma/client          : 3.7.0
@gt-codes gt-codes added the kind/bug A reported bug. label Jan 3, 2022
@janpio janpio added bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. team/client Issue for team Client. topic: client api labels Jan 3, 2022
@gt-codes
Copy link
Author

gt-codes commented Jan 3, 2022

@janpio Yes, I referenced this documentation. What do I need to do on my end to fix this issue?

@pantharshit00
Copy link
Contributor

I am unable to reproduce this. Can you please make sure that you are using upsert and not upsertMany? That is the method which returns the count.

@pantharshit00 pantharshit00 added bug/0-unknown Bug is new, does not have information for reproduction or reproduction could not be confirmed. and removed bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. labels Jan 4, 2022
@gt-codes
Copy link
Author

gt-codes commented Jan 9, 2022

@pantharshit00 My exact code is in the issue description, I'm not using upsertMany.

@pantharshit00
Copy link
Contributor

As I previously mentioned, I am unable to reproduce this:

image

Can you share a reproduction inside of a git repository so that we can have a more reliable example of the problem?

@gt-codes
Copy link
Author

From a conversation I had with @ruheni, here are the logs from the query in this issues description. I got these logs from new PrismaClient({ log: ['query', 'info'] }). I hope this provides more inisght into what's going on @pantharshit00

prisma:info Starting a mysql pool with 17 connections.
prisma:query BEGIN
prisma:query SELECT `venir`.`User`.`id` FROM `venir`.`User` WHERE `venir`.`User`.`email` = ?
prisma:query SELECT `venir`.`Item`.`id`, `venir`.`Item`.`ownerId` FROM `venir`.`Item` WHERE (1=1 AND `venir`.`Item`.`ownerId` IN (?))
prisma:query SELECT `venir`.`Log`.`id`, `venir`.`Log`.`userId` FROM `venir`.`Log` WHERE (1=1 AND `venir`.`Log`.`userId` IN (?))
prisma:query SELECT `venir`.`Rsvp`.`id`, `venir`.`Rsvp`.`userId` FROM `venir`.`Rsvp` WHERE (1=1 AND `venir`.`Rsvp`.`userId` IN (?))
prisma:query SELECT `venir`.`Event`.`id`, `venir`.`Event`.`hostId` FROM `venir`.`Event` WHERE (1=1 AND `venir`.`Event`.`hostId` IN (?))
prisma:query SELECT `venir`.`Item`.`id`, `venir`.`Item`.`eventId` FROM `venir`.`Item` WHERE (1=1 AND `venir`.`Item`.`eventId` IN (?,?))
prisma:query SELECT `venir`.`Log`.`id`, `venir`.`Log`.`eventId` FROM `venir`.`Log` WHERE (1=1 AND `venir`.`Log`.`eventId` IN (?,?))
prisma:query SELECT `venir`.`Rsvp`.`id`, `venir`.`Rsvp`.`eventId` FROM `venir`.`Rsvp` WHERE (1=1 AND `venir`.`Rsvp`.`eventId` IN (?,?))
prisma:query SELECT `venir`.`Profile`.`id`, `venir`.`Profile`.`userId` FROM `venir`.`Profile` WHERE (1=1 AND `venir`.`Profile`.`userId` IN (?))
prisma:query SELECT `venir`.`User`.`id` FROM `venir`.`User` WHERE `venir`.`User`.`email` = ?
prisma:query UPDATE `venir`.`User` SET `lastLoggedIn` = ?, `updatedAt` = ? WHERE `venir`.`User`.`id` IN (?)
prisma:query SELECT `venir`.`User`.`id`, `venir`.`User`.`email`, `venir`.`User`.`name`, `venir`.`User`.`avi`, `venir`.`User`.`createdAt`, `venir`.`User`.`updatedAt`, `venir`.`User`.`lastLoggedIn` FROM `venir`.`User` WHERE `venir`.`User`.`id` = ? LIMIT ? OFFSET ?
prisma:query COMMIT
{ user: { count: 0 } }

prisma:info Starting a mysql pool with 17 connections.
prisma:query SELECT `venir`.`Event`.`id`, `venir`.`Event`.`hostId`, `venir`.`Event`.`name`, `venir`.`Event`.`settingsId`, `venir`.`Event`.`isoDate`, `venir`.`Event`.`location`, `venir`.`Event`.`createdAt`, `venir`.`Event`.`updatedAt` FROM `venir`.`Event` WHERE 1=1 ORDER BY `venir`.`Event`.`updatedAt` DESC
prisma:query SELECT `venir`.`Rsvp`.`id`, `venir`.`Rsvp`.`userId`, `venir`.`Rsvp`.`eventId`, `venir`.`Rsvp`.`response`, `venir`.`Rsvp`.`createdAt`, `venir`.`Rsvp`.`updatedAt` FROM `venir`.`Rsvp` WHERE `venir`.`Rsvp`.`eventId` IN (?,?)
There was an error running the data loader for route routes/__auth
Error: 
Invalid `prisma.user.findUnique()` invocation in
./api/build/index.js:679:34

./app/routes/__auth.tsx
   677 var loader = async ({ request }) => {
   678   const _user = await auth(request, { failureRedirect: "/login" });
→  679   const user = await prisma.user.findUnique({
           where: {
         ?   id?: String,
         ?   email?: String
           },
           include: {
             profile: true
           }
         })

Argument where of type UserWhereUniqueInput needs at least one argument. Available args are listed in green.

Note: Lines with ? are optional.

    at Object.validate (./node_modules/@prisma/client/runtime/index.js:34755:20)
    at PrismaClient._executeRequest (./node_modules/@prisma/client/runtime/index.js:39749:17)
    at consumer (./node_modules/@prisma/client/runtime/index.js:39690:23)
    at ./node_modules/@prisma/client/runtime/index.js:39694:49
    at AsyncResource.runInAsyncScope (node:async_hooks:199:9)
    at PrismaClient._request (./node_modules/@prisma/client/runtime/index.js:39694:27)
    at request (./node_modules/@prisma/client/runtime/index.js:39799:77)
    at _callback (./node_modules/@prisma/client/runtime/index.js:40007:14)
    at PrismaPromise.then (./node_modules/@prisma/client/runtime/index.js:40014:23)

@uvalus
Copy link

uvalus commented Jan 11, 2022

I've discovered that if you use upsert (when creating a record) it behaves as expected.
However if you use upsert to update a record it returns the { count: number } response.

This was first noted under Prisma 3.6.0 and still persists under 3.8.0.
Version 3.5.0 behaves as expected so something must have changed between those versions.

const dbUser = await prismaClient.user.upsert({
  where: {
    email: args.email
  },
  update: {
    name: args.name,
    email: args.email,
  },
  create: {
    name: args.name,
    email: args.email,
  },
});

console.log(dbUser);

Returns

{ count: 0 }

on an update

But it returns:

{
  id: 169,
  created_at: 2022-01-11T22:59:13.844Z,
  updated_at: 2022-01-11T22:59:13.844Z,
  name: 'test user 2',
  email: 'test2@test.com'
}

When creating data for the first time

@pantharshit00
Copy link
Contributor

I am still unable to reproduce this. I tried last 3 versions and still wasn't able to reproduce. Can you please maybe share a git repo with a script and the schema which reproduces this? I think it might be related to schema structure as well.

@uvalus
Copy link

uvalus commented Jan 17, 2022

What sort of schema structures would likely cause this ?
Question - would the response be erroneously computing the number of relations the user is a part of instead of returning the affected record ?

BTW I've had to work around the issue by doing an explicit find / create / update so my code works as expected now.

Even if I changed a value with the update (using the upsert command) e.g. the updated_at property to be new Date() it still behaved incorrectly (as mentioned in my previous post).

@flybayer
Copy link

flybayer commented Jan 21, 2022

We're also experiencing this issue in production with v3.8.1. It was working fine on v3.5.0.

I can share my schema privately if it would help.

@nkrekow
Copy link

nkrekow commented Jan 25, 2022

also running into this issue (v3.8.1, mysql)...when creating a new entry upsert returns the expected data. if a record already exists matching there where it returns a count. however, if the record already exists and i use findUnique() with the same where: and select: as upsert i get the data im expecting to get

export async function login(body) {
    let { email, name, image } = body

    // the return statement below works as expected if a new record is created, 
    // otherwise if a matching record exists im just getting count back instead of what is in select
    // like i do if its a new record created
    return await db.user.upsert({
        where: { email: email },
        select: { id: true, name: true, image: true },
        update: { name, image },
        create: { email, name, image }
    })

    // if the record already exists and i use findUnique instead the correct information is 
    // returned instead of "count"
    return await db.user.findUnique({
        where: { email },
        select: { id: true, name: true, image: true }
    })
}

here is the model its pulling from

model User {
  id            String    @id @default(cuid())
  name          String?
  email         String    @unique
  image         String?
  createdAt     DateTime  @default(now())
  updatedAt     DateTime  @updatedAt
  sessions      Session[]
}

@pantharshit00
Copy link
Contributor

@nkrekow

image

I tried the above and still wasn't able to reproduce this. Can you please tell me the exact MySQL version you are using?

@pantharshit00
Copy link
Contributor

@uvalus It might be schema parser which is creating the wrong query graph so I was asking for this. I still unable to trigger this so if you share a minimal example which can reproduce the problem consistently, please share it.

@nkrekow
Copy link

nkrekow commented Jan 25, 2022

@pantharshit00 this is on PlanetScale and it looks like they're using mysql version 8.0.23

@uvalus
Copy link

uvalus commented Jan 25, 2022

Can confirm, I am using PlanetScale as well

@flybayer
Copy link

Also using Planetscale

@janpio
Copy link
Member

janpio commented Jan 25, 2022

(Noice, seems we are getting somewhere here)
Do you also all have the referentialIntegrity preview feature with referentialIntegrity = prisma enabled?

@uvalus
Copy link

uvalus commented Jan 25, 2022

Yes

@nkrekow
Copy link

nkrekow commented Jan 25, 2022

yup!
CleanShot 2022-01-25 at 10 22 04@2x

@janpio
Copy link
Member

janpio commented Jan 27, 2022

I can not reproduce this on PlanetScale with referentialIntegrity = "prisma" enabled:

C:\Users\Jan\Documents\throwaway\10935>node script.js     
users before []
upsert1 { id: 'ckyx13p1q0002dgs2vi5ifpmy', name: 'test', image: 'sf' }
upsert2 { id: 'ckyx13p1q0002dgs2vi5ifpmy', name: '123', image: '456' }
users after [
  {
    id: 'ckyx13p1q0002dgs2vi5ifpmy',
    name: '123',
    email: 'test',
    image: '456',
    createdAt: 2022-01-27T13:45:17.198Z,
    updatedAt: 2022-01-27T13:45:18.121Z
  }
]

For this code:

const { PrismaClient } = require('@prisma/client')

const prisma = new PrismaClient()

async function login(body) {

  let { email, name, image } = body

  return await prisma.user.upsert({
    where: { email: email },
    select: { id: true, name: true, image: true },
    update: { name, image },
    create: { email, name, image }
  })
}

async function main() {

  console.log("users before", await prisma.user.findMany({}))

  let body1 = { email: "test", name: "test", image: "sf" }
  let body2 = { email: "test", name: "123", image: "456" }

  console.log("upsert1", await login(body1))
  console.log("upsert2", await login(body2))

  console.log("users after", await prisma.user.findMany({}))

}

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

and schema:

generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["referentialIntegrity"]
}

datasource db {
  provider             = "mysql"
  url                  = env("DATABASE_URL")
  referentialIntegrity = "prisma"
}

model User {
  id        String   @id @default(cuid())
  name      String?
  email     String   @unique
  image     String?
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

Am I missing something?
Can you double check and compare with your schemas what could be different?

@gt-codes Is your Invalid prisma.user.findUnique() invocation error in your log related, and a follow up of it not returning the data? Can you add console.log of the upsert result as I did to your app and run these logs again please?

@janpio janpio mentioned this issue Jan 27, 2022
35 tasks
@ramiel
Copy link

ramiel commented Feb 15, 2022

I can confirm I have the same issue. My configuration is for planetscale, but locally I'm using normal Mysql and can expeience the same problem

@janpio janpio added the bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. label Feb 24, 2022
@ramiel
Copy link

ramiel commented Feb 25, 2022

So, yesterday I wasn't able to reproduce that behavior, as long as I tried. I checked with the same version I'm using (3.9.2). I'll keep trying but maybe @ItzDerock code is enough?

@pantharshit00
Copy link
Contributor

Can other people as well here try the latest version and report back?

@ramiel
Copy link

ramiel commented Feb 26, 2022

So, here there's a reproduction repository based on @ItzDerock code but with the configuration for Mysql/Planet scale.
The issue is present when the update is executed, so to reproduce it you need to run npm run dev twice. I used version 3.10.0

https://github.com/ramiel/prisma-issue-10935

Screenshot_20220226_154643

@ramiel
Copy link

ramiel commented Mar 13, 2022

Any news on this?

@janpio
Copy link
Member

janpio commented Mar 13, 2022

We are still waiting for a confirmed reproduction. (Feel free to try the one posted in the comment above and let us know if this works - that will save us some time.)

@ramiel
Copy link

ramiel commented Mar 13, 2022

I provided a repository with the reproducible error a couple of comments above. Haven't you tried it? Did you try and it's working for you instead?

@janpio
Copy link
Member

janpio commented Mar 13, 2022

Oh sorry, I missed that it was you who posted that - this way my message of course does not make a lot of sense.
We did not have the time to appraoch that reproduction yet unfortunately. If anyone else can confirm the reproduction reproduces, that would be helpful.

@cdinu
Copy link

cdinu commented Mar 28, 2022

@janpio, I can confirm that the reproduction reproduces. Is it helpful?

@janpio janpio added bug/2-confirmed Bug has been reproduced and confirmed. and removed bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. labels Apr 2, 2022
@janpio
Copy link
Member

janpio commented Apr 2, 2022

I can indeed confirm this as well now in the context of referentialIntegrity = "prisma" for the referentialIntegrity preview feature - when a child model is connected to the model you are updating.

@ponei
Copy link

ponei commented Apr 21, 2022

Can also confirm this; using PlanetScale on production but also happens locally with MySQL
Returns fine if the identifier doesn't exist, but if it does it just returns {"count": number}

datasource db {
  provider             = "mysql"
  url                  = env("DATABASE_URL")
  referentialIntegrity = "prisma"
}

generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["referentialIntegrity", "interactiveTransactions"]
}

@ramiel
Copy link

ramiel commented May 16, 2022

Any news on this?

@dpetrick
Copy link
Contributor

dpetrick commented Aug 3, 2022

I'm unable to reproduce this issue on Prisma 4.1. Reopen please if you still run into the same issue after upgrading.

@janpio
Copy link
Member

janpio commented Aug 3, 2022

I can confirm that this does not reproduce any more with 4.1:

PS C:\Users\Jan\Documents\throwaway\prisma-issue-10935> npm run dev

> dev
> ts-node ./script.ts

{
  id: 1,
  email: 'email@person.com',
  name: 'Derock',
  bio: 'cool person'
}
PS C:\Users\Jan\Documents\throwaway\prisma-issue-10935> npm run dev

> dev
> ts-node ./script.ts

{
  id: 1,
  email: 'email@person.com',
  name: 'Derock',
  bio: 'cool person'
}

PS C:\Users\Jan\Documents\throwaway\prisma-issue-10935> npx prisma -v
Environment variables loaded from .env
prisma                  : 4.1.1
@prisma/client          : 4.1.1
Current platform        : windows
Query Engine (Node-API) : libquery-engine 8d8414deb360336e4698a65aa45a1fbaf1ce13d8 (at node_modules\@prisma\engines\query_engine-windows.dll.node)
Migration Engine        : migration-engine-cli 8d8414deb360336e4698a65aa45a1fbaf1ce13d8 (at node_modules\@prisma\engines\migration-engine-windows.exe)       
Introspection Engine    : introspection-core 8d8414deb360336e4698a65aa45a1fbaf1ce13d8 (at node_modules\@prisma\engines\introspection-engine-windows.exe)     
Format Binary           : prisma-fmt 8d8414deb360336e4698a65aa45a1fbaf1ce13d8 (at node_modules\@prisma\engines\prisma-fmt-windows.exe)
Default Engines Hash    : 8d8414deb360336e4698a65aa45a1fbaf1ce13d8
Studio                  : 0.469.0
Preview Features        : referentialIntegrity

Can you please confirm @ramiel @ponei @cdinu @ItzDerock etc?

@sarthaksaklecha
Copy link

The issue still reproduces. Upsert, when updating is returning { count : number }

@janpio
Copy link
Member

janpio commented Feb 19, 2024

Please open a new issue with a full reproduction if you still get this problem with a recent version of Prisma. We will not further investigate this in this closed issue from 2022. Thank you.

@GilbertoTomasone
Copy link

I faced a similar problem. However, in my experience, the return format { count: number } occurred exclusively when the update object included the primary key. Works fine with unique keys.

@joshbedo
Copy link

joshbedo commented Mar 27, 2024

Running into the same issue using mysql. if it doesnt exist it returns the record if it exists it returns a count of updated records.

Prisma ^5.9.1

datasource db {
  provider     = "mysql"
  url          = env("DATABASE_URL")
  relationMode = "prisma"
}

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

@janpio
Copy link
Member

janpio commented Mar 27, 2024

Please open a new issue with a full reproduction if you still get this problem with a recent version of Prisma. We will not further investigate this in this closed issue from 2022. Thank you.

@prisma prisma locked as resolved and limited conversation to collaborators Mar 27, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug/2-confirmed Bug has been reproduced and confirmed. kind/bug A reported bug. team/client Issue for team Client. topic: client api topic: database-provider/planetscale topic: relationMode formerly `referentialIntegrity` topic: upsert()
Projects
None yet
Development

No branches or pull requests