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

fix: crdb enum casting error when executing the same prepared statement twice #4448

Merged
merged 6 commits into from
Nov 20, 2023

Conversation

Weakky
Copy link
Member

@Weakky Weakky commented Nov 15, 2023

Overview

fixes prisma/prisma#21901

I'm honestly unsure why exactly this fixes the issue as I'm still unsure why we had this error in the first place. There seemed to be an issue only on CRDB when executing the same prepared statement twice and truncating in the middle. The error was:

PREPARE s1 AS INSERT INTO "Test" ("id", "colors") VALUES ($1, ARRAY[$2::text]::"Color"[]);

EXECUTE s1(1, 'red');
TRUNCATE TABLE "Test" CASCADE;
EXECUTE s1(1, 'red');
ERROR:  placeholder $2 already has type string, cannot assign Color

The PR changes how we cast enum arrays:

PREPARE s1 AS INSERT INTO "Test" ("id", "colors") VALUES ($1, CAST($2::text[] AS "Color"[]));

Which seems to be fixing the CRDB error.

Copy link

codspeed-hq bot commented Nov 15, 2023

CodSpeed Performance Report

Merging #4448 will not alter performance

Comparing fix/enum-crdb-error (f4d396b) with main (4d2e008)

Summary

✅ 11 untouched benchmarks

@Weakky Weakky requested a review from a team as a code owner November 15, 2023 12:59
@Weakky Weakky requested review from miguelff and jkomyno and removed request for a team November 15, 2023 12:59
@Weakky Weakky added this to the 5.7.0 milestone Nov 15, 2023
@Weakky Weakky changed the title fix crdb enum caching fix crdb enum casting error when executing the same prepared statement twice Nov 15, 2023
@Weakky Weakky changed the title fix crdb enum casting error when executing the same prepared statement twice fix: crdb enum casting error when executing the same prepared statement twice Nov 15, 2023
Copy link
Contributor

@miguelff miguelff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find odd that we don't understand the root cause about why it fails. It feels like some kind of "cached" data that is wiped by the truncate statement, but other than speculation we don't understand the root cause, and that's a little bit concerning to me as well.

Nevertheless, If the regression is fixed, I think it's worth merging.

@AndrewSouthpaw
Copy link

Thanks for the fast work here! 😍

I'll flag this with the CRDB team as well, maybe one of their engineers can chime in about why this was an error.

@AndrewSouthpaw
Copy link

Here's their response:

Firstly, my apologies i'm not awfully familiar with Prisma so would like to try and reproduce this in isolation.

Is behaviour this happening when the statement is run against CRDB or only when utilising Prisma?

I was wondering if we could generate a statement bundle which captures the failure? This would be the best way to demonstrate to Engineering, if required, what is happening.

@Weakky
Copy link
Member Author

Weakky commented Nov 17, 2023

Hey @AndrewSouthpaw,

I was wondering if we could generate a statement bundle which captures the failure? This would be the best way to demonstrate to Engineering, if required, what is happening.

Yes we can. The queries I put above in the PR description is what enables to reproduce the failure. These queries have to be executed sequentially and it will error on the second EXECUTE.

PREPARE s1 AS INSERT INTO "Test" ("id", "colors") VALUES ($1, ARRAY[$2::text]::"Color"[]);

EXECUTE s1(1, 'red');
TRUNCATE TABLE "Test" CASCADE;
EXECUTE s1(1, 'red');

I also contacted the CockroachDB team and was planning to make an issue. Just so we don't create duplicates here, have you already created one? Thanks a lot for proactively reaching out to the CockroachDB team on your own though 🙏

@Weakky Weakky merged commit 7025c28 into main Nov 20, 2023
64 of 66 checks passed
@Weakky Weakky deleted the fix/enum-crdb-error branch November 20, 2023 12:28
@AndrewSouthpaw
Copy link

AndrewSouthpaw commented Nov 21, 2023

Went ahead and opened one here: cockroachdb/cockroach#114867. I had opened an internal ticket with them, but I agree it makes more sense to continue this discussion in an issue on their GitHub.

Thanks so much for the quick fix! Excited to try out 5.7.0 when it's released and finally upgrade prisma 💪🏼

@janpio
Copy link
Contributor

janpio commented Nov 21, 2023

If you are eager to try it out already, 5.7.0-dev.31 of prisma and @prisma/client should allow you to confirm the fix already. (Better don't use that in production though.)

@AndrewSouthpaw
Copy link

AndrewSouthpaw commented Nov 23, 2023

Hmm it looks like that hasn't solved the issue for us, we're able to repro with dev.31 and the latest dev.41.

image

Here's the salient bits of schema:

model User {
  adminRoles             AdminRoleType[]   @default([])
}

enum AdminRoleType {
  Admin
  ...
}

Code snippet:

describe("a", () => {
  it("foo", async () => {
    await prismaDb.user.create({ data: { adminRoles: [AdminRole.Admin] } });
  });
  it("bar", async () => {
    await prismaDb.user.create({ data: { adminRoles: [AdminRole.Admin] } });
  });
});

And the logs:

    [prisma:query] (3ms) INSERT INTO "public"."User" ("adminRoles","createdAt",...) VALUES (ARRAY[$1::text]::"public"."AdminRoleType"[],$2) RETURNING ... ["Admin","2023-11-23 02:31:14.801 UTC",...]
    [prisma:query] (9ms) SELECT tablename
                                                                            FROM pg_tables
                                                                            WHERE schemaname = 'public' []
    [prisma:query] (411ms) TRUNCATE TABLE ... CASCADE; []
    [prisma:query] (0ms) INSERT INTO "public"."User" ("adminRoles","createdAt",...) VALUES (ARRAY[$1::text]::"public"."AdminRoleType"[],$2) RETURNING ... ["Admin","2023-11-23 02:31:15.243 UTC",...]

(error)

@Weakky
Copy link
Member Author

Weakky commented Nov 30, 2023

Hey @AndrewSouthpaw,

The SQL snippets you have posted suggest that you are not using the fix, so I'm a little confused.

If you look at the PR description, the new casting syntax should be:

VALUES (CAST($1::$text[] AS "public"."AdminRoleType"[]))

But your engine is still rendering:

VALUES (ARRAY[$1::text]::"public"."AdminRoleType"[])

I'm not sure if that's because you have some caching issues going on or if it's because of something else.

May I ask you, if you haven't done that already, to prune/delete your node_modules and reinstall everything? It's not uncommon after client updates that some components (engine/client/cli) don't update correctly.

Thank you 🙏

@AndrewSouthpaw
Copy link

AndrewSouthpaw commented Dec 4, 2023

Hmm, I've tried deleting and recreating my node_modules. I've confirmed I'm running on ~5.7.0-dev.41, which translates to "version": "5.7.0-integration-refactor-consistently-use-binarytarget-term.1", for @prisma/engines. Still the same issue though. Same if I bump up to ~5.7.0-dev.95.

@janpio
Copy link
Contributor

janpio commented Dec 5, 2023

Don't use ~ for the dev versions, use exactly the latest one. npm install prisma@dev @prisma/client@dev should give you that, and if not remove any additional characters. Confirm what you are running with prisma -v.

@AndrewSouthpaw
Copy link

Confirmed, that fixes the issue! Thanks for the fix 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants