Skip to content

Commit

Permalink
driver-adapters: support bytes type in pg and neon (#4307)
Browse files Browse the repository at this point in the history
* driver-adapters: support bytes in neon and pg

* driver-adapters: pass bytes from Rust to JS as Node.js Buffer
  • Loading branch information
aqrln authored Oct 3, 2023
1 parent a39bb2d commit 944a9c2
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 6 deletions.
23 changes: 22 additions & 1 deletion query-engine/driver-adapters/js/adapter-neon/src/conversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export function fieldToColumnType(fieldTypeId: number): ColumnType {
case NeonColumnType['INET']:
case NeonColumnType['CIDR']:
return ColumnTypeEnum.Text
case NeonColumnType['BYTEA']:
return ColumnTypeEnum.Bytes
default:
if (fieldTypeId >= 10000) {
// Postgres Custom Types
Expand All @@ -67,10 +69,29 @@ function convertJson(json: string): unknown {
return (json === 'null') ? JsonNullMarker : JSON.parse(json)
}

// Original BYTEA parser
const parsePgBytes = types.getTypeParser(NeonColumnType.BYTEA) as (_: string) => Buffer

/**
* Convert bytes to a JSON-encodable representation since we can't
* currently send a parsed Buffer or ArrayBuffer across JS to Rust
* boundary.
* TODO:
* 1. Check if using base64 would be more efficient than this encoding.
* 2. Consider the possibility of eliminating re-encoding altogether
* and passing bytea hex format to the engine if that can be aligned
* with other adapter flavours.
*/
function convertBytes(serializedBytes: string): number[] {
const buffer = parsePgBytes(serializedBytes)
return Array.from(new Uint8Array(buffer))
}

// return string instead of JavaScript Date object
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))
types.setTypeParser(NeonColumnType.MONEY, money => money.slice(1))
types.setTypeParser(NeonColumnType.BYTEA, convertBytes)
23 changes: 22 additions & 1 deletion query-engine/driver-adapters/js/adapter-pg/src/conversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export function fieldToColumnType(fieldTypeId: number): ColumnType {
case PgColumnType['INET']:
case PgColumnType['CIDR']:
return ColumnTypeEnum.Text
case PgColumnType['BYTEA']:
return ColumnTypeEnum.Bytes
default:
if (fieldTypeId >= 10000) {
// Postgres Custom Types
Expand All @@ -67,10 +69,29 @@ function convertJson(json: string): unknown {
return (json === 'null') ? JsonNullMarker : JSON.parse(json)
}

// Original BYTEA parser
const parsePgBytes = types.getTypeParser(PgColumnType.BYTEA) as (_: string) => Buffer

/**
* Convert bytes to a JSON-encodable representation since we can't
* currently send a parsed Buffer or ArrayBuffer across JS to Rust
* boundary.
* TODO:
* 1. Check if using base64 would be more efficient than this encoding.
* 2. Consider the possibility of eliminating re-encoding altogether
* and passing bytea hex format to the engine if that can be aligned
* with other adapter flavours.
*/
function convertBytes(serializedBytes: string): number[] {
const buffer = parsePgBytes(serializedBytes)
return Array.from(new Uint8Array(buffer))
}

// return string instead of JavaScript Date object
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))
types.setTypeParser(PgColumnType.MONEY, money => money.slice(1))
types.setTypeParser(PgColumnType.BYTEA, convertBytes)
7 changes: 3 additions & 4 deletions query-engine/driver-adapters/src/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,9 @@ impl ToNapiValue for JSArg {
match value {
JSArg::RawString(s) => ToNapiValue::to_napi_value(env, s),
JSArg::Value(v) => ToNapiValue::to_napi_value(env, v),
JSArg::Buffer(bytes) => ToNapiValue::to_napi_value(
env,
napi::Env::from_raw(env).create_arraybuffer_with_data(bytes)?.into_raw(),
),
JSArg::Buffer(bytes) => {
ToNapiValue::to_napi_value(env, napi::Env::from_raw(env).create_buffer_with_data(bytes)?.into_raw())
}
}
}
}
Expand Down

0 comments on commit 944a9c2

Please sign in to comment.