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 5.0 Migration findUnique on @unique columns that are enums #20227

Closed
cdaz5 opened this issue Jul 14, 2023 · 16 comments · Fixed by prisma/prisma-engines#4072
Closed

Prisma 5.0 Migration findUnique on @unique columns that are enums #20227

cdaz5 opened this issue Jul 14, 2023 · 16 comments · Fixed by prisma/prisma-engines#4072
Assignees
Labels
5.0.0 bug/2-confirmed Bug has been reproduced and confirmed. kind/bug A reported bug. team/client Issue for team Client. topic: enum "type"/block `enum` topic: findUnique()
Milestone

Comments

@cdaz5
Copy link

cdaz5 commented Jul 14, 2023

Bug description

Given a schema:

enum FakeEnum {
  abc
  xyz
}

model Fake {
  id          String       @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  type        FakeEnum @unique
}

After migrating to 5.0 our findUnique call for the Fake model with type returns null. If i switch to findFirst it will return the correct row.

prisma.fake.findUnique({
  where: {
    type: FakeEnum.abc
  }
})

// this does not find the row but switching to findFirst does

How to reproduce

have a model that has a @unique field that is an enum and run a findUnique query against that column. Apologies if you're looking for a full repro I can try to put that together as well when I have more time, just wanted to get this report in asap.

Expected behavior

I would expect that given the schema and models above with a row in the database that has the type of abc a query like the below would return that row:

prisma.fake.findUnique({
  where: {
    type:  FakeEnum.abc
  }
})

Prisma information

enum FakeEnum {
  abc
  xyz
}

model Fake {
  id          String       @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  type        FakeEnum @unique
}
prisma.fake.findUnique({
  where: {
    type:  FakeEnum.abc
  }
})

Environment & setup

  • OS: macOS
  • Database: PostgreSQL
  • Node.js version: 19.7.0

Prisma Version

5.0.0
@cdaz5 cdaz5 added the kind/bug A reported bug. label Jul 14, 2023
@cdaz5 cdaz5 changed the title Prisma 5.0 Migration FindUnique on @unique columns that are enums Prisma 5.0 Migration findUnique on @unique columns that are enums Jul 14, 2023
@janpio janpio changed the title Prisma 5.0 Migration findUnique on @unique columns that are enums Prisma 5.0 Migration findUnique on @unique columns that are enums Jul 14, 2023
@janpio janpio added 5.0.0 team/client Issue for team Client. topic: enum "type"/block `enum` topic: findUnique() bug/0-unknown Bug is new, does not have information for reproduction or reproduction could not be confirmed. labels Jul 14, 2023
@imwexpex
Copy link

Same for us, the following code in Prisma 5 returns NULL, while the previous version of Prisma returns the correct value

await prisma.geoConfig.findUnique({
          where: {
            country_state: {
              country: Country.US,
              state: State.AK,
            },
          },
        }),

Schema

model GeoConfig {
  uuid String @id @db.Uuid

  country Country
  state   State

  enabled Boolean @default(true)

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  @@unique([country, state])
}

enum Country {
  US
}

enum State {
  AK
  // other US States
}

@janpio
Copy link
Member

janpio commented Jul 16, 2023

So findUnique in Prisma 5 can not filter by enum values any more in your experience?

Do Country.US and State.AK still return the correct value as expected?
Can you turn on query logging and debugging and post the full output you get please? Thanks.

@imwexpex
Copy link

@janpio

So findUnique in Prisma 5 can not filter by enum values any more in your experience? - Yes

Do Country.US and State.AK still return the correct value as expected? - Yes, from generated prisma client:

export const Country: {
  US: 'US',
};
export const State: {
  AK: 'AK',
}

Query log:

prisma:query SELECT "public"."GeoConfig"."uuid", "public"."GeoConfig"."country", "public"."GeoConfig"."state", "public"."GeoConfig"."minAge", "public"."GeoConfig"."enabled", "public"."GeoConfig"."createdAt", "public"."GeoConfig"."updatedAt", "public"."GeoConfig"."updatedBy" FROM "public"."GeoConfig" WHERE (("public"."GeoConfig"."country" = $1 AND "public"."GeoConfig"."state" = $2) AND 1=1) LIMIT $3 OFFSET $4

Client engine log:

  prisma:client  Prisma Client call: +1s
  prisma:client  prisma.geoConfig.findUnique({
  where: {
    country_state: {
      country: "US",
      state: "AK"
    }
  }
}) +0ms
  prisma:client  Generated request: +0ms
  prisma:client  {
  "modelName": "GeoConfig",
  "action": "findUnique",
  "query": {
    "arguments": {
      "where": {
        "country_state": {
          "country": "US",
          "state": "AK"
        }
      }
    },
    "selection": {
      "$composites": true,
      "$scalars": true
    }
  }
}

@imwexpex
Copy link

Spotted the issue. This happens if Prisma calls are inside the array Map function, and ONLY if the array has more than 1 element in it

image image

@imwexpex
Copy link

Prisma client even generates different sql Query

Query when array.length > 1:

prisma:query SELECT "public"."GeoConfig"."uuid", "public"."GeoConfig"."country", "public"."GeoConfig"."state", "public"."GeoConfig"."minAge", "public"."GeoConfig"."enabled", "public"."GeoConfig"."createdAt", "public"."GeoConfig"."updatedAt", "public"."GeoConfig"."updatedBy" FROM "public"."GeoConfig" WHERE (("public"."GeoConfig"."country" = $1 AND "public"."GeoConfig"."state" = $2) OR ("public"."GeoConfig"."country" = $3 AND "public"."GeoConfig"."state" = $4)) OFFSET $5

Query when array.length === 1:

prisma:query SELECT "public"."GeoConfig"."uuid", "public"."GeoConfig"."country", "public"."GeoConfig"."state", "public"."GeoConfig"."minAge", "public"."GeoConfig"."enabled", "public"."GeoConfig"."createdAt", "public"."GeoConfig"."updatedAt", "public"."GeoConfig"."updatedBy" FROM "public"."GeoConfig" WHERE (("public"."GeoConfig"."country" = $1 AND "public"."GeoConfig"."state" = $2) AND 1=1) LIMIT $3 OFFSET $4

@Jolg42 Jolg42 added bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. and removed bug/0-unknown Bug is new, does not have information for reproduction or reproduction could not be confirmed. labels Jul 17, 2023
@SevInf
Copy link
Contributor

SevInf commented Jul 17, 2023

Can confirm with the following schema:

model model {
  id       String   @id @default(uuid())
  category Category @unique
}

enum Category {
  A
  B
}

and the code:

async function main() {
  const prisma = new PrismaClient()
  await prisma.model.deleteMany()
  await prisma.model.create({
    data: { category: 'A' },
  })

  const results = await Promise.all([
    prisma.model.findUnique({ where: { category: 'A' } }),
    prisma.model.findUnique({ where: { category: 'B' } }),
  ])

  console.log(results)
}

Happens on 5.0.0 and 4.16.2 with jsonProtocol, does not happen with GraphQL.

@SevInf SevInf 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 Jul 17, 2023
@SevInf SevInf self-assigned this Jul 17, 2023
SevInf added a commit to prisma/prisma-engines that referenced this issue Jul 17, 2023
When JSON protocol is used and batching is happening, if the unique
value is enum, we incorrectly compared the results with the inputs:
inputs are PrismaValue::String, while outputs are PrismaValue::Enum.

Fix prisma/prisma#20227
@Jolg42 Jolg42 added this to the 5.1.0 milestone Jul 17, 2023
SevInf added a commit to prisma/prisma-engines that referenced this issue Jul 18, 2023
* qe: Fix batch results processing for enums

When JSON protocol is used and batching is happening, if the unique
value is enum, we incorrectly compared the results with the inputs:
inputs are PrismaValue::String, while outputs are PrismaValue::Enum.

Fix prisma/prisma#20227

* Fix mongo tests
@SevInf
Copy link
Contributor

SevInf commented Jul 18, 2023

Hello everyone. The fix is merged and will be a part of 5.1 release. If you want to test it before that, you can try 5.1.0-dev.15 development snapshot. We don't recommend using it in production, but it should be enough to ensure that fix works for you.

@imwexpex
Copy link

@SevInf thanks for the quick responses and fix! I can confirm that the bug is fixed in the 5.1.0-dev.15 development snapshot.

@jkepps
Copy link

jkepps commented Jul 25, 2023

@SevInf do we have an estimated timeline for the 5.1.0 release?

@Jolg42
Copy link
Member

Jolg42 commented Jul 25, 2023

@jkepps Yes! 5.1.0 release is planned for Tuesday, August 1st.

@gkkirsch
Copy link

gkkirsch commented Jul 25, 2023

Yikes, just running into this in production. I thought I was going crazy. We are getting nulls where we are expecting full records. This happens as soon as an enum is included in an index.
Channel is an ENUM.

  @@unique([userId, event, channel])

Thanks for jumping on this quickly.

For anyone getting this bug in production this could cause some pretty bad non intended consequences. In our example we could have sent notifications to all users that had their notifications turned off.

@SevInf Any chance we can we get a bug patch before August?

@imwexpex
Copy link

Yikes, just running into this in production. I thought I was going crazy. We are getting nulls where we are expecting full records. This happens as soon as an enum is included in an index.

Channel is an ENUM.


  @@unique([userId, event, channel])

Thanks for jumping on this quickly.

For anyone getting this bug in production this could cause some pretty bad non intended consequences. In our example we could have sent notifications to all users that had their notifications turned off.

@SevInf Any chance we can we get a bug patch before August?

You can downgrade to previous Prisma version and disable JSONprotocol as a workaround

@SevInf
Copy link
Contributor

SevInf commented Jul 26, 2023

@gkkirsch I too would suggest to hold off 5.x update until Tuesday in your case.

@maiconsanson

This comment was marked as resolved.

@Jolg42

This comment was marked as resolved.

@maiconsanson

This comment was marked as resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
5.0.0 bug/2-confirmed Bug has been reproduced and confirmed. kind/bug A reported bug. team/client Issue for team Client. topic: enum "type"/block `enum` topic: findUnique()
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants