From 6dfb20ab5747b84114054ab09c4c233afaa57a91 Mon Sep 17 00:00:00 2001 From: jkomyno Date: Tue, 16 Jan 2024 12:58:07 +0100 Subject: [PATCH 1/5] feat(driver-adapters): fix bigint handling on creation and filter --- .../tests/new/regressions/max_integer.rs | 2 ++ .../tests/writes/data_types/bigint.rs | 6 +----- .../tests/writes/data_types/native_types/postgres.rs | 8 ++------ .../driver-adapters/src/wasm/adapter_method.rs | 11 +++++++---- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/regressions/max_integer.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/regressions/max_integer.rs index e00b2d22e198..3eee8d0d4aee 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/regressions/max_integer.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/new/regressions/max_integer.rs @@ -187,6 +187,8 @@ mod max_integer { schema.to_owned() } + // Info: `driver-adapters` are currently excluded because they yield a different error message, + // coming straight from the database. #[connector_test( schema(overflow_pg), only(Postgres), diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/bigint.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/bigint.rs index c78b522f4994..469ebd227d49 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/bigint.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/bigint.rs @@ -17,11 +17,7 @@ mod bigint { } // "Using a BigInt field" should "work" - #[connector_test(exclude( - Postgres("pg.js.wasm", "neon.js.wasm"), - Sqlite("libsql.js.wasm"), - Vitess("planetscale.js.wasm") - ))] + #[connector_test()] async fn using_bigint_field(runner: Runner) -> TestResult<()> { insta::assert_snapshot!( run_query!(&runner, r#"mutation { diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/native_types/postgres.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/native_types/postgres.rs index 2a83d17f6fb7..d1f17ad35863 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/native_types/postgres.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/native_types/postgres.rs @@ -23,7 +23,7 @@ mod postgres { } //"Postgres native int types" should "work" - #[connector_test(schema(schema_int), only(Postgres), exclude(Postgres("pg.js.wasm", "neon.js.wasm")))] + #[connector_test(schema(schema_int), only(Postgres))] async fn native_int_types(runner: Runner) -> TestResult<()> { insta::assert_snapshot!( run_query!(&runner, r#"mutation { @@ -191,11 +191,7 @@ mod postgres { } // "Other Postgres native types" should "work" - #[connector_test( - schema(schema_other_types), - only(Postgres), - exclude(CockroachDb, Postgres("pg.js.wasm", "neon.js.wasm")) - )] + #[connector_test(schema(schema_other_types), only(Postgres), exclude(CockroachDb))] async fn native_other_types(runner: Runner) -> TestResult<()> { insta::assert_snapshot!( run_query!(&runner, r#"mutation { diff --git a/query-engine/driver-adapters/src/wasm/adapter_method.rs b/query-engine/driver-adapters/src/wasm/adapter_method.rs index a66afeca4c5a..0e405bd30580 100644 --- a/query-engine/driver-adapters/src/wasm/adapter_method.rs +++ b/query-engine/driver-adapters/src/wasm/adapter_method.rs @@ -11,10 +11,13 @@ use super::error::into_quaint_error; use super::from_js::FromJsValue; use crate::AdapterResult; -// `serialize_missing_as_null` is required to make sure that "empty" values (e.g., `None` and `()`) -// are serialized as `null` and not `undefined`. -// This is due to certain drivers (e.g., LibSQL) not supporting `undefined` values. -pub(crate) static SERIALIZER: Serializer = Serializer::new().serialize_missing_as_null(true); +// - `serialize_missing_as_null` is required to make sure that "empty" values (e.g., `None` and `()`) +// are serialized as `null` and not `undefined`. +// This is due to certain drivers (e.g., LibSQL) not supporting `undefined` values. +// - `serialize_large_number_types_as_bigints` is required to allow reading bigints from Prisma Client. +pub(crate) static SERIALIZER: Serializer = Serializer::new() + .serialize_large_number_types_as_bigints(true) + .serialize_missing_as_null(true); #[derive(Clone)] pub(crate) struct AdapterMethod From 8300a19a0da415d20f00815559dfcce08fb0be23 Mon Sep 17 00:00:00 2001 From: jkomyno Date: Tue, 16 Jan 2024 14:15:37 +0100 Subject: [PATCH 2/5] chore(driver-adapters): comment out native_other_types, like it was before --- .../tests/writes/data_types/native_types/postgres.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/native_types/postgres.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/native_types/postgres.rs index d1f17ad35863..e24245745991 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/native_types/postgres.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/native_types/postgres.rs @@ -191,7 +191,11 @@ mod postgres { } // "Other Postgres native types" should "work" - #[connector_test(schema(schema_other_types), only(Postgres), exclude(CockroachDb))] + #[connector_test( + schema(schema_other_types), + only(Postgres), + exclude(CockroachDb, Postgres("pg.js.wasm", "neon.js.wasm")) + )] async fn native_other_types(runner: Runner) -> TestResult<()> { insta::assert_snapshot!( run_query!(&runner, r#"mutation { From 94ce58a573bd688a1fa52351f70f3a1e83e10ed1 Mon Sep 17 00:00:00 2001 From: jkomyno Date: Wed, 17 Jan 2024 13:09:53 +0100 Subject: [PATCH 3/5] chore(driver-adapters): excluded PlanetScale from test --- .../query-engine-tests/tests/writes/data_types/bigint.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/bigint.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/bigint.rs index 469ebd227d49..61e3d482d778 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/bigint.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/bigint.rs @@ -17,7 +17,8 @@ mod bigint { } // "Using a BigInt field" should "work" - #[connector_test()] + // TODO: https://github.com/prisma/team-orm/issues/836 + #[connector_test(exclude(Vitess("planetscale.js.wasm")))] async fn using_bigint_field(runner: Runner) -> TestResult<()> { insta::assert_snapshot!( run_query!(&runner, r#"mutation { From 0676bd93737ee536bc803589ef7fbffd0f0b632f Mon Sep 17 00:00:00 2001 From: jkomyno Date: Thu, 18 Jan 2024 20:06:19 +0100 Subject: [PATCH 4/5] tmp/fix: avoid adding quotes to bigint numbers in PlanetScale, waiting for upstream PR to be merged --- .../executor/src/planetscale/sanitize.ts | 90 +++++++++++++++++++ .../driver-adapters/executor/src/testd.ts | 5 +- 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 query-engine/driver-adapters/executor/src/planetscale/sanitize.ts diff --git a/query-engine/driver-adapters/executor/src/planetscale/sanitize.ts b/query-engine/driver-adapters/executor/src/planetscale/sanitize.ts new file mode 100644 index 000000000000..a62d6000bd39 --- /dev/null +++ b/query-engine/driver-adapters/executor/src/planetscale/sanitize.ts @@ -0,0 +1,90 @@ +// This is a temporary workaround for `bigint` serialization issues in the Planetscale driver, +// which will be fixed upstream once https://github.com/planetscale/database-js/pull/159 is merged. +// This only impacts Rust tests concerning `driver-adapters`. + +type Stringable = { toString: () => string } +type Value = null | undefined | number | boolean | string | Array | Date | Stringable + +export function format(query: string, values: Value[] | Record): string { + return Array.isArray(values) ? replacePosition(query, values) : replaceNamed(query, values) +} + +function replacePosition(query: string, values: Value[]): string { + let index = 0 + return query.replace(/\?/g, (match) => { + return index < values.length ? sanitize(values[index++]) : match + }) +} + +function replaceNamed(query: string, values: Record): string { + return query.replace(/:(\w+)/g, (match, name) => { + return hasOwn(values, name) ? sanitize(values[name]) : match + }) +} + +function hasOwn(obj: unknown, name: string): boolean { + return Object.prototype.hasOwnProperty.call(obj, name) +} + +function sanitize(value: Value): string { + if (value == null) { + return 'null' + } + + if (['number', 'bigint'].includes(typeof value)) { + return String(value) + } + + if (typeof value === 'boolean') { + return value ? 'true' : 'false' + } + + if (typeof value === 'string') { + return quote(value) + } + + if (Array.isArray(value)) { + return value.map(sanitize).join(', ') + } + + if (value instanceof Date) { + return quote(value.toISOString().slice(0, -1)) + } + + return quote(value.toString()) +} + +function quote(text: string): string { + return `'${escape(text)}'` +} + +const re = /[\0\b\n\r\t\x1a\\"']/g + +function escape(text: string): string { + return text.replace(re, replacement) +} + +function replacement(text: string): string { + switch (text) { + case '"': + return '\\"' + case "'": + return "\\'" + case '\n': + return '\\n' + case '\r': + return '\\r' + case '\t': + return '\\t' + case '\\': + return '\\\\' + case '\0': + return '\\0' + case '\b': + return '\\b' + case '\x1a': + return '\\Z' + default: + return '' + } +} diff --git a/query-engine/driver-adapters/executor/src/testd.ts b/query-engine/driver-adapters/executor/src/testd.ts index 8ee0d8b74d92..b29889d0e664 100644 --- a/query-engine/driver-adapters/executor/src/testd.ts +++ b/query-engine/driver-adapters/executor/src/testd.ts @@ -19,6 +19,7 @@ import { PrismaLibSQL } from '@prisma/adapter-libsql' // planetscale dependencies import { Client as PlanetscaleClient } from '@planetscale/database' import { PrismaPlanetScale } from '@prisma/adapter-planetscale' +import { format as formatPlanetScaleQuery } from './planetscale/sanitize' @@ -292,11 +293,13 @@ async function planetscaleAdapter(url: string): Promise { throw new Error("DRIVER_ADAPTER_CONFIG is not defined or empty, but its required for planetscale adapter."); } - const client = new PlanetscaleClient({ // preserving path name so proxy url would look like real DB url url: copyPathName(url, proxyUrl), fetch, + + // TODO: remove once https://github.com/planetscale/database-js/pull/159 is merged. + format: formatPlanetScaleQuery, }) return new PrismaPlanetScale(client) From 57c5acbbebbf3763e9eb5aa31c4a6e08b4a9ecfe Mon Sep 17 00:00:00 2001 From: jkomyno Date: Thu, 18 Jan 2024 20:20:41 +0100 Subject: [PATCH 5/5] chore: update comments, remove PlanetScale exclusion for "using_bigint_field" test --- .../query-engine-tests/tests/writes/data_types/bigint.rs | 3 +-- .../driver-adapters/executor/src/planetscale/sanitize.ts | 2 +- query-engine/driver-adapters/executor/src/testd.ts | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/bigint.rs b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/bigint.rs index 61e3d482d778..469ebd227d49 100644 --- a/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/bigint.rs +++ b/query-engine/connector-test-kit-rs/query-engine-tests/tests/writes/data_types/bigint.rs @@ -17,8 +17,7 @@ mod bigint { } // "Using a BigInt field" should "work" - // TODO: https://github.com/prisma/team-orm/issues/836 - #[connector_test(exclude(Vitess("planetscale.js.wasm")))] + #[connector_test()] async fn using_bigint_field(runner: Runner) -> TestResult<()> { insta::assert_snapshot!( run_query!(&runner, r#"mutation { diff --git a/query-engine/driver-adapters/executor/src/planetscale/sanitize.ts b/query-engine/driver-adapters/executor/src/planetscale/sanitize.ts index a62d6000bd39..5c7d24fcde4c 100644 --- a/query-engine/driver-adapters/executor/src/planetscale/sanitize.ts +++ b/query-engine/driver-adapters/executor/src/planetscale/sanitize.ts @@ -1,5 +1,5 @@ // This is a temporary workaround for `bigint` serialization issues in the Planetscale driver, -// which will be fixed upstream once https://github.com/planetscale/database-js/pull/159 is merged. +// which will be fixed upstream once https://github.com/planetscale/database-js/pull/159 is published. // This only impacts Rust tests concerning `driver-adapters`. type Stringable = { toString: () => string } diff --git a/query-engine/driver-adapters/executor/src/testd.ts b/query-engine/driver-adapters/executor/src/testd.ts index b29889d0e664..2575e6ab404b 100644 --- a/query-engine/driver-adapters/executor/src/testd.ts +++ b/query-engine/driver-adapters/executor/src/testd.ts @@ -298,7 +298,7 @@ async function planetscaleAdapter(url: string): Promise { url: copyPathName(url, proxyUrl), fetch, - // TODO: remove once https://github.com/planetscale/database-js/pull/159 is merged. + // TODO: remove once https://github.com/planetscale/database-js/pull/159 is published upstream. format: formatPlanetScaleQuery, })