Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 127 additions & 1 deletion packages/adapter-neon/src/conversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,132 @@ const ArrayColumnType = {
XML_ARRAY: 143,
}

export class UnsupportedNativeDataType extends Error {
// map of type codes to type names
static typeNames: { [key: number]: string } = {
16: 'bool',
17: 'bytea',
18: 'char',
19: 'name',
20: 'int8',
21: 'int2',
22: 'int2vector',
23: 'int4',
24: 'regproc',
25: 'text',
26: 'oid',
27: 'tid',
28: 'xid',
29: 'cid',
30: 'oidvector',
32: 'pg_ddl_command',
71: 'pg_type',
75: 'pg_attribute',
81: 'pg_proc',
83: 'pg_class',
114: 'json',
142: 'xml',
194: 'pg_node_tree',
269: 'table_am_handler',
325: 'index_am_handler',
600: 'point',
601: 'lseg',
602: 'path',
603: 'box',
604: 'polygon',
628: 'line',
650: 'cidr',
700: 'float4',
701: 'float8',
705: 'unknown',
718: 'circle',
774: 'macaddr8',
790: 'money',
829: 'macaddr',
869: 'inet',
1033: 'aclitem',
1042: 'bpchar',
1043: 'varchar',
1082: 'date',
1083: 'time',
1114: 'timestamp',
1184: 'timestamptz',
1186: 'interval',
1266: 'timetz',
1560: 'bit',
1562: 'varbit',
1700: 'numeric',
1790: 'refcursor',
2202: 'regprocedure',
2203: 'regoper',
2204: 'regoperator',
2205: 'regclass',
2206: 'regtype',
2249: 'record',
2275: 'cstring',
2276: 'any',
2277: 'anyarray',
2278: 'void',
2279: 'trigger',
2280: 'language_handler',
2281: 'internal',
2283: 'anyelement',
2287: '_record',
2776: 'anynonarray',
2950: 'uuid',
2970: 'txid_snapshot',
3115: 'fdw_handler',
3220: 'pg_lsn',
3310: 'tsm_handler',
3361: 'pg_ndistinct',
3402: 'pg_dependencies',
3500: 'anyenum',
3614: 'tsvector',
3615: 'tsquery',
3642: 'gtsvector',
3734: 'regconfig',
3769: 'regdictionary',
3802: 'jsonb',
3831: 'anyrange',
3838: 'event_trigger',
3904: 'int4range',
3906: 'numrange',
3908: 'tsrange',
3910: 'tstzrange',
3912: 'daterange',
3926: 'int8range',
4072: 'jsonpath',
4089: 'regnamespace',
4096: 'regrole',
4191: 'regcollation',
4451: 'int4multirange',
4532: 'nummultirange',
4533: 'tsmultirange',
4534: 'tstzmultirange',
4535: 'datemultirange',
4536: 'int8multirange',
4537: 'anymultirange',
4538: 'anycompatiblemultirange',
4600: 'pg_brin_bloom_summary',
4601: 'pg_brin_minmax_multi_summary',
5017: 'pg_mcv_list',
5038: 'pg_snapshot',
5069: 'xid8',
5077: 'anycompatible',
5078: 'anycompatiblearray',
5079: 'anycompatiblenonarray',
5080: 'anycompatiblerange',
}

type: string

constructor(code: number) {
super()
this.type = UnsupportedNativeDataType.typeNames[code] || 'Unknown'
this.message = `Unsupported column type ${this.type}`
}
}

/**
* This is a simplification of quaint's value inference logic. Take a look at quaint's conversion.rs
* module to see how other attributes of the field packet such as the field length are used to infer
Expand Down Expand Up @@ -129,7 +255,7 @@ export function fieldToColumnType(fieldTypeId: number): ColumnType {
// Postgres Custom Types
return ColumnTypeEnum.Enum
}
throw new Error(`Unsupported column type: ${fieldTypeId}`)
throw new UnsupportedNativeDataType(fieldTypeId)
}
}

Expand Down
34 changes: 26 additions & 8 deletions packages/adapter-neon/src/neon.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/require-await */
import type neon from '@neondatabase/serverless'
import type {
ColumnType,
DriverAdapter,
Query,
Queryable,
Expand All @@ -11,7 +12,7 @@ import type {
} from '@prisma/driver-adapter-utils'
import { Debug, err, ok } from '@prisma/driver-adapter-utils'

import { fieldToColumnType } from './conversion'
import { fieldToColumnType, UnsupportedNativeDataType } from './conversion'

const debug = Debug('prisma:driver-adapter:neon')

Expand All @@ -29,15 +30,32 @@ abstract class NeonQueryable implements Queryable {
const tag = '[js::query_raw]'
debug(`${tag} %O`, query)

return (await this.performIO(query)).map(({ fields, rows }) => {
const columns = fields.map((field) => field.name)
const columnTypes = fields.map((field) => fieldToColumnType(field.dataTypeID))
const res = await this.performIO(query)

return {
columnNames: columns,
columnTypes,
rows,
if (!res.ok) {
return err(res.error)
}

const { fields, rows } = res.value
const columnNames = fields.map((field) => field.name)
let columnTypes: ColumnType[] = []

try {
columnTypes = fields.map((field) => fieldToColumnType(field.dataTypeID))
} catch (e) {
if (e instanceof UnsupportedNativeDataType) {
return err({
kind: 'UnsupportedNativeDataType',
type: e.type,
})
}
throw e
}

return ok({
columnNames,
columnTypes,
rows,
})
}

Expand Down
128 changes: 127 additions & 1 deletion packages/adapter-pg/src/conversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,132 @@ const ArrayColumnType = {
XML_ARRAY: 143,
}

export class UnsupportedNativeDataType extends Error {
// map of type codes to type names
static typeNames: { [key: number]: string } = {
16: 'bool',
17: 'bytea',
18: 'char',
19: 'name',
20: 'int8',
21: 'int2',
22: 'int2vector',
23: 'int4',
24: 'regproc',
25: 'text',
26: 'oid',
27: 'tid',
28: 'xid',
29: 'cid',
30: 'oidvector',
32: 'pg_ddl_command',
71: 'pg_type',
75: 'pg_attribute',
81: 'pg_proc',
83: 'pg_class',
114: 'json',
142: 'xml',
194: 'pg_node_tree',
269: 'table_am_handler',
325: 'index_am_handler',
600: 'point',
601: 'lseg',
602: 'path',
603: 'box',
604: 'polygon',
628: 'line',
650: 'cidr',
700: 'float4',
701: 'float8',
705: 'unknown',
718: 'circle',
774: 'macaddr8',
790: 'money',
829: 'macaddr',
869: 'inet',
1033: 'aclitem',
1042: 'bpchar',
1043: 'varchar',
1082: 'date',
1083: 'time',
1114: 'timestamp',
1184: 'timestamptz',
1186: 'interval',
1266: 'timetz',
1560: 'bit',
1562: 'varbit',
1700: 'numeric',
1790: 'refcursor',
2202: 'regprocedure',
2203: 'regoper',
2204: 'regoperator',
2205: 'regclass',
2206: 'regtype',
2249: 'record',
2275: 'cstring',
2276: 'any',
2277: 'anyarray',
2278: 'void',
2279: 'trigger',
2280: 'language_handler',
2281: 'internal',
2283: 'anyelement',
2287: '_record',
2776: 'anynonarray',
2950: 'uuid',
2970: 'txid_snapshot',
3115: 'fdw_handler',
3220: 'pg_lsn',
3310: 'tsm_handler',
3361: 'pg_ndistinct',
3402: 'pg_dependencies',
3500: 'anyenum',
3614: 'tsvector',
3615: 'tsquery',
3642: 'gtsvector',
3734: 'regconfig',
3769: 'regdictionary',
3802: 'jsonb',
3831: 'anyrange',
3838: 'event_trigger',
3904: 'int4range',
3906: 'numrange',
3908: 'tsrange',
3910: 'tstzrange',
3912: 'daterange',
3926: 'int8range',
4072: 'jsonpath',
4089: 'regnamespace',
4096: 'regrole',
4191: 'regcollation',
4451: 'int4multirange',
4532: 'nummultirange',
4533: 'tsmultirange',
4534: 'tstzmultirange',
4535: 'datemultirange',
4536: 'int8multirange',
4537: 'anymultirange',
4538: 'anycompatiblemultirange',
4600: 'pg_brin_bloom_summary',
4601: 'pg_brin_minmax_multi_summary',
5017: 'pg_mcv_list',
5038: 'pg_snapshot',
5069: 'xid8',
5077: 'anycompatible',
5078: 'anycompatiblearray',
5079: 'anycompatiblenonarray',
5080: 'anycompatiblerange',
}

type: string

constructor(code: number) {
super()
this.type = UnsupportedNativeDataType.typeNames[code] || 'Unknown'
this.message = `Unsupported column type ${this.type}`
}
}

/**
* This is a simplification of quaint's value inference logic. Take a look at quaint's conversion.rs
* module to see how other attributes of the field packet such as the field length are used to infer
Expand Down Expand Up @@ -129,7 +255,7 @@ export function fieldToColumnType(fieldTypeId: number): ColumnType {
// Postgres Custom Types
return ColumnTypeEnum.Enum
}
throw new Error(`Unsupported column type: ${fieldTypeId}`)
throw new UnsupportedNativeDataType(fieldTypeId)
}
}

Expand Down
35 changes: 26 additions & 9 deletions packages/adapter-pg/src/pg.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint-disable @typescript-eslint/require-await */
import type {
ColumnType,
DriverAdapter,
Query,
Queryable,
Expand All @@ -11,7 +12,7 @@ import type {
import { Debug, err, ok } from '@prisma/driver-adapter-utils'
import type pg from 'pg'

import { fieldToColumnType } from './conversion'
import { fieldToColumnType, UnsupportedNativeDataType } from './conversion'

const debug = Debug('prisma:driver-adapter:pg')

Expand All @@ -30,16 +31,32 @@ class PgQueryable<ClientT extends StdClient | TransactionClient> implements Quer
const tag = '[js::query_raw]'
debug(`${tag} %O`, query)

const ioResult = await this.performIO(query)
return ioResult.map(({ fields, rows }) => {
const columns = fields.map((field) => field.name)
const columnTypes = fields.map((field) => fieldToColumnType(field.dataTypeID))
const res = await this.performIO(query)

return {
columnNames: columns,
columnTypes,
rows,
if (!res.ok) {
return err(res.error)
}

const { fields, rows } = res.value
const columnNames = fields.map((field) => field.name)
let columnTypes: ColumnType[] = []

try {
columnTypes = fields.map((field) => fieldToColumnType(field.dataTypeID))
} catch (e) {
if (e instanceof UnsupportedNativeDataType) {
return err({
kind: 'UnsupportedNativeDataType',
type: e.type,
})
}
throw e
}

return ok({
columnNames,
columnTypes,
rows,
})
}

Expand Down
Loading