postgrejs 3.12.0 → 3.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/connection/bind-param.d.ts +21 -0
- package/connection/bind-param.js +21 -0
- package/connection/connection.d.ts +136 -0
- package/connection/connection.js +132 -5
- package/connection/copy-stream.d.ts +2 -0
- package/connection/copy-stream.js +2 -0
- package/connection/cursor.d.ts +67 -5
- package/connection/cursor.js +88 -15
- package/connection/intl-connection.d.ts +14 -0
- package/connection/intl-connection.js +95 -15
- package/connection/large-object.d.ts +18 -0
- package/connection/large-object.js +17 -0
- package/connection/logical-replication.d.ts +15 -0
- package/connection/logical-replication.js +6 -0
- package/connection/pool.d.ts +80 -0
- package/connection/pool.js +82 -9
- package/connection/portal.d.ts +37 -0
- package/connection/portal.js +29 -0
- package/connection/prepared-statement.d.ts +68 -0
- package/connection/prepared-statement.js +71 -2
- package/constants.d.ts +18 -0
- package/constants.js +18 -0
- package/data-type-map.d.ts +38 -0
- package/data-type-map.js +38 -0
- package/data-types/bit-type.d.ts +4 -0
- package/data-types/bit-type.js +4 -0
- package/data-types/bool-type.d.ts +2 -0
- package/data-types/bool-type.js +2 -0
- package/data-types/box-type.d.ts +2 -0
- package/data-types/box-type.js +2 -0
- package/data-types/bytea-type.d.ts +2 -0
- package/data-types/bytea-type.js +2 -0
- package/data-types/char-type.d.ts +2 -0
- package/data-types/char-type.js +2 -0
- package/data-types/circle-type.d.ts +2 -0
- package/data-types/circle-type.js +2 -0
- package/data-types/date-type.d.ts +2 -0
- package/data-types/date-type.js +2 -0
- package/data-types/float4-type.d.ts +2 -0
- package/data-types/float4-type.js +2 -0
- package/data-types/float8-type.d.ts +2 -0
- package/data-types/float8-type.js +2 -0
- package/data-types/inet-type.d.ts +4 -0
- package/data-types/inet-type.js +4 -0
- package/data-types/int2-type.d.ts +2 -0
- package/data-types/int2-type.js +2 -0
- package/data-types/int2-vector-type.d.ts +2 -0
- package/data-types/int2-vector-type.js +2 -0
- package/data-types/int4-type.d.ts +2 -0
- package/data-types/int4-type.js +2 -0
- package/data-types/int8-type.d.ts +2 -0
- package/data-types/int8-type.js +2 -0
- package/data-types/interval-type.d.ts +9 -0
- package/data-types/interval-type.js +9 -0
- package/data-types/json-type.d.ts +2 -0
- package/data-types/json-type.js +2 -0
- package/data-types/jsonb-type.d.ts +2 -0
- package/data-types/jsonb-type.js +2 -0
- package/data-types/jsonpath-type.d.ts +2 -0
- package/data-types/jsonpath-type.js +2 -0
- package/data-types/line-type.d.ts +2 -0
- package/data-types/line-type.js +2 -0
- package/data-types/lseg-type.d.ts +2 -0
- package/data-types/lseg-type.js +2 -0
- package/data-types/macaddr-type.d.ts +4 -0
- package/data-types/macaddr-type.js +4 -0
- package/data-types/money-type.d.ts +1 -0
- package/data-types/money-type.js +17 -10
- package/data-types/numeric-type.d.ts +2 -0
- package/data-types/numeric-type.js +2 -0
- package/data-types/oid-type.d.ts +2 -0
- package/data-types/oid-type.js +2 -0
- package/data-types/oid-vector-type.d.ts +1 -0
- package/data-types/oid-vector-type.js +1 -0
- package/data-types/path-type.d.ts +4 -0
- package/data-types/path-type.js +4 -0
- package/data-types/pg-lsn-type.d.ts +2 -0
- package/data-types/pg-lsn-type.js +2 -0
- package/data-types/point-type.d.ts +2 -0
- package/data-types/point-type.js +2 -0
- package/data-types/range-type.d.ts +4 -0
- package/data-types/range-type.js +4 -0
- package/data-types/snapshot-type.d.ts +4 -0
- package/data-types/snapshot-type.js +4 -0
- package/data-types/tid-type.d.ts +2 -0
- package/data-types/tid-type.js +2 -0
- package/data-types/time-type.d.ts +2 -0
- package/data-types/time-type.js +2 -0
- package/data-types/timestamp-type.d.ts +2 -0
- package/data-types/timestamp-type.js +2 -0
- package/data-types/timestamptz-type.d.ts +2 -0
- package/data-types/timestamptz-type.js +2 -0
- package/data-types/timetz-type.d.ts +2 -0
- package/data-types/timetz-type.js +2 -0
- package/data-types/tsvector-type.d.ts +4 -0
- package/data-types/tsvector-type.js +4 -0
- package/data-types/uuid-type.d.ts +2 -0
- package/data-types/uuid-type.js +2 -0
- package/data-types/varchar-type.d.ts +2 -0
- package/data-types/varchar-type.js +2 -0
- package/data-types/xid-type.d.ts +6 -0
- package/data-types/xid-type.js +6 -0
- package/interfaces/command-result.d.ts +7 -0
- package/interfaces/copy-from-rows-options.d.ts +4 -0
- package/interfaces/data-mapping-options.d.ts +6 -0
- package/interfaces/data-type.d.ts +37 -0
- package/interfaces/database-connection-params.d.ts +31 -0
- package/interfaces/field-info.d.ts +8 -0
- package/interfaces/function-call-options.d.ts +1 -0
- package/interfaces/function-call-result.d.ts +6 -0
- package/interfaces/pipeline-request.d.ts +2 -0
- package/interfaces/query-options.d.ts +7 -0
- package/interfaces/query-result.d.ts +7 -0
- package/interfaces/script-execute-options.d.ts +4 -0
- package/interfaces/script-result.d.ts +1 -0
- package/interfaces/statement-prepare-options.d.ts +1 -0
- package/package.json +5 -5
- package/protocol/backend.d.ts +6 -0
- package/protocol/backend.js +35 -5
- package/protocol/cert-signature.d.ts +8 -0
- package/protocol/cert-signature.js +8 -0
- package/protocol/database-error.d.ts +8 -0
- package/protocol/database-error.js +8 -0
- package/protocol/frontend.d.ts +16 -0
- package/protocol/frontend.js +13 -6
- package/protocol/pg-socket.d.ts +10 -0
- package/protocol/pg-socket.js +14 -7
- package/protocol/pgoutput.d.ts +15 -0
- package/protocol/pgoutput.js +7 -0
- package/protocol/protocol.d.ts +50 -2
- package/protocol/protocol.js +17 -1
- package/protocol/sasl.d.ts +22 -0
- package/protocol/sasl.js +21 -0
- package/protocol/smart-buffer.d.ts +4 -0
- package/safe-event-emitter.d.ts +7 -0
- package/safe-event-emitter.js +7 -0
- package/types.d.ts +21 -0
- package/util/array-calculatedim.d.ts +10 -0
- package/util/array-calculatedim.js +10 -0
- package/util/bigint-methods.d.ts +7 -0
- package/util/bigint-methods.js +9 -0
- package/util/config-from-env.d.ts +10 -0
- package/util/config-from-env.js +10 -0
- package/util/connection-config.d.ts +17 -0
- package/util/connection-config.js +17 -0
- package/util/copy-from-rows.d.ts +12 -0
- package/util/copy-from-rows.js +9 -0
- package/util/decimal-as-string.d.ts +6 -0
- package/util/decimal-as-string.js +6 -0
- package/util/decode-binaryarray.d.ts +9 -0
- package/util/decode-binaryarray.js +9 -0
- package/util/escape-literal.d.ts +11 -0
- package/util/escape-literal.js +13 -0
- package/util/fast-parseint.d.ts +14 -0
- package/util/fast-parseint.js +14 -0
- package/util/format-datetime.d.ts +26 -0
- package/util/format-datetime.js +26 -0
- package/util/get-parsers.d.ts +9 -0
- package/util/get-parsers.js +9 -0
- package/util/hex-text.d.ts +13 -21
- package/util/hex-text.js +24 -21
- package/util/local-date.d.ts +2 -41
- package/util/local-date.js +39 -41
- package/util/parse-array.d.ts +8 -0
- package/util/parse-array.js +8 -0
- package/util/parse-bytea.d.ts +15 -0
- package/util/parse-bytea.js +15 -0
- package/util/parse-datetime.d.ts +26 -0
- package/util/parse-datetime.js +26 -0
- package/util/parse-row.d.ts +23 -2
- package/util/parse-row.js +56 -36
- package/util/parse-time.d.ts +10 -0
- package/util/parse-time.js +10 -0
- package/util/resolve-column-formats.d.ts +1 -0
- package/util/row-decoder.d.ts +32 -0
- package/util/row-decoder.js +22 -0
- package/util/stringify-arrayliteral.d.ts +33 -0
- package/util/stringify-arrayliteral.js +220 -20
- package/util/stringify-for-sql.d.ts +17 -0
- package/util/stringify-for-sql.js +17 -0
- package/util/wrap-row-description.d.ts +10 -0
- package/util/wrap-row-description.js +10 -0
- package/CHANGELOG.md +0 -1453
package/util/parse-row.js
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Reads one row into an array of values.
|
|
3
|
+
*
|
|
4
|
+
* @param parsers One per column, already chosen for its format.
|
|
5
|
+
* @param data The row's own bytes, from the DataRow message.
|
|
6
|
+
* @param columnCount How many values it holds.
|
|
7
|
+
* @param options Passed to each parser.
|
|
8
|
+
* @param start Where the row's values begin in `data`.
|
|
9
|
+
* @returns The values, in column order.
|
|
10
|
+
*/
|
|
11
|
+
export function parseRow(parsers, data, columnCount, options, start = 0) {
|
|
2
12
|
const row = new Array(columnCount);
|
|
3
|
-
let offset =
|
|
13
|
+
let offset = start;
|
|
4
14
|
let len;
|
|
5
15
|
let i;
|
|
6
16
|
for (i = 0; i < columnCount; i++) {
|
|
@@ -21,28 +31,26 @@ export function parseRow(parsers, data, columnCount, options) {
|
|
|
21
31
|
}
|
|
22
32
|
return row;
|
|
23
33
|
}
|
|
24
|
-
/**
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
* giving up well under 1% of the win on a result worth compiling for.
|
|
34
|
-
*/
|
|
34
|
+
/** Rows decoded against one `FieldInfo[]` before compiling a factory for it. */
|
|
35
|
+
/* Compiling costs ~0.8µs when the engine can reuse its own compilation
|
|
36
|
+
cache for identical source and several µs when it cannot, against
|
|
37
|
+
~0.1µs saved per row - so a query returning a handful of rows would
|
|
38
|
+
pay more than it ever got back. Since wrapRowDescription() builds a
|
|
39
|
+
fresh fields array per query, a single-row query executed in a loop
|
|
40
|
+
would otherwise recompile on every call. Waiting a few rows keeps that
|
|
41
|
+
case free while giving up well under 1% of the win on a result worth
|
|
42
|
+
compiling for. */
|
|
35
43
|
const OBJECT_ROW_FACTORY_THRESHOLD = 8;
|
|
36
44
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* it leaves behind, which a single-row query (a new fields array every
|
|
40
|
-
* time, never looked up again) would pay on every call for nothing.
|
|
41
|
-
*
|
|
42
|
-
* Keyed weakly, so a finished query's factory goes away with its fields;
|
|
43
|
-
* an entry earns its keep only when the same fields array is decoded
|
|
44
|
-
* against again after something else interrupted it.
|
|
45
|
+
* The compiled factories, keyed weakly by the fields they were built
|
|
46
|
+
* for, so a finished query's factory goes away with them.
|
|
45
47
|
*/
|
|
48
|
+
/* Only factories that were actually compiled go in here, never the row
|
|
49
|
+
counts leading up to one: writing a fresh key costs ~67ns plus the
|
|
50
|
+
garbage it leaves behind, which a single-row query - a new fields
|
|
51
|
+
array every time, never looked up again - would pay on every call for
|
|
52
|
+
nothing. An entry earns its keep only when the same fields array is
|
|
53
|
+
decoded against again after something else interrupted it. */
|
|
46
54
|
const objectRowFactories = new WeakMap();
|
|
47
55
|
// Rows of one result arrive in a run, so a single entry in front of the
|
|
48
56
|
// WeakMap answers nearly every lookup with one identity check - and is
|
|
@@ -58,17 +66,18 @@ let memoDeclined = false;
|
|
|
58
66
|
* Compiles a function that builds this query's row object in one shot,
|
|
59
67
|
* from a single object literal with every column name in it.
|
|
60
68
|
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* Returns null when that isn't possible, leaving the caller on the
|
|
67
|
-
* assignment path: a column named `__proto__` would set the prototype
|
|
68
|
-
* rather than become an own property if it appeared as a literal key, and
|
|
69
|
-
* Function construction itself can be unavailable (a Content-Security-
|
|
70
|
-
* Policy without 'unsafe-eval').
|
|
69
|
+
* @param fields The columns to build the literal from.
|
|
70
|
+
* @param columnCount How many of them the rows carry.
|
|
71
|
+
* @returns The factory, or `null` when this shape cannot be compiled -
|
|
72
|
+
* a column named `__proto__`, or a runtime with Function construction
|
|
73
|
+
* disabled - which leaves the caller on the assignment path.
|
|
71
74
|
*/
|
|
75
|
+
/* Assigning the columns one at a time instead (row[name] = value) walks
|
|
76
|
+
the object through one hidden-class transition per column, per row -
|
|
77
|
+
~6.8x the cost of handing the engine a literal whose shape it can lay
|
|
78
|
+
out once and reuse for every row of the result. A `__proto__` key in a
|
|
79
|
+
literal sets the prototype rather than becoming an own property, which
|
|
80
|
+
is why that one is refused rather than escaped. */
|
|
72
81
|
function buildObjectRowFactory(fields, columnCount) {
|
|
73
82
|
let src = 'return{';
|
|
74
83
|
let name;
|
|
@@ -115,7 +124,18 @@ function getObjectRowFactory(fields, columnCount) {
|
|
|
115
124
|
objectRowFactories.set(fields, factory);
|
|
116
125
|
return factory;
|
|
117
126
|
}
|
|
118
|
-
|
|
127
|
+
/**
|
|
128
|
+
* Reads one row into an object keyed by column name.
|
|
129
|
+
*
|
|
130
|
+
* @param parsers One per column, already chosen for its format.
|
|
131
|
+
* @param data The row's own bytes, from the DataRow message.
|
|
132
|
+
* @param columnCount How many values it holds.
|
|
133
|
+
* @param options Passed to each parser.
|
|
134
|
+
* @param fields The columns, whose names become the keys.
|
|
135
|
+
* @param start Where the row's values begin in `data`.
|
|
136
|
+
* @returns The row as an object.
|
|
137
|
+
*/
|
|
138
|
+
export function parseObjectRow(parsers, data, columnCount, options, fields, start = 0) {
|
|
119
139
|
// A compiled factory is built against `fields`, so it can only be used
|
|
120
140
|
// when the row really does have one value per field.
|
|
121
141
|
const factory = fields.length === columnCount
|
|
@@ -123,7 +143,7 @@ export function parseObjectRow(parsers, data, columnCount, options, fields) {
|
|
|
123
143
|
: null;
|
|
124
144
|
if (factory) {
|
|
125
145
|
const values = new Array(columnCount);
|
|
126
|
-
let offset =
|
|
146
|
+
let offset = start;
|
|
127
147
|
let len;
|
|
128
148
|
let i;
|
|
129
149
|
for (i = 0; i < columnCount; i++) {
|
|
@@ -139,11 +159,11 @@ export function parseObjectRow(parsers, data, columnCount, options, fields) {
|
|
|
139
159
|
}
|
|
140
160
|
return factory(values);
|
|
141
161
|
}
|
|
142
|
-
return parseObjectRowByAssignment(parsers, data, columnCount, options, fields);
|
|
162
|
+
return parseObjectRowByAssignment(parsers, data, columnCount, options, fields, start);
|
|
143
163
|
}
|
|
144
|
-
function parseObjectRowByAssignment(parsers, data, columnCount, options, fields) {
|
|
164
|
+
function parseObjectRowByAssignment(parsers, data, columnCount, options, fields, start = 0) {
|
|
145
165
|
const row = {};
|
|
146
|
-
let offset =
|
|
166
|
+
let offset = start;
|
|
147
167
|
let len;
|
|
148
168
|
let i;
|
|
149
169
|
let value;
|
package/util/parse-time.d.ts
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/** A time as the server writes one: two digits a part, colons in place. */
|
|
1
2
|
export declare const STRICT_TIME_PATTERN: RegExp;
|
|
3
|
+
/** The same, loosened for what a caller might pass as a parameter - the colons and the seconds may be left out. */
|
|
2
4
|
export declare const TIME_PATTERN: RegExp;
|
|
5
|
+
/**
|
|
6
|
+
* Reads a time of day into a Date on the epoch day.
|
|
7
|
+
*
|
|
8
|
+
* @param str The value's text.
|
|
9
|
+
* @param parseTimeZone Whether an offset in the text should be applied.
|
|
10
|
+
* @param utc Whether to build the Date in UTC rather than locally.
|
|
11
|
+
* @returns A Date carrying that clock time.
|
|
12
|
+
*/
|
|
3
13
|
export declare function parseTime(str: string, parseTimeZone?: boolean, utc?: boolean): Date;
|
package/util/parse-time.js
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import { fastParseInt } from './fast-parseint.js';
|
|
2
2
|
// noinspection RegExpUnnecessaryNonCapturingGroup
|
|
3
|
+
/** A time as the server writes one: two digits a part, colons in place. */
|
|
3
4
|
export const STRICT_TIME_PATTERN = /^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])(?:\.(\d+))?(?:(Z)|(?:([+-])([01]?[0-9]|2[0-3]):?([0-5][0-9])?))?$/;
|
|
4
5
|
// noinspection RegExpUnnecessaryNonCapturingGroup
|
|
6
|
+
/** The same, loosened for what a caller might pass as a parameter - the colons and the seconds may be left out. */
|
|
5
7
|
export const TIME_PATTERN = /^([01][0-9]|2[0-3]):?([0-5][0-9]):?([0-5][0-9])?(?:\.(\d+))?(?:(Z)|(?:([+-])([01]?[0-9]|2[0-3]):?([0-5][0-9])?))?$/;
|
|
8
|
+
/**
|
|
9
|
+
* Reads a time of day into a Date on the epoch day.
|
|
10
|
+
*
|
|
11
|
+
* @param str The value's text.
|
|
12
|
+
* @param parseTimeZone Whether an offset in the text should be applied.
|
|
13
|
+
* @param utc Whether to build the Date in UTC rather than locally.
|
|
14
|
+
* @returns A Date carrying that clock time.
|
|
15
|
+
*/
|
|
6
16
|
export function parseTime(str, parseTimeZone, utc) {
|
|
7
17
|
const m = str.match(TIME_PATTERN);
|
|
8
18
|
if (!m)
|
|
@@ -2,6 +2,7 @@ import type { DataTypeMap } from '../data-type-map.js';
|
|
|
2
2
|
import type { DataMappingOptions } from '../interfaces/data-mapping-options.js';
|
|
3
3
|
import { Protocol } from '../protocol/protocol.js';
|
|
4
4
|
import type { Maybe } from '../types.js';
|
|
5
|
+
/** What decides the per-column format codes a Bind asks for. */
|
|
5
6
|
export interface ColumnFormatOptions extends DataMappingOptions {
|
|
6
7
|
columnFormat?: Protocol.DataFormat | Protocol.DataFormat[];
|
|
7
8
|
}
|
package/util/row-decoder.d.ts
CHANGED
|
@@ -32,16 +32,48 @@ export declare abstract class RowDecoder {
|
|
|
32
32
|
*/
|
|
33
33
|
readonly rowType: 'array' | 'object' | 'custom';
|
|
34
34
|
abstract decode(parsers: AnyParseFunction[], data: Buffer, columnCount: number, options: DataMappingOptions, fields: FieldInfo[]): any;
|
|
35
|
+
/**
|
|
36
|
+
* The same, reading the row where it already is: `buffer` is the
|
|
37
|
+
* socket's own read buffer and the row's values run for `len` bytes
|
|
38
|
+
* from `offset`.
|
|
39
|
+
*
|
|
40
|
+
* Optional, and what a decoder implements when it has no use for a
|
|
41
|
+
* `Buffer` of its own - which is every decoder that reads its values
|
|
42
|
+
* and does not keep them. Implementing it means no view is built for
|
|
43
|
+
* the row at all; a decoder that only implements `decode()` still gets
|
|
44
|
+
* one, exactly as before.
|
|
45
|
+
*/
|
|
46
|
+
decodeAt?(parsers: AnyParseFunction[], buffer: Buffer, offset: number, len: number, columnCount: number, options: DataMappingOptions, fields: FieldInfo[]): any;
|
|
35
47
|
}
|
|
48
|
+
/** Reads each row into an array of values, in column order. */
|
|
49
|
+
/**
|
|
50
|
+
* A row's bytes as a `Buffer` of their own.
|
|
51
|
+
*
|
|
52
|
+
* For the paths that set a row aside and read it later, and for a
|
|
53
|
+
* caller's decoder that only implements `decode()`.
|
|
54
|
+
*
|
|
55
|
+
* @param msg The row as it arrived.
|
|
56
|
+
* @returns A view of just its values.
|
|
57
|
+
*/
|
|
58
|
+
export declare function dataRowBytes(msg: {
|
|
59
|
+
buffer: Buffer;
|
|
60
|
+
offset: number;
|
|
61
|
+
len: number;
|
|
62
|
+
}): Buffer;
|
|
36
63
|
export declare class ArrayRowDecoder extends RowDecoder {
|
|
37
64
|
readonly rowType: "array";
|
|
38
65
|
decode(parsers: AnyParseFunction[], data: Buffer, columnCount: number, options: DataMappingOptions): any[];
|
|
66
|
+
decodeAt(parsers: AnyParseFunction[], buffer: Buffer, offset: number, _len: number, columnCount: number, options: DataMappingOptions): any[];
|
|
39
67
|
}
|
|
68
|
+
/** Reads each row into an object keyed by column name. */
|
|
40
69
|
export declare class ObjectRowDecoder extends RowDecoder {
|
|
41
70
|
readonly rowType: "object";
|
|
42
71
|
decode(parsers: AnyParseFunction[], data: Buffer, columnCount: number, options: DataMappingOptions, fields: FieldInfo[]): object;
|
|
72
|
+
decodeAt(parsers: AnyParseFunction[], buffer: Buffer, offset: number, _len: number, columnCount: number, options: DataMappingOptions, fields: FieldInfo[]): object;
|
|
43
73
|
}
|
|
74
|
+
/** The array decoder every query shares - it holds no state. */
|
|
44
75
|
export declare const DEFAULT_ARRAY_ROW_DECODER: ArrayRowDecoder;
|
|
76
|
+
/** The object decoder every query shares - it holds no state. */
|
|
45
77
|
export declare const DEFAULT_OBJECT_ROW_DECODER: ObjectRowDecoder;
|
|
46
78
|
interface RowDecoderOptions {
|
|
47
79
|
rowDecoder?: 'array' | 'object' | RowDecoder;
|
package/util/row-decoder.js
CHANGED
|
@@ -30,19 +30,41 @@ export class RowDecoder {
|
|
|
30
30
|
*/
|
|
31
31
|
rowType = 'custom';
|
|
32
32
|
}
|
|
33
|
+
/** Reads each row into an array of values, in column order. */
|
|
34
|
+
/**
|
|
35
|
+
* A row's bytes as a `Buffer` of their own.
|
|
36
|
+
*
|
|
37
|
+
* For the paths that set a row aside and read it later, and for a
|
|
38
|
+
* caller's decoder that only implements `decode()`.
|
|
39
|
+
*
|
|
40
|
+
* @param msg The row as it arrived.
|
|
41
|
+
* @returns A view of just its values.
|
|
42
|
+
*/
|
|
43
|
+
export function dataRowBytes(msg) {
|
|
44
|
+
return msg.buffer.subarray(msg.offset, msg.offset + msg.len);
|
|
45
|
+
}
|
|
33
46
|
export class ArrayRowDecoder extends RowDecoder {
|
|
34
47
|
rowType = 'array';
|
|
35
48
|
decode(parsers, data, columnCount, options) {
|
|
36
49
|
return parseRow(parsers, data, columnCount, options);
|
|
37
50
|
}
|
|
51
|
+
decodeAt(parsers, buffer, offset, _len, columnCount, options) {
|
|
52
|
+
return parseRow(parsers, buffer, columnCount, options, offset);
|
|
53
|
+
}
|
|
38
54
|
}
|
|
55
|
+
/** Reads each row into an object keyed by column name. */
|
|
39
56
|
export class ObjectRowDecoder extends RowDecoder {
|
|
40
57
|
rowType = 'object';
|
|
41
58
|
decode(parsers, data, columnCount, options, fields) {
|
|
42
59
|
return parseObjectRow(parsers, data, columnCount, options, fields);
|
|
43
60
|
}
|
|
61
|
+
decodeAt(parsers, buffer, offset, _len, columnCount, options, fields) {
|
|
62
|
+
return parseObjectRow(parsers, buffer, columnCount, options, fields, offset);
|
|
63
|
+
}
|
|
44
64
|
}
|
|
65
|
+
/** The array decoder every query shares - it holds no state. */
|
|
45
66
|
export const DEFAULT_ARRAY_ROW_DECODER = new ArrayRowDecoder();
|
|
67
|
+
/** The object decoder every query shares - it holds no state. */
|
|
46
68
|
export const DEFAULT_OBJECT_ROW_DECODER = new ObjectRowDecoder();
|
|
47
69
|
/**
|
|
48
70
|
* Collapses the `rowDecoder`/`objectRows` query options into one RowDecoder
|
|
@@ -1,3 +1,36 @@
|
|
|
1
1
|
import type { DataMappingOptions } from '../interfaces/data-mapping-options.js';
|
|
2
2
|
import type { EncodeTextFunction } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Renders an array as the literal the server parses - `{1,2,{3,4}}`.
|
|
5
|
+
*
|
|
6
|
+
* @param value The array, nested to any depth.
|
|
7
|
+
* @param options Passed to the element encoder.
|
|
8
|
+
* @param encode The element type's own text encoder, when the type is
|
|
9
|
+
* known; without one each element is taken as it stringifies.
|
|
10
|
+
* @returns The literal.
|
|
11
|
+
*/
|
|
3
12
|
export declare function stringifyArrayLiteral(value: any[], options?: DataMappingOptions, encode?: EncodeTextFunction): string;
|
|
13
|
+
/**
|
|
14
|
+
* Writes an array as a length-prefixed literal, straight into `io`,
|
|
15
|
+
* without building the literal as a string first.
|
|
16
|
+
*
|
|
17
|
+
* The text is the one `stringifyArrayLiteral()` returns, so what reaches
|
|
18
|
+
* the server is the same either way. Only an array of numbers with no
|
|
19
|
+
* element encoder takes this path - the untyped-parameter case, and the
|
|
20
|
+
* only one where a numeric array becomes a literal at all, since a
|
|
21
|
+
* declared one keeps the binary encoding. Anything else, and anything
|
|
22
|
+
* under `WRITE_BYTES_FROM` elements, is handed to the string path.
|
|
23
|
+
*
|
|
24
|
+
* @param io The buffer to write into - the connection's own.
|
|
25
|
+
* @param value The array to write.
|
|
26
|
+
* @param options Passed to the element encoder, when there is one.
|
|
27
|
+
* @param encode The element type's own text encoder, if the type was
|
|
28
|
+
* declared.
|
|
29
|
+
*/
|
|
30
|
+
export declare function writeArrayLiteral(io: {
|
|
31
|
+
buffer: Buffer;
|
|
32
|
+
size: number;
|
|
33
|
+
writeInt32BE(v: number): number;
|
|
34
|
+
writeBytes(b: Buffer): number;
|
|
35
|
+
writeLString(s?: string, encoding?: BufferEncoding): number;
|
|
36
|
+
}, value: any[], options?: DataMappingOptions, encode?: EncodeTextFunction): void;
|
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
import { arrayCalculateDim } from './array-calculatedim.js';
|
|
2
|
+
import { arrayLeaf } from './array-leaf.js';
|
|
2
3
|
/**
|
|
3
4
|
* What a number's own text looks like: digits, one optional dot, an
|
|
4
|
-
* optional exponent, an optional leading minus.
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* which is what the server itself prints and what every other client
|
|
8
|
-
* writes.
|
|
9
|
-
*
|
|
10
|
-
* Deliberately narrower than "has no special characters": it is applied
|
|
11
|
-
* only to what a JS number or bigint encoded to, and matching it is the
|
|
12
|
-
* evidence that the encoder really did produce a number's text. `NaN`
|
|
13
|
-
* and `Infinity` fail it and stay quoted (both forms parse the same, so
|
|
14
|
-
* this costs nothing), and so does anything an unexpected encoder made
|
|
15
|
-
* of a number - a date type handed a timestamp, say.
|
|
5
|
+
* optional exponent, an optional leading minus. An element that matches
|
|
6
|
+
* goes out bare - `{1,2}` rather than `{"1","2"}`, which is what the
|
|
7
|
+
* server itself prints and what every other client writes.
|
|
16
8
|
*/
|
|
9
|
+
/* Deliberately narrower than "has no special characters": it is applied
|
|
10
|
+
only to what a JS number or bigint encoded to, and matching it is the
|
|
11
|
+
evidence that the encoder really did produce a number's text. NaN and
|
|
12
|
+
Infinity fail it and stay quoted - both forms parse the same, so that
|
|
13
|
+
costs nothing - and so does anything an unexpected encoder made of a
|
|
14
|
+
number, a date type handed a timestamp say. */
|
|
17
15
|
const BARE_NUMBER = /^-?\d+(\.\d+)?([eE][-+]?\d+)?$/;
|
|
16
|
+
/**
|
|
17
|
+
* Renders an array as the literal the server parses - `{1,2,{3,4}}`.
|
|
18
|
+
*
|
|
19
|
+
* @param value The array, nested to any depth.
|
|
20
|
+
* @param options Passed to the element encoder.
|
|
21
|
+
* @param encode The element type's own text encoder, when the type is
|
|
22
|
+
* known; without one each element is taken as it stringifies.
|
|
23
|
+
* @returns The literal.
|
|
24
|
+
*/
|
|
18
25
|
export function stringifyArrayLiteral(value, options, encode) {
|
|
19
26
|
const dim = arrayCalculateDim(value);
|
|
20
27
|
// `dim` is built once above and never mutated, so its last index is
|
|
@@ -66,16 +73,209 @@ export function stringifyArrayLiteral(value, options, encode) {
|
|
|
66
73
|
};
|
|
67
74
|
return writeDim(value, 0);
|
|
68
75
|
}
|
|
69
|
-
/**
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
*/
|
|
76
|
+
/** Quotes one element, escaping the two characters that need it. */
|
|
77
|
+
/* Backslash and double quote are the only two the literal grammar gives
|
|
78
|
+
meaning to inside a quoted element, and neither is in most values - so
|
|
79
|
+
they are looked for before anything is rewritten. The two replace()
|
|
80
|
+
calls each walk the string and build another one even when they change
|
|
81
|
+
nothing, which for a column of ordinary text was half the cost of
|
|
82
|
+
writing the literal. */
|
|
77
83
|
function escapeArrayItem(str) {
|
|
78
84
|
return str.indexOf('\\') < 0 && str.indexOf('"') < 0
|
|
79
85
|
? '"' + str + '"'
|
|
80
86
|
: '"' + str.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
|
|
81
87
|
}
|
|
88
|
+
/** How many bytes writeArrayLiteral() writes into `io` at a time. */
|
|
89
|
+
/* Bounded rather than grown to fit: a 100 000-element array is 1.1MB of
|
|
90
|
+
literal, and a scratch sized to the largest one ever written would
|
|
91
|
+
hold that for the life of the process. Flushing every 64KB keeps this
|
|
92
|
+
constant, and what it flushes into is the connection's own buffer,
|
|
93
|
+
which already knows how to grow and to hand its pages back when
|
|
94
|
+
idle. */
|
|
95
|
+
const CHUNK = 64 * 1024;
|
|
96
|
+
/** The scratch itself, reused by every call. */
|
|
97
|
+
const chunk = Buffer.allocUnsafe(CHUNK);
|
|
98
|
+
/**
|
|
99
|
+
* Whether the digit lane applies to this value - see writeArrayLiteral().
|
|
100
|
+
* Asked of the array's first leaf to choose a path, and of every element
|
|
101
|
+
* on the way past.
|
|
102
|
+
*/
|
|
103
|
+
function isInt32(v) {
|
|
104
|
+
return (typeof v === 'number' &&
|
|
105
|
+
v >= -2147483648 &&
|
|
106
|
+
v <= 2147483647 &&
|
|
107
|
+
Number.isInteger(v));
|
|
108
|
+
}
|
|
109
|
+
/** Digits, written backwards, before they are copied out forwards. */
|
|
110
|
+
const DIGITS = new Uint8Array(24);
|
|
111
|
+
/** Below this many elements the literal is built as a string instead. */
|
|
112
|
+
/* Writing bytes wins from about a hundred elements up and loses below
|
|
113
|
+
it: Buffer.write() has a per-call cost that `+=` does not, and for a
|
|
114
|
+
handful of short elements that cost is the whole of the work. The
|
|
115
|
+
number is where the two met when measured, so it is a floor against a
|
|
116
|
+
small regression rather than a tuned parameter. */
|
|
117
|
+
const WRITE_BYTES_FROM = 16;
|
|
118
|
+
/**
|
|
119
|
+
* Writes an array as a length-prefixed literal, straight into `io`,
|
|
120
|
+
* without building the literal as a string first.
|
|
121
|
+
*
|
|
122
|
+
* The text is the one `stringifyArrayLiteral()` returns, so what reaches
|
|
123
|
+
* the server is the same either way. Only an array of numbers with no
|
|
124
|
+
* element encoder takes this path - the untyped-parameter case, and the
|
|
125
|
+
* only one where a numeric array becomes a literal at all, since a
|
|
126
|
+
* declared one keeps the binary encoding. Anything else, and anything
|
|
127
|
+
* under `WRITE_BYTES_FROM` elements, is handed to the string path.
|
|
128
|
+
*
|
|
129
|
+
* @param io The buffer to write into - the connection's own.
|
|
130
|
+
* @param value The array to write.
|
|
131
|
+
* @param options Passed to the element encoder, when there is one.
|
|
132
|
+
* @param encode The element type's own text encoder, if the type was
|
|
133
|
+
* declared.
|
|
134
|
+
*/
|
|
135
|
+
/* The string was never wanted: writeLString() encoded it to UTF-8 and
|
|
136
|
+
threw it away. For a 100 000-element int4[] it is 1.1MB, built out of
|
|
137
|
+
~200 000 rope nodes, flattened once and encoded once - counted with
|
|
138
|
+
--trace-gc over 100 calls, that step collects 10.1 MB a call.
|
|
139
|
+
|
|
140
|
+
The saving is not in avoiding the string, though. Writing bytes
|
|
141
|
+
through Buffer.write() per element is *slower* than letting V8 build a
|
|
142
|
+
rope and flatten it once - 1.1x to 1.35x slower across every size and
|
|
143
|
+
type, which is why this is not simply the byte-writing version of
|
|
144
|
+
stringifyArrayLiteral(). What pays is never producing the element's
|
|
145
|
+
text at all: an integer's digits go into the buffer from the number
|
|
146
|
+
itself, with no string and no per-element call. Against the string
|
|
147
|
+
path on an int4[], medians of alternating runs:
|
|
148
|
+
|
|
149
|
+
elements 64 1 000 100 000
|
|
150
|
+
string 2.38 us 22.2 us 3180 us
|
|
151
|
+
digits 0.88 us 4.8 us 917 us
|
|
152
|
+
2.7x 4.6x 3.5x
|
|
153
|
+
|
|
154
|
+
What a caller waits for moves less, and the difference is worth
|
|
155
|
+
knowing before quoting one: inserting the same array over a loopback
|
|
156
|
+
connection is 14.21ms against 12.51ms, 1.14x, because the server's own
|
|
157
|
+
parse of a 1.1MB literal is most of it. The allocation is gone either
|
|
158
|
+
way - 10.10 MB a call to 0.00.
|
|
159
|
+
|
|
160
|
+
So the fast lane is integers, and everything else on this path - a
|
|
161
|
+
float, a bigint too large to be exact, anything a reader of the array
|
|
162
|
+
did not expect - falls back to its own text and is written as such. */
|
|
163
|
+
export function writeArrayLiteral(io, value, options, encode) {
|
|
164
|
+
if (encode ||
|
|
165
|
+
!Array.isArray(value) ||
|
|
166
|
+
value.length < WRITE_BYTES_FROM ||
|
|
167
|
+
!isInt32(arrayLeaf(value))) {
|
|
168
|
+
io.writeLString(stringifyArrayLiteral(value, options, encode), 'utf8');
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const dim = arrayCalculateDim(value);
|
|
172
|
+
const lastLevel = dim.length - 1;
|
|
173
|
+
// The length is only known once everything is written, so the field is
|
|
174
|
+
// reserved now and filled in at the end - the same shape the binary
|
|
175
|
+
// encoders use for their own payloads.
|
|
176
|
+
io.writeInt32BE(0);
|
|
177
|
+
const lengthAt = io.size - 4;
|
|
178
|
+
const start = io.size;
|
|
179
|
+
let p = 0;
|
|
180
|
+
const writeDim = (arr, level) => {
|
|
181
|
+
const elemCount = dim[level];
|
|
182
|
+
const isLeafLevel = level >= lastLevel;
|
|
183
|
+
// No room check here: this is entered either at the top level, with
|
|
184
|
+
// an empty scratch, or from inside the loop below, which has just
|
|
185
|
+
// made room for the separator, the longest number, and both braces.
|
|
186
|
+
chunk[p++] = 123; /* { */
|
|
187
|
+
let x;
|
|
188
|
+
let s;
|
|
189
|
+
let v;
|
|
190
|
+
let q;
|
|
191
|
+
let i;
|
|
192
|
+
for (i = 0; i < elemCount; i++) {
|
|
193
|
+
// Every element writes at most a separator, a sign and 24 digits,
|
|
194
|
+
// plus the two braces a nested dimension would open and close
|
|
195
|
+
// around them; the text branch reserves its own room below. That
|
|
196
|
+
// headroom is what lets the braces be written unchecked.
|
|
197
|
+
if (p > CHUNK - 32) {
|
|
198
|
+
io.writeBytes(chunk.subarray(0, p));
|
|
199
|
+
p = 0;
|
|
200
|
+
}
|
|
201
|
+
if (i)
|
|
202
|
+
chunk[p++] = 44; /* , */
|
|
203
|
+
x = arr && arr[i];
|
|
204
|
+
if (!isLeafLevel) {
|
|
205
|
+
if (x != null && !Array.isArray(x))
|
|
206
|
+
x = [x];
|
|
207
|
+
writeDim(x, level + 1);
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if (x == null) {
|
|
211
|
+
chunk[p++] = 78; /* N */
|
|
212
|
+
chunk[p++] = 85; /* U */
|
|
213
|
+
chunk[p++] = 76; /* L */
|
|
214
|
+
chunk[p++] = 76; /* L */
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
// int32 rather than any safe integer: the digits come out of a
|
|
218
|
+
// repeated `(v / 10) | 0`, which is exact and fast only within
|
|
219
|
+
// that range. Above it, dividing a double sixteen times per
|
|
220
|
+
// element is slower than letting V8 print the number - measured at
|
|
221
|
+
// 11x slower on values near 9e15 - so those go the same way as a
|
|
222
|
+
// float does, through their own text.
|
|
223
|
+
if (x >= -2147483648 && x <= 2147483647 && Number.isInteger(x)) {
|
|
224
|
+
v = x;
|
|
225
|
+
if (v < 0) {
|
|
226
|
+
chunk[p++] = 45; /* - */
|
|
227
|
+
v = -v;
|
|
228
|
+
}
|
|
229
|
+
q = 24;
|
|
230
|
+
do {
|
|
231
|
+
DIGITS[--q] = 48 + (v % 10);
|
|
232
|
+
v = (v / 10) | 0;
|
|
233
|
+
} while (v);
|
|
234
|
+
while (q < 24)
|
|
235
|
+
chunk[p++] = DIGITS[q++];
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
// Anything else: its own text, quoted exactly as the string path
|
|
239
|
+
// would quote it.
|
|
240
|
+
// Asked before the text is produced, and of the value rather than
|
|
241
|
+
// of its spelling - the same rule the string path states: a
|
|
242
|
+
// string's own text is quoted whatever it looks like.
|
|
243
|
+
const isNumber = typeof x === 'number' || typeof x === 'bigint';
|
|
244
|
+
s = '' + x;
|
|
245
|
+
const bare = isNumber && BARE_NUMBER.test(s);
|
|
246
|
+
if (!bare)
|
|
247
|
+
s =
|
|
248
|
+
s.indexOf('\\') < 0 && s.indexOf('"') < 0
|
|
249
|
+
? s
|
|
250
|
+
: s.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
251
|
+
// A UTF-16 code unit is at most three UTF-8 bytes, which is the
|
|
252
|
+
// room to have without measuring the string first. The two quotes
|
|
253
|
+
// are in it, and one byte more for the `}` that may follow this
|
|
254
|
+
// element without a check of its own.
|
|
255
|
+
const bound = s.length * 3 + 3;
|
|
256
|
+
if (p + bound > CHUNK) {
|
|
257
|
+
io.writeBytes(chunk.subarray(0, p));
|
|
258
|
+
p = 0;
|
|
259
|
+
}
|
|
260
|
+
if (bound > CHUNK) {
|
|
261
|
+
// One element larger than the whole scratch - a long text value.
|
|
262
|
+
// It goes out on its own rather than growing anything, and
|
|
263
|
+
// `Buffer.write` would otherwise have truncated it in silence.
|
|
264
|
+
io.writeBytes(Buffer.from(bare ? s : '"' + s + '"', 'utf8'));
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
if (bare)
|
|
268
|
+
p += chunk.write(s, p, 'utf8');
|
|
269
|
+
else {
|
|
270
|
+
chunk[p++] = 34; /* " */
|
|
271
|
+
p += chunk.write(s, p, 'utf8');
|
|
272
|
+
chunk[p++] = 34;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
chunk[p++] = 125; /* } */
|
|
276
|
+
};
|
|
277
|
+
writeDim(value, 0);
|
|
278
|
+
if (p)
|
|
279
|
+
io.writeBytes(chunk.subarray(0, p));
|
|
280
|
+
io.buffer.writeInt32BE(io.size - start, lengthAt);
|
|
281
|
+
}
|
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
import type { DataMappingOptions } from '../interfaces/data-mapping-options.js';
|
|
2
2
|
import type { EncodeTextFunction } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Renders an array as the `ARRAY[...]` an SQL statement can carry.
|
|
5
|
+
*
|
|
6
|
+
* For the `sql` tag, which puts values into the text rather than sending
|
|
7
|
+
* them as parameters.
|
|
8
|
+
*
|
|
9
|
+
* @param arr The array, nested to any depth.
|
|
10
|
+
* @param options Passed to the element encoder.
|
|
11
|
+
* @returns The literal, cast to the element type it was built for.
|
|
12
|
+
*/
|
|
3
13
|
export declare function stringifyArrayForSQL(v: any[], options?: DataMappingOptions, encode?: EncodeTextFunction): string;
|
|
14
|
+
/**
|
|
15
|
+
* Renders one value as the literal an SQL statement can carry.
|
|
16
|
+
*
|
|
17
|
+
* @param v The value.
|
|
18
|
+
* @param options Passed to the type's own text encoder.
|
|
19
|
+
* @returns The literal, quoted and escaped as the value needs.
|
|
20
|
+
*/
|
|
4
21
|
export declare function stringifyValueForSQL(v: any, options?: DataMappingOptions, encode?: EncodeTextFunction): string;
|
|
@@ -3,6 +3,16 @@ import { GlobalTypeMap } from '../data-type-map.js';
|
|
|
3
3
|
import { UuidType } from '../data-types/uuid-type.js';
|
|
4
4
|
import { escapeLiteral } from './escape-literal.js';
|
|
5
5
|
import { formatDateParam } from './format-datetime.js';
|
|
6
|
+
/**
|
|
7
|
+
* Renders an array as the `ARRAY[...]` an SQL statement can carry.
|
|
8
|
+
*
|
|
9
|
+
* For the `sql` tag, which puts values into the text rather than sending
|
|
10
|
+
* them as parameters.
|
|
11
|
+
*
|
|
12
|
+
* @param arr The array, nested to any depth.
|
|
13
|
+
* @param options Passed to the element encoder.
|
|
14
|
+
* @returns The literal, cast to the element type it was built for.
|
|
15
|
+
*/
|
|
6
16
|
export function stringifyArrayForSQL(v, options, encode) {
|
|
7
17
|
const arr = v.map(x => stringifyValueForSQL(x, options, encode));
|
|
8
18
|
return 'ARRAY[' + arr.join(',') + ']';
|
|
@@ -38,6 +48,13 @@ function stringifyObjectForSQL(v, options) {
|
|
|
38
48
|
dataType.name);
|
|
39
49
|
return escapeLiteral(JSON.stringify(v)) + '::json';
|
|
40
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Renders one value as the literal an SQL statement can carry.
|
|
53
|
+
*
|
|
54
|
+
* @param v The value.
|
|
55
|
+
* @param options Passed to the type's own text encoder.
|
|
56
|
+
* @returns The literal, quoted and escaped as the value needs.
|
|
57
|
+
*/
|
|
41
58
|
export function stringifyValueForSQL(v, options, encode) {
|
|
42
59
|
if (v == null)
|
|
43
60
|
return 'null';
|
|
@@ -3,4 +3,14 @@ import type { DataTypeMap } from '../data-type-map.js';
|
|
|
3
3
|
import type { DataMappingOptions } from '../interfaces/data-mapping-options.js';
|
|
4
4
|
import type { FieldInfo } from '../interfaces/field-info.js';
|
|
5
5
|
import type { Protocol } from '../protocol/protocol.js';
|
|
6
|
+
/**
|
|
7
|
+
* Turns the server's RowDescription into the `FieldInfo[]` a caller
|
|
8
|
+
* sees, naming each column's type and what it maps to.
|
|
9
|
+
*
|
|
10
|
+
* @param typeMap Where the types are registered.
|
|
11
|
+
* @param fields The columns, as the server described them.
|
|
12
|
+
* @param columnFormat What format they are coming back in.
|
|
13
|
+
* @param options The mapping options in force.
|
|
14
|
+
* @returns One FieldInfo per column, in order.
|
|
15
|
+
*/
|
|
6
16
|
export declare function wrapRowDescription(typeMap: DataTypeMap, fields: Protocol.RowDescription[], columnFormat: DataFormat | DataFormat[], mappingOptions?: DataMappingOptions): FieldInfo[];
|
|
@@ -9,6 +9,16 @@ const DataTypeOIDByName = {};
|
|
|
9
9
|
for (const oid of Object.keys(DataTypeNames)) {
|
|
10
10
|
DataTypeOIDByName[DataTypeNames[oid]] = Number(oid);
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Turns the server's RowDescription into the `FieldInfo[]` a caller
|
|
14
|
+
* sees, naming each column's type and what it maps to.
|
|
15
|
+
*
|
|
16
|
+
* @param typeMap Where the types are registered.
|
|
17
|
+
* @param fields The columns, as the server described them.
|
|
18
|
+
* @param columnFormat What format they are coming back in.
|
|
19
|
+
* @param options The mapping options in force.
|
|
20
|
+
* @returns One FieldInfo per column, in order.
|
|
21
|
+
*/
|
|
12
22
|
export function wrapRowDescription(typeMap, fields, columnFormat, mappingOptions) {
|
|
13
23
|
const asString = mappingOptions?.fetchAsString;
|
|
14
24
|
return fields.map((f, idx) => {
|