From a437f71ab038893c0001b09743862e841bedca01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Fern=C3=A1ndez?= Date: Fri, 29 Sep 2023 15:00:09 +0200 Subject: [PATCH] driver(adapters): More test fixes focused on neon/pg (#4301) * fix(driver-adapter): add support for UUID type * Add conversion of UUID to neon * Add conversion of OID to neon and pg Fixes writes::data_types::native_types::postgres::postgres::native_int_types * Prepare adapter-side transformations * Fix money * Isolate quaint conversion to their own set of modules * polymorphic, per flavor conversion. (prep refactoring) * Revert "polymorphic, per flavor conversion. (prep refactoring)" This reverts commit 07bddd35466f8c8a05419db386c9e9769c735b99. * Revert "Isolate quaint conversion to their own set of modules" This reverts commit 2f8439d7a57bf3c27eacce2f7abb8d323bde4113. * Update query-engine/driver-adapters/src/proxy.rs Co-authored-by: Alexey Orlenko * Update query-engine/driver-adapters/src/proxy.rs Co-authored-by: Alexey Orlenko * Remove unused conversions * Update query-engine/driver-adapters/src/proxy.rs Co-authored-by: Alexey Orlenko * fixup! Remove unused conversions * Update driver-adapter-utils version * Update drivers versions * Fix typos in proxy.rs * formatting --------- Co-authored-by: jkomyno Co-authored-by: Alexey Orlenko --- Cargo.lock | 1 + query-engine/driver-adapters/Cargo.toml | 1 + .../js/adapter-neon/package.json | 2 +- .../js/adapter-neon/src/conversion.ts | 18 +++++++++++++----- .../js/adapter-neon/src/neon.ts | 4 +++- .../driver-adapters/js/adapter-pg/package.json | 2 +- .../js/adapter-pg/src/conversion.ts | 18 +++++++++++++----- .../driver-adapters/js/adapter-pg/src/pg.ts | 1 + .../js/driver-adapter-utils/package.json | 2 +- .../js/driver-adapter-utils/src/const.ts | 4 ++-- query-engine/driver-adapters/src/proxy.rs | 18 ++++++++++++++++-- 11 files changed, 53 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 803c2ccda82c..5f4df8b9a2f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1068,6 +1068,7 @@ dependencies = [ "tokio", "tracing", "tracing-core", + "uuid", ] [[package]] diff --git a/query-engine/driver-adapters/Cargo.toml b/query-engine/driver-adapters/Cargo.toml index 39e6804eca28..4c0b55bb0a92 100644 --- a/query-engine/driver-adapters/Cargo.toml +++ b/query-engine/driver-adapters/Cargo.toml @@ -13,6 +13,7 @@ psl.workspace = true tracing = "0.1" tracing-core = "0.1" metrics = "0.18" +uuid = { version = "1", features = ["v4"] } # Note: these deps are temporarily specified here to avoid importing them from tiberius (the SQL server driver). # They will be imported from quaint-core instead in a future PR. diff --git a/query-engine/driver-adapters/js/adapter-neon/package.json b/query-engine/driver-adapters/js/adapter-neon/package.json index 3c0089a4757d..a891c0147969 100644 --- a/query-engine/driver-adapters/js/adapter-neon/package.json +++ b/query-engine/driver-adapters/js/adapter-neon/package.json @@ -1,6 +1,6 @@ { "name": "@prisma/adapter-neon", - "version": "0.4.2", + "version": "0.5.0", "description": "Prisma's driver adapter for \"@neondatabase/serverless\"", "main": "dist/index.js", "module": "dist/index.mjs", diff --git a/query-engine/driver-adapters/js/adapter-neon/src/conversion.ts b/query-engine/driver-adapters/js/adapter-neon/src/conversion.ts index 7b08ba5bd1f8..99db8870de98 100644 --- a/query-engine/driver-adapters/js/adapter-neon/src/conversion.ts +++ b/query-engine/driver-adapters/js/adapter-neon/src/conversion.ts @@ -28,14 +28,22 @@ export function fieldToColumnType(fieldTypeId: number): ColumnType { case NeonColumnType['TIMESTAMP']: return ColumnTypeEnum.DateTime case NeonColumnType['NUMERIC']: + case NeonColumnType['MONEY']: return ColumnTypeEnum.Numeric + case NeonColumnType['JSONB']: + return ColumnTypeEnum.Json + case NeonColumnType['UUID']: + return ColumnTypeEnum.Uuid + case NeonColumnType['OID']: + return ColumnTypeEnum.Int64 case NeonColumnType['BPCHAR']: - return ColumnTypeEnum.Char case NeonColumnType['TEXT']: case NeonColumnType['VARCHAR']: + case NeonColumnType['BIT']: + case NeonColumnType['VARBIT']: + case NeonColumnType['INET']: + case NeonColumnType['CIDR']: return ColumnTypeEnum.Text - case NeonColumnType['JSONB']: - return ColumnTypeEnum.Json default: if (fieldTypeId >= 10000) { // Postgres Custom Types @@ -60,9 +68,9 @@ function convertJson(json: string): unknown { } // return string instead of JavaScript Date object -types.setTypeParser(NeonColumnType.DATE, date => date) types.setTypeParser(NeonColumnType.TIME, date => date) +types.setTypeParser(NeonColumnType.DATE, date => date) types.setTypeParser(NeonColumnType.TIMESTAMP, date => date) - types.setTypeParser(NeonColumnType.JSONB, convertJson) types.setTypeParser(NeonColumnType.JSON, convertJson) +types.setTypeParser(NeonColumnType.MONEY, (money: string) => money.slice(1)) \ No newline at end of file diff --git a/query-engine/driver-adapters/js/adapter-neon/src/neon.ts b/query-engine/driver-adapters/js/adapter-neon/src/neon.ts index cd0731240488..c86b8d88bef0 100644 --- a/query-engine/driver-adapters/js/adapter-neon/src/neon.ts +++ b/query-engine/driver-adapters/js/adapter-neon/src/neon.ts @@ -29,9 +29,11 @@ abstract class NeonQueryable implements Queryable { return (await this.performIO(query)).map(({ fields, rows }) => { const columns = fields.map((field) => field.name) + const columnTypes = fields.map((field) => fieldToColumnType(field.dataTypeID)) + return { columnNames: columns, - columnTypes: fields.map((field) => fieldToColumnType(field.dataTypeID)), + columnTypes, rows, } }) diff --git a/query-engine/driver-adapters/js/adapter-pg/package.json b/query-engine/driver-adapters/js/adapter-pg/package.json index 68cdad5ea715..6e17419ae85f 100644 --- a/query-engine/driver-adapters/js/adapter-pg/package.json +++ b/query-engine/driver-adapters/js/adapter-pg/package.json @@ -1,6 +1,6 @@ { "name": "@prisma/adapter-pg", - "version": "0.4.2", + "version": "0.5.0", "description": "Prisma's driver adapter for \"pg\"", "main": "dist/index.js", "module": "dist/index.mjs", diff --git a/query-engine/driver-adapters/js/adapter-pg/src/conversion.ts b/query-engine/driver-adapters/js/adapter-pg/src/conversion.ts index da145a5eb663..a8102f95ad0b 100644 --- a/query-engine/driver-adapters/js/adapter-pg/src/conversion.ts +++ b/query-engine/driver-adapters/js/adapter-pg/src/conversion.ts @@ -28,14 +28,22 @@ export function fieldToColumnType(fieldTypeId: number): ColumnType { case PgColumnType['TIMESTAMP']: return ColumnTypeEnum.DateTime case PgColumnType['NUMERIC']: + case PgColumnType['MONEY']: return ColumnTypeEnum.Numeric + case PgColumnType['JSONB']: + return ColumnTypeEnum.Json + case PgColumnType['UUID']: + return ColumnTypeEnum.Uuid + case PgColumnType['OID']: + return ColumnTypeEnum.Int64 case PgColumnType['BPCHAR']: - return ColumnTypeEnum.Char case PgColumnType['TEXT']: case PgColumnType['VARCHAR']: + case PgColumnType['BIT']: + case PgColumnType['VARBIT']: + case PgColumnType['INET']: + case PgColumnType['CIDR']: return ColumnTypeEnum.Text - case PgColumnType['JSONB']: - return ColumnTypeEnum.Json default: if (fieldTypeId >= 10000) { // Postgres Custom Types @@ -60,9 +68,9 @@ function convertJson(json: string): unknown { } // return string instead of JavaScript Date object -types.setTypeParser(PgColumnType.DATE, date => date) types.setTypeParser(PgColumnType.TIME, date => date) +types.setTypeParser(PgColumnType.DATE, date => date) types.setTypeParser(PgColumnType.TIMESTAMP, date => date) - types.setTypeParser(PgColumnType.JSONB, convertJson) types.setTypeParser(PgColumnType.JSON, convertJson) +types.setTypeParser(PgColumnType.MONEY, (money: string) => money.slice(1)) \ No newline at end of file diff --git a/query-engine/driver-adapters/js/adapter-pg/src/pg.ts b/query-engine/driver-adapters/js/adapter-pg/src/pg.ts index ae2df4e7a6b6..a049b59a0740 100644 --- a/query-engine/driver-adapters/js/adapter-pg/src/pg.ts +++ b/query-engine/driver-adapters/js/adapter-pg/src/pg.ts @@ -32,6 +32,7 @@ class PgQueryable implements Quer const columns = fields.map((field) => field.name) const columnTypes = fields.map((field) => fieldToColumnType(field.dataTypeID)) + const resultSet: ResultSet = { columnNames: columns, columnTypes, diff --git a/query-engine/driver-adapters/js/driver-adapter-utils/package.json b/query-engine/driver-adapters/js/driver-adapter-utils/package.json index ee3487053d0e..ffa1d8209750 100644 --- a/query-engine/driver-adapters/js/driver-adapter-utils/package.json +++ b/query-engine/driver-adapters/js/driver-adapter-utils/package.json @@ -1,6 +1,6 @@ { "name": "@prisma/driver-adapter-utils", - "version": "0.7.0", + "version": "0.8.0", "description": "Internal set of utilities and types for Prisma's driver adapters.", "main": "dist/index.js", "module": "dist/index.mjs", diff --git a/query-engine/driver-adapters/js/driver-adapter-utils/src/const.ts b/query-engine/driver-adapters/js/driver-adapter-utils/src/const.ts index a313812eaf5b..09fa4b3ad6e1 100644 --- a/query-engine/driver-adapters/js/driver-adapter-utils/src/const.ts +++ b/query-engine/driver-adapters/js/driver-adapter-utils/src/const.ts @@ -17,8 +17,8 @@ export const ColumnTypeEnum = { 'Json': 11, 'Enum': 12, 'Bytes': 13, - // 'Set': 14, - // 'Array': 15, + 'Set': 14, + 'Uuid': 15, // ... 'UnknownNumber': 128 } as const diff --git a/query-engine/driver-adapters/src/proxy.rs b/query-engine/driver-adapters/src/proxy.rs index d1ab2b361d69..a71742d3f282 100644 --- a/query-engine/driver-adapters/src/proxy.rs +++ b/query-engine/driver-adapters/src/proxy.rs @@ -159,8 +159,13 @@ pub enum ColumnType { /// This is currently unhandled, and will panic if encountered. Set = 14, - // Below there are custom types that don't have a 1:1 translation with a quaint::Value. - // enum variant. + /// UUID from postgres-flavored driver adapters is mapped to this type. + Uuid = 15, + + /* + * Below there are custom types that don't have a 1:1 translation with a quaint::Value. + * enum variant. + */ /// UnknownNumber is used when the type of the column is a number but of unknown particular type /// and precision. /// @@ -363,6 +368,15 @@ fn js_value_to_quaint( "expected a string or an array in column {column_name}, found {mismatch}", )), }, + ColumnType::Uuid => match json_value { + serde_json::Value::String(s) => uuid::Uuid::parse_str(&s) + .map(QuaintValue::uuid) + .map_err(|_| conversion_error!("Expected a UUID string")), + serde_json::Value::Null => Ok(QuaintValue::Bytes(None)), + mismatch => Err(conversion_error!( + "Expected a UUID string in column {column_name}, found {mismatch}" + )), + }, ColumnType::UnknownNumber => match json_value { serde_json::Value::Number(n) => n .as_i64()