postgrejs 3.1.3 → 3.4.0
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/CHANGELOG.md +79 -1
- package/README.md +79 -13
- package/connection/connection.d.ts +97 -0
- package/connection/connection.js +141 -2
- package/connection/cursor.d.ts +2 -1
- package/connection/cursor.js +6 -6
- package/connection/intl-connection.d.ts +113 -3
- package/connection/intl-connection.js +530 -45
- package/connection/prepared-statement.d.ts +64 -1
- package/connection/prepared-statement.js +97 -6
- package/data-types/bool-type.js +0 -1
- package/data-types/box-type.js +0 -1
- package/data-types/bytea-type.js +5 -3
- package/data-types/char-type.js +2 -2
- package/data-types/circle-type.js +0 -1
- package/data-types/date-type.js +1 -2
- package/data-types/float4-type.js +4 -5
- package/data-types/float8-type.js +4 -6
- package/data-types/int2-type.js +2 -2
- package/data-types/int2-vector-type.js +3 -2
- package/data-types/int4-type.js +2 -2
- package/data-types/int8-type.js +2 -2
- package/data-types/json-type.js +2 -2
- package/data-types/jsonb-type.js +6 -5
- package/data-types/lseg-type.js +0 -1
- package/data-types/numeric-type.js +9 -4
- package/data-types/oid-type.js +2 -2
- package/data-types/oid-vector-type.js +3 -2
- package/data-types/point-type.js +0 -1
- package/data-types/time-type.js +1 -2
- package/data-types/timestamp-type.js +13 -3
- package/data-types/timestamptz-type.js +27 -10
- package/data-types/uuid-type.js +1 -2
- package/data-types/varchar-type.js +2 -2
- package/index.d.ts +4 -0
- package/index.js +4 -0
- package/interfaces/batch-result.d.ts +42 -0
- package/interfaces/batch-result.js +1 -0
- package/interfaces/command-result.d.ts +3 -2
- package/interfaces/copy-from-rows-options.d.ts +58 -0
- package/interfaces/copy-from-rows-options.js +1 -0
- package/interfaces/data-type.d.ts +0 -1
- package/interfaces/database-connection-params.d.ts +25 -0
- package/interfaces/pipeline-request.d.ts +16 -0
- package/interfaces/pipeline-request.js +1 -0
- package/interfaces/query-options.d.ts +18 -0
- package/interfaces/script-execute-options.d.ts +12 -0
- package/package.json +18 -3
- package/protocol/backend.js +6 -6
- package/protocol/buffer-reader.d.ts +7 -12
- package/protocol/buffer-reader.js +11 -58
- package/protocol/database-error.d.ts +16 -0
- package/protocol/database-error.js +15 -0
- package/protocol/frontend.js +86 -96
- package/protocol/pg-socket.d.ts +82 -33
- package/protocol/pg-socket.js +143 -86
- package/protocol/pgoutput.js +2 -2
- package/protocol/smart-buffer.d.ts +11 -29
- package/protocol/smart-buffer.js +19 -162
- package/types.d.ts +13 -1
- package/util/assert-integer.d.ts +43 -0
- package/util/assert-integer.js +58 -0
- package/util/bigint-methods.d.ts +0 -1
- package/util/bigint-methods.js +0 -22
- package/util/copy-from-rows.d.ts +56 -0
- package/util/copy-from-rows.js +95 -0
- package/util/decode-binaryarray.d.ts +1 -1
- package/util/decode-binaryarray.js +7 -7
- package/util/encode-binaryarray.js +6 -6
- package/util/encode-copy-binary.d.ts +48 -0
- package/util/encode-copy-binary.js +112 -0
- package/util/fast-parsefloat.d.ts +15 -0
- package/util/fast-parsefloat.js +141 -0
- package/util/get-parsers.js +4 -8
- package/util/parse-datetime.js +7 -0
- package/util/parse-pg-timestamp.d.ts +31 -0
- package/util/parse-pg-timestamp.js +199 -0
- package/util/parse-row.js +120 -0
- package/util/row-decoder.d.ts +49 -0
- package/util/row-decoder.js +63 -0
|
@@ -2,13 +2,13 @@ import { DataTypeOIDs } from '../constants.js';
|
|
|
2
2
|
import { SmartBuffer } from '../protocol/smart-buffer.js';
|
|
3
3
|
import { formatTimestamptz } from '../util/format-datetime.js';
|
|
4
4
|
import { parseDateTimeTz } from '../util/parse-datetime.js';
|
|
5
|
+
import { parsePgTimestampBuffer } from '../util/parse-pg-timestamp.js';
|
|
5
6
|
const timeShift = 946684800000;
|
|
6
7
|
const timeMul = 4294967296;
|
|
7
8
|
export const TimestamptzType = {
|
|
8
9
|
name: 'timestamptz',
|
|
9
10
|
oid: DataTypeOIDs.timestamptz,
|
|
10
11
|
jsType: 'Date',
|
|
11
|
-
fixedBinarySize: 8,
|
|
12
12
|
encodeText(v) {
|
|
13
13
|
return formatTimestamptz(v);
|
|
14
14
|
},
|
|
@@ -34,7 +34,7 @@ export const TimestamptzType = {
|
|
|
34
34
|
buf.writeInt32BE(hi);
|
|
35
35
|
buf.writeUInt32BE(lo);
|
|
36
36
|
},
|
|
37
|
-
decodeBinary(v, offset = 0, options) {
|
|
37
|
+
decodeBinary(v, offset = 0, _len, options) {
|
|
38
38
|
const fetchAsString = options.fetchAsString?.includes(DataTypeOIDs.timestamptz);
|
|
39
39
|
const hi = v.readInt32BE(offset);
|
|
40
40
|
const lo = v.readUInt32BE(offset + 4);
|
|
@@ -42,11 +42,16 @@ export const TimestamptzType = {
|
|
|
42
42
|
return fetchAsString ? 'infinity' : Infinity;
|
|
43
43
|
if (lo === 0x00000000 && hi === -0x80000000)
|
|
44
44
|
return fetchAsString ? '-infinity' : -Infinity;
|
|
45
|
-
// Shift from 2000 to 1970
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
// Shift from 2000 to 1970. A timestamptz is an absolute instant, so
|
|
46
|
+
// this is already the value - there is nothing to reinterpret against
|
|
47
|
+
// the local zone the way `timestamp` (which carries no zone of its
|
|
48
|
+
// own) has to. Rebuilding the Date from its own local getters, as this
|
|
49
|
+
// used to, gave back the same instant for every value except one: an
|
|
50
|
+
// instant inside the hour that repeats when local time falls back is
|
|
51
|
+
// ambiguous read as wall-clock, so the rebuild silently picked the
|
|
52
|
+
// other one and moved the value an hour. The text path never did that,
|
|
53
|
+
// so the same row decoded binary and text disagreed.
|
|
54
|
+
const d = new Date((lo + hi * timeMul) / 1000 + timeShift);
|
|
50
55
|
return fetchAsString ? dateToTimestamptzString(d) : d;
|
|
51
56
|
},
|
|
52
57
|
decodeText(v, options) {
|
|
@@ -64,11 +69,23 @@ export const TimestamptzType = {
|
|
|
64
69
|
}
|
|
65
70
|
return d;
|
|
66
71
|
},
|
|
67
|
-
//
|
|
68
|
-
//
|
|
72
|
+
// Reads PostgreSQL's own timestamp shape straight from the wire bytes.
|
|
73
|
+
// Building the string first and handing it to decodeText() costs about
|
|
74
|
+
// as much again as the parse itself, for a string that exists only to be
|
|
75
|
+
// scanned a character at a time. Anything not in that exact shape
|
|
76
|
+
// (infinity, a BC suffix, an LMT-style offset) has no Date to give back
|
|
77
|
+
// and takes the original path, which still needs the string.
|
|
78
|
+
//
|
|
79
|
+
// Note this type's decodeText always parses first and only branches on
|
|
69
80
|
// fetchAsString afterward (unlike date/time/timestamp, which early-return
|
|
70
|
-
// the raw string)
|
|
81
|
+
// the raw string), so the same order is kept here.
|
|
71
82
|
decodeTextBuffer(buf, offset, len, options) {
|
|
83
|
+
const d = parsePgTimestampBuffer(buf, offset, offset + len);
|
|
84
|
+
if (d !== undefined) {
|
|
85
|
+
return options.fetchAsString?.includes(DataTypeOIDs.timestamptz)
|
|
86
|
+
? dateToTimestamptzString(d)
|
|
87
|
+
: d;
|
|
88
|
+
}
|
|
72
89
|
return TimestamptzType.decodeText(buf.toString('latin1', offset, offset + len), options);
|
|
73
90
|
},
|
|
74
91
|
isType(v) {
|
package/data-types/uuid-type.js
CHANGED
|
@@ -4,7 +4,6 @@ export const UuidType = {
|
|
|
4
4
|
name: 'uuid',
|
|
5
5
|
oid: DataTypeOIDs.uuid,
|
|
6
6
|
jsType: 'String',
|
|
7
|
-
fixedBinarySize: 16,
|
|
8
7
|
encodeText(v) {
|
|
9
8
|
return '' + v;
|
|
10
9
|
},
|
|
@@ -12,7 +11,7 @@ export const UuidType = {
|
|
|
12
11
|
if (!GUID_PATTERN.test(v))
|
|
13
12
|
throw new Error(`"${v}" is not a valid guid value`);
|
|
14
13
|
const b = Buffer.from(v.replace(/-/g, ''), 'hex');
|
|
15
|
-
buf.
|
|
14
|
+
buf.writeBytes(b);
|
|
16
15
|
},
|
|
17
16
|
decodeBinary(v, offset = 0) {
|
|
18
17
|
return (v.toString('hex', offset, offset + 4) +
|
|
@@ -9,8 +9,8 @@ export const VarcharType = {
|
|
|
9
9
|
encodeBinary(buf, v) {
|
|
10
10
|
buf.writeString('' + v, 'utf8');
|
|
11
11
|
},
|
|
12
|
-
decodeBinary(v, offset = 0) {
|
|
13
|
-
return v.toString('utf8', offset);
|
|
12
|
+
decodeBinary(v, offset = 0, len) {
|
|
13
|
+
return v.toString('utf8', offset, offset + len);
|
|
14
14
|
},
|
|
15
15
|
decodeText(v) {
|
|
16
16
|
// The wire decoder always hands this a string (see intl-connection.ts's
|
package/index.d.ts
CHANGED
|
@@ -8,13 +8,16 @@ export * from './connection/pool.js';
|
|
|
8
8
|
export * from './connection/prepared-statement.js';
|
|
9
9
|
export * from './constants.js';
|
|
10
10
|
export * from './data-type-map.js';
|
|
11
|
+
export * from './interfaces/batch-result.js';
|
|
11
12
|
export * from './interfaces/command-result.js';
|
|
13
|
+
export * from './interfaces/copy-from-rows-options.js';
|
|
12
14
|
export * from './interfaces/data-mapping-options.js';
|
|
13
15
|
export * from './interfaces/data-type.js';
|
|
14
16
|
export * from './interfaces/database-connection-params.js';
|
|
15
17
|
export * from './interfaces/field-info.js';
|
|
16
18
|
export * from './interfaces/function-call-options.js';
|
|
17
19
|
export * from './interfaces/function-call-result.js';
|
|
20
|
+
export * from './interfaces/pipeline-request.js';
|
|
18
21
|
export * from './interfaces/query-options.js';
|
|
19
22
|
export * from './interfaces/query-result.js';
|
|
20
23
|
export * from './interfaces/script-execute-options.js';
|
|
@@ -27,6 +30,7 @@ export * from './util/connection-config.js';
|
|
|
27
30
|
export * from './util/escape-identifier.js';
|
|
28
31
|
export * from './util/escape-literal.js';
|
|
29
32
|
export * from './util/parse-datetime.js';
|
|
33
|
+
export * from './util/row-decoder.js';
|
|
30
34
|
export * from './util/sql-tag.js';
|
|
31
35
|
export * from './util/stringify-arrayliteral.js';
|
|
32
36
|
export * from './util/stringify-for-sql.js';
|
package/index.js
CHANGED
|
@@ -8,13 +8,16 @@ export * from './connection/pool.js';
|
|
|
8
8
|
export * from './connection/prepared-statement.js';
|
|
9
9
|
export * from './constants.js';
|
|
10
10
|
export * from './data-type-map.js';
|
|
11
|
+
export * from './interfaces/batch-result.js';
|
|
11
12
|
export * from './interfaces/command-result.js';
|
|
13
|
+
export * from './interfaces/copy-from-rows-options.js';
|
|
12
14
|
export * from './interfaces/data-mapping-options.js';
|
|
13
15
|
export * from './interfaces/data-type.js';
|
|
14
16
|
export * from './interfaces/database-connection-params.js';
|
|
15
17
|
export * from './interfaces/field-info.js';
|
|
16
18
|
export * from './interfaces/function-call-options.js';
|
|
17
19
|
export * from './interfaces/function-call-result.js';
|
|
20
|
+
export * from './interfaces/pipeline-request.js';
|
|
18
21
|
export * from './interfaces/query-options.js';
|
|
19
22
|
export * from './interfaces/query-result.js';
|
|
20
23
|
export * from './interfaces/script-execute-options.js';
|
|
@@ -27,6 +30,7 @@ export * from './util/connection-config.js';
|
|
|
27
30
|
export * from './util/escape-identifier.js';
|
|
28
31
|
export * from './util/escape-literal.js';
|
|
29
32
|
export * from './util/parse-datetime.js';
|
|
33
|
+
export * from './util/row-decoder.js';
|
|
30
34
|
export * from './util/sql-tag.js';
|
|
31
35
|
export * from './util/stringify-arrayliteral.js';
|
|
32
36
|
export * from './util/stringify-for-sql.js';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { FieldInfo } from './field-info.js';
|
|
2
|
+
/**
|
|
3
|
+
* What one parameter set in a batch produced. There is exactly one of
|
|
4
|
+
* these per set handed to `PreparedStatement.executeBatch()`, in the same
|
|
5
|
+
* order - the server answers each Execute with its own CommandComplete,
|
|
6
|
+
* so the mapping is positional and does not depend on the statement.
|
|
7
|
+
*/
|
|
8
|
+
export interface BatchCommandResult {
|
|
9
|
+
/** The command tag PostgreSQL reported for this set (INSERT/UPDATE/...). */
|
|
10
|
+
command?: string;
|
|
11
|
+
/** Rows affected, for INSERT/UPDATE/DELETE - as in QueryResult. */
|
|
12
|
+
rowsAffected?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Rows this set returned, decoded the same way `execute()` decodes them
|
|
15
|
+
* (including any `rowDecoder` given in the options). Only present when
|
|
16
|
+
* the statement actually returns rows - a plain UPDATE without RETURNING
|
|
17
|
+
* leaves this undefined rather than setting it to an empty array.
|
|
18
|
+
*/
|
|
19
|
+
rows?: any[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The result of `PreparedStatement.executeBatch()`.
|
|
23
|
+
*
|
|
24
|
+
* `results` is always the full set of *completed* sets. On success that is
|
|
25
|
+
* every set that was submitted; when the server rejects one, the batch
|
|
26
|
+
* stops there (see the class doc) and the completed prefix is attached to
|
|
27
|
+
* the thrown error as `batchResults` instead.
|
|
28
|
+
*/
|
|
29
|
+
export interface BatchResult {
|
|
30
|
+
/** One entry per parameter set, in submission order. */
|
|
31
|
+
results: BatchCommandResult[];
|
|
32
|
+
/** Sum of every set's `rowsAffected`, for the common bulk-write case. */
|
|
33
|
+
totalRowsAffected: number;
|
|
34
|
+
/**
|
|
35
|
+
* Column descriptions, when the statement returns rows. One copy for the
|
|
36
|
+
* whole batch rather than per set: every set runs the same prepared
|
|
37
|
+
* statement, so the shape cannot differ between them.
|
|
38
|
+
*/
|
|
39
|
+
fields?: FieldInfo[];
|
|
40
|
+
/** Wall time for the whole batch, when `timing` is enabled. */
|
|
41
|
+
executeTime?: number;
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -14,9 +14,10 @@ export interface CommandResult {
|
|
|
14
14
|
*/
|
|
15
15
|
rows?: Row[];
|
|
16
16
|
/**
|
|
17
|
-
* Contains row type
|
|
17
|
+
* Contains row type - `'custom'` when a custom `RowDecoder` instance was
|
|
18
|
+
* supplied via `rowDecoder` (there's no way to know what shape it returns)
|
|
18
19
|
*/
|
|
19
|
-
rowType?: 'array' | 'object';
|
|
20
|
+
rowType?: 'array' | 'object' | 'custom';
|
|
20
21
|
/**
|
|
21
22
|
* Time elapsed to execute command - only measured when `timing` is
|
|
22
23
|
* enabled (off by default; see `DatabaseConnectionParams.timing`).
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { DataTypeMap } from '../data-type-map.js';
|
|
2
|
+
import type { OID } from '../types.js';
|
|
3
|
+
import type { DataMappingOptions } from './data-mapping-options.js';
|
|
4
|
+
export interface CopyFromRowsOptions extends DataMappingOptions {
|
|
5
|
+
/** Type registry used to encode values; defaults to GlobalTypeMap. */
|
|
6
|
+
typeMap?: DataTypeMap;
|
|
7
|
+
/**
|
|
8
|
+
* Destination columns, in the order the rows supply them. Omitted means
|
|
9
|
+
* every column of the table, in table order - the same default `COPY
|
|
10
|
+
* table FROM STDIN` has without a column list.
|
|
11
|
+
*/
|
|
12
|
+
columns?: string[];
|
|
13
|
+
/**
|
|
14
|
+
* Type OIDs for those columns, skipping the round trip that would
|
|
15
|
+
* otherwise ask the server for them.
|
|
16
|
+
*
|
|
17
|
+
* Only worth setting to avoid that probe on a hot path, and only when the
|
|
18
|
+
* OIDs are known to match the table: binary COPY does no conversion, so a
|
|
19
|
+
* wrong OID here is not a mismatch the server can reconcile - it either
|
|
20
|
+
* rejects the stream or, for two types that happen to share a width,
|
|
21
|
+
* stores the bytes as the wrong value.
|
|
22
|
+
*/
|
|
23
|
+
columnTypes?: OID[];
|
|
24
|
+
/**
|
|
25
|
+
* Bytes to accumulate before sending a CopyData message. Defaults to
|
|
26
|
+
* 128KB; anything from 64KB to 256KB measures much the same, while a
|
|
27
|
+
* message per row is roughly ten times slower.
|
|
28
|
+
*/
|
|
29
|
+
chunkSize?: number;
|
|
30
|
+
/**
|
|
31
|
+
* What to do with a value the destination column's type cannot encode -
|
|
32
|
+
* `'abc'` for an integer column, `{}` for a numeric one.
|
|
33
|
+
*
|
|
34
|
+
* `'throw'` (default) aborts the copy, naming the row and column. The
|
|
35
|
+
* other two exist for a load big enough that abandoning it over one bad
|
|
36
|
+
* record costs more than the record is worth: `'null'` writes NULL in
|
|
37
|
+
* that column and keeps the row, `'skip'` drops the row entirely. Both
|
|
38
|
+
* report how many they touched, so a tolerant load still says what it
|
|
39
|
+
* swallowed rather than looking clean.
|
|
40
|
+
*
|
|
41
|
+
* None of them apply to NaN or Infinity in a float or numeric column -
|
|
42
|
+
* PostgreSQL stores those as values distinct from NULL, so they encode
|
|
43
|
+
* normally and are never "invalid".
|
|
44
|
+
*/
|
|
45
|
+
onInvalidValue?: 'throw' | 'null' | 'skip';
|
|
46
|
+
}
|
|
47
|
+
/** What `copyFromRows()` reports back. */
|
|
48
|
+
export interface CopyFromRowsResult {
|
|
49
|
+
/** Rows actually sent to the server. */
|
|
50
|
+
rowCount: number;
|
|
51
|
+
/**
|
|
52
|
+
* Rows dropped under `onInvalidValue: 'skip'`. Always 0 otherwise, and a
|
|
53
|
+
* non-zero value here is the only sign a tolerant load lost anything.
|
|
54
|
+
*/
|
|
55
|
+
skippedRows: number;
|
|
56
|
+
/** Values replaced with NULL under `onInvalidValue: 'null'`. */
|
|
57
|
+
nulledValues: number;
|
|
58
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -10,7 +10,6 @@ export interface DataType {
|
|
|
10
10
|
decodeBinary: DecodeBinaryFunction;
|
|
11
11
|
decodeText: DecodeTextFunction;
|
|
12
12
|
decodeTextBuffer?: DecodeTextBufferFunction;
|
|
13
|
-
fixedBinarySize?: number;
|
|
14
13
|
encodeAsNull?: EncodeAsNullFunction;
|
|
15
14
|
encodeBinary?: EncodeBinaryFunction;
|
|
16
15
|
encodeText?: EncodeTextFunction;
|
|
@@ -83,6 +83,31 @@ export interface DatabaseConnectionParams {
|
|
|
83
83
|
* @default false
|
|
84
84
|
*/
|
|
85
85
|
autoCommit?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Reuse a server-side prepared statement for SQL this connection has run
|
|
88
|
+
* before, instead of parsing it again every time.
|
|
89
|
+
*
|
|
90
|
+
* On by default. A repeated query then costs Bind/Execute rather than
|
|
91
|
+
* Parse/Bind/Describe/Execute, which on fifty concurrent calls of one
|
|
92
|
+
* statement measured 0.97ms against 3.13ms.
|
|
93
|
+
*
|
|
94
|
+
* Turn it off when named prepared statements cannot survive between
|
|
95
|
+
* calls - the usual case being PgBouncer in transaction pooling mode
|
|
96
|
+
* before 1.21, which hands each transaction a different backend, so a
|
|
97
|
+
* statement prepared on one is missing on the next.
|
|
98
|
+
*
|
|
99
|
+
* @default true
|
|
100
|
+
*/
|
|
101
|
+
prepare?: boolean;
|
|
102
|
+
/**
|
|
103
|
+
* How many prepared statements one connection keeps. The least recently
|
|
104
|
+
* used is closed when the limit is reached, so an application that
|
|
105
|
+
* builds SQL text dynamically cannot accumulate statements on the server
|
|
106
|
+
* without bound.
|
|
107
|
+
*
|
|
108
|
+
* @default 64
|
|
109
|
+
*/
|
|
110
|
+
preparedStatementCacheSize?: number;
|
|
86
111
|
/**
|
|
87
112
|
* When on, if a statement in a transaction block generates an error,
|
|
88
113
|
* the error is ignored and the transaction continues.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Maybe, OID } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* One statement in a `Connection.pipeline()` call. The `sql` tag's own
|
|
4
|
+
* output satisfies this shape, so a pipeline can be written straight from
|
|
5
|
+
* tagged templates without any conversion.
|
|
6
|
+
*/
|
|
7
|
+
export interface PipelineRequest {
|
|
8
|
+
sql: string;
|
|
9
|
+
params?: any[];
|
|
10
|
+
/**
|
|
11
|
+
* Parameter type OIDs for this statement. Per statement rather than per
|
|
12
|
+
* pipeline: the statements differ, so one shared list could only ever be
|
|
13
|
+
* right for one of them.
|
|
14
|
+
*/
|
|
15
|
+
paramTypes?: Maybe<OID>[];
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { BindParam } from '../connection/bind-param.js';
|
|
2
2
|
import type { DataFormat } from '../constants.js';
|
|
3
3
|
import type { DataTypeMap } from '../data-type-map.js';
|
|
4
|
+
import type { RowDecoder } from '../util/row-decoder.js';
|
|
4
5
|
import type { DataMappingOptions } from './data-mapping-options.js';
|
|
5
6
|
export interface QueryOptions extends DataMappingOptions {
|
|
6
7
|
/**
|
|
@@ -10,9 +11,26 @@ export interface QueryOptions extends DataMappingOptions {
|
|
|
10
11
|
autoCommit?: boolean;
|
|
11
12
|
/**
|
|
12
13
|
* Specifies if rows will be fetched as <FieldName, Value> pair objects or array of values
|
|
14
|
+
* @deprecated Use `rowDecoder: 'object'` instead - `objectRows: true` still works exactly
|
|
15
|
+
* as before, it's just the same thing `rowDecoder` now also expresses.
|
|
13
16
|
* @default false
|
|
14
17
|
*/
|
|
15
18
|
objectRows?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Overrides the connection's `prepare` setting for this call - `false`
|
|
21
|
+
* to keep a one-off statement out of the cache, `true` to use it on a
|
|
22
|
+
* connection that has caching off.
|
|
23
|
+
*/
|
|
24
|
+
prepare?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Controls how each row's raw column data is turned into the value handed back to the
|
|
27
|
+
* caller. `'array'` and `'object'` select the built-in decoders (the same output
|
|
28
|
+
* `objectRows` has always produced); pass an instance of your own `RowDecoder` subclass
|
|
29
|
+
* to take over decoding entirely instead - e.g. for lazy per-cell decoding. Takes
|
|
30
|
+
* precedence over `objectRows` when both are set.
|
|
31
|
+
* @default 'array'
|
|
32
|
+
*/
|
|
33
|
+
rowDecoder?: 'array' | 'object' | RowDecoder;
|
|
16
34
|
/**
|
|
17
35
|
* Data type map instance
|
|
18
36
|
* @default GlobalTypeMap
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { DataTypeMap } from '../data-type-map.js';
|
|
2
|
+
import type { RowDecoder } from '../util/row-decoder.js';
|
|
2
3
|
import type { DataMappingOptions } from './data-mapping-options.js';
|
|
3
4
|
export interface ScriptExecuteOptions extends DataMappingOptions {
|
|
4
5
|
/**
|
|
@@ -8,9 +9,20 @@ export interface ScriptExecuteOptions extends DataMappingOptions {
|
|
|
8
9
|
autoCommit?: boolean;
|
|
9
10
|
/**
|
|
10
11
|
* Specifies if rows will be fetched as <FieldName, Value> pair objects or array of values
|
|
12
|
+
* @deprecated Use `rowDecoder: 'object'` instead - `objectRows: true` still works exactly
|
|
13
|
+
* as before, it's just the same thing `rowDecoder` now also expresses.
|
|
11
14
|
* @default false
|
|
12
15
|
*/
|
|
13
16
|
objectRows?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Controls how each row's raw column data is turned into the value handed back to the
|
|
19
|
+
* caller. `'array'` and `'object'` select the built-in decoders (the same output
|
|
20
|
+
* `objectRows` has always produced); pass an instance of your own `RowDecoder` subclass
|
|
21
|
+
* to take over decoding entirely instead - e.g. for lazy per-cell decoding. Takes
|
|
22
|
+
* precedence over `objectRows` when both are set.
|
|
23
|
+
* @default 'array'
|
|
24
|
+
*/
|
|
25
|
+
rowDecoder?: 'array' | 'object' | RowDecoder;
|
|
14
26
|
/**
|
|
15
27
|
* Data type map instance
|
|
16
28
|
* @default GlobalTypeMap
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "postgrejs",
|
|
3
3
|
"description": "Professional PostgreSQL client NodeJS",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.4.0",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"@jsopen/objects": "^2.2.3",
|
|
9
9
|
"doublylinked": "^2.5.6",
|
|
10
|
+
"flexy-buffer": "^1.1.0",
|
|
10
11
|
"lightning-pool": "^4.12.0",
|
|
11
12
|
"power-tasks": "^1.14.2",
|
|
12
13
|
"putil-promisify": "^1.10.1",
|
|
@@ -28,7 +29,10 @@
|
|
|
28
29
|
},
|
|
29
30
|
"homepage": "https://www.postgrejs.com/",
|
|
30
31
|
"contributors": [
|
|
31
|
-
"Eray Hanoglu <e.hanoglu@panates.com>"
|
|
32
|
+
"Eray Hanoglu <e.hanoglu@panates.com>",
|
|
33
|
+
"Ilker Gurelli <i.gurelli@panates.com>",
|
|
34
|
+
"Onur Tokel <o.tokel@panates.com>",
|
|
35
|
+
"Bircan Yuruk <b.yuruk@panates.com>"
|
|
32
36
|
],
|
|
33
37
|
"repository": {
|
|
34
38
|
"type": "git",
|
|
@@ -45,7 +49,18 @@
|
|
|
45
49
|
"client",
|
|
46
50
|
"backend",
|
|
47
51
|
"rdbms",
|
|
48
|
-
"sql"
|
|
52
|
+
"sql",
|
|
53
|
+
"typescript",
|
|
54
|
+
"wire-protocol",
|
|
55
|
+
"no-native-bindings",
|
|
56
|
+
"cursor",
|
|
57
|
+
"server-side-cursor",
|
|
58
|
+
"logical-replication",
|
|
59
|
+
"copy",
|
|
60
|
+
"connection-pool",
|
|
61
|
+
"prepared-statements",
|
|
62
|
+
"bun",
|
|
63
|
+
"bunjs"
|
|
49
64
|
],
|
|
50
65
|
"publishConfig": {
|
|
51
66
|
"access": "public"
|
package/protocol/backend.js
CHANGED
|
@@ -124,7 +124,7 @@ function parseAuthentication(io, code, len) {
|
|
|
124
124
|
case 5:
|
|
125
125
|
return {
|
|
126
126
|
kind: 'MD5Password',
|
|
127
|
-
salt: io.
|
|
127
|
+
salt: io.readBytes(len - 8),
|
|
128
128
|
};
|
|
129
129
|
case 6:
|
|
130
130
|
return {
|
|
@@ -141,7 +141,7 @@ function parseAuthentication(io, code, len) {
|
|
|
141
141
|
case 8:
|
|
142
142
|
return {
|
|
143
143
|
kind: 'GSSContinue',
|
|
144
|
-
data: io.
|
|
144
|
+
data: io.readBytes(len - 8),
|
|
145
145
|
};
|
|
146
146
|
case 10: {
|
|
147
147
|
const out = {
|
|
@@ -174,7 +174,7 @@ function parseBackendKeyData(io) {
|
|
|
174
174
|
// this message's body (see Backend.parse()), so the secret key is
|
|
175
175
|
// simply whatever bytes remain - 4 of them before protocol 3.2, up to
|
|
176
176
|
// 256 with it (see VERSION_MINOR_LONG_CANCEL_KEY).
|
|
177
|
-
const secretKey = io.
|
|
177
|
+
const secretKey = io.readBytes();
|
|
178
178
|
return { processID, secretKey };
|
|
179
179
|
}
|
|
180
180
|
function parseCommandComplete(io) {
|
|
@@ -184,7 +184,7 @@ function parseCommandComplete(io) {
|
|
|
184
184
|
}
|
|
185
185
|
function parseCopyData(io, code, len) {
|
|
186
186
|
return {
|
|
187
|
-
data: io.
|
|
187
|
+
data: io.readBytes(len - 4),
|
|
188
188
|
};
|
|
189
189
|
}
|
|
190
190
|
function parseCopyResponse(io) {
|
|
@@ -208,7 +208,7 @@ function parseCopyResponse(io) {
|
|
|
208
208
|
}
|
|
209
209
|
function parseDataRow(io, code, len) {
|
|
210
210
|
const columnCount = io.readUInt16BE();
|
|
211
|
-
const data = io.
|
|
211
|
+
const data = io.readBytes(len - 6);
|
|
212
212
|
return { columnCount, data };
|
|
213
213
|
}
|
|
214
214
|
function parseErrorResponse(io) {
|
|
@@ -234,7 +234,7 @@ function parseFunctionCallResponse(io) {
|
|
|
234
234
|
// bytes following) - not deducible from the outer message length alone,
|
|
235
235
|
// unlike most fixed-shape messages this codebase parses.
|
|
236
236
|
const len = io.readInt32BE();
|
|
237
|
-
return { result: len < 0 ? null : io.
|
|
237
|
+
return { result: len < 0 ? null : io.readBytes(len) };
|
|
238
238
|
}
|
|
239
239
|
function parseNegotiateProtocolVersion(io) {
|
|
240
240
|
const supportedVersionMinor = io.readUInt32BE();
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
readInt16BE(): number;
|
|
9
|
-
readUInt32BE(): number;
|
|
10
|
-
readInt32BE(): number;
|
|
1
|
+
import { BufferReader as FlexyBufferReader } from 'flexy-buffer';
|
|
2
|
+
/**
|
|
3
|
+
* Adds the PostgreSQL wire format's two string encodings on top of
|
|
4
|
+
* flexy-buffer's `BufferReader`: a NUL-terminated C string, and a
|
|
5
|
+
* length-prefixed string where a negative length is the NULL sentinel.
|
|
6
|
+
*/
|
|
7
|
+
export declare class BufferReader extends FlexyBufferReader {
|
|
11
8
|
readCString(encoding?: BufferEncoding): string;
|
|
12
9
|
readLString(len: number, encoding?: BufferEncoding): string | null;
|
|
13
|
-
readBuffer(len?: number): Buffer;
|
|
14
|
-
private _checkReadable;
|
|
15
10
|
}
|
|
@@ -1,68 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
return this.buffer.length;
|
|
9
|
-
}
|
|
10
|
-
readUInt8() {
|
|
11
|
-
this._checkReadable(1);
|
|
12
|
-
const v = this.buffer.readUInt8(this.offset);
|
|
13
|
-
this.offset++;
|
|
14
|
-
return v;
|
|
15
|
-
}
|
|
16
|
-
readUInt16BE() {
|
|
17
|
-
this._checkReadable(2);
|
|
18
|
-
const v = this.buffer.readUInt16BE(this.offset);
|
|
19
|
-
this.offset += 2;
|
|
20
|
-
return v;
|
|
21
|
-
}
|
|
22
|
-
readInt16BE() {
|
|
23
|
-
this._checkReadable(2);
|
|
24
|
-
const v = this.buffer.readInt16BE(this.offset);
|
|
25
|
-
this.offset += 2;
|
|
26
|
-
return v;
|
|
27
|
-
}
|
|
28
|
-
readUInt32BE() {
|
|
29
|
-
this._checkReadable(4);
|
|
30
|
-
const v = this.buffer.readUInt32BE(this.offset);
|
|
31
|
-
this.offset += 4;
|
|
32
|
-
return v;
|
|
33
|
-
}
|
|
34
|
-
readInt32BE() {
|
|
35
|
-
this._checkReadable(4);
|
|
36
|
-
const v = this.buffer.readInt32BE(this.offset);
|
|
37
|
-
this.offset += 4;
|
|
38
|
-
return v;
|
|
39
|
-
}
|
|
1
|
+
import { BufferReader as FlexyBufferReader } from 'flexy-buffer';
|
|
2
|
+
/**
|
|
3
|
+
* Adds the PostgreSQL wire format's two string encodings on top of
|
|
4
|
+
* flexy-buffer's `BufferReader`: a NUL-terminated C string, and a
|
|
5
|
+
* length-prefixed string where a negative length is the NULL sentinel.
|
|
6
|
+
*/
|
|
7
|
+
export class BufferReader extends FlexyBufferReader {
|
|
40
8
|
readCString(encoding) {
|
|
41
|
-
const idx = this.buffer.indexOf(0, this.
|
|
9
|
+
const idx = this.buffer.indexOf(0, this.position);
|
|
42
10
|
if (idx === -1)
|
|
43
11
|
throw new Error('Eof in buffer detected (readCString)');
|
|
44
|
-
const v = this.buffer.toString(encoding, this.
|
|
45
|
-
this.
|
|
12
|
+
const v = this.buffer.toString(encoding, this.position, idx);
|
|
13
|
+
this.position = idx + 1;
|
|
46
14
|
return v;
|
|
47
15
|
}
|
|
48
16
|
readLString(len, encoding) {
|
|
49
17
|
if (len < 0)
|
|
50
18
|
return null;
|
|
51
|
-
this.
|
|
52
|
-
const v = this.buffer.toString(encoding, this.offset, this.offset + len);
|
|
53
|
-
this.offset += len;
|
|
54
|
-
return v;
|
|
55
|
-
}
|
|
56
|
-
readBuffer(len) {
|
|
57
|
-
if (len)
|
|
58
|
-
this._checkReadable(len);
|
|
59
|
-
const end = len !== undefined ? this.offset + len : this.length;
|
|
60
|
-
const buf = this.buffer.subarray(this.offset, end);
|
|
61
|
-
this.offset = end;
|
|
62
|
-
return buf;
|
|
63
|
-
}
|
|
64
|
-
_checkReadable(size) {
|
|
65
|
-
if (this.offset + size - 1 >= this.length)
|
|
66
|
-
throw new Error('Eof in buffer detected');
|
|
19
|
+
return this.readString(len, encoding);
|
|
67
20
|
}
|
|
68
21
|
}
|
|
@@ -1,5 +1,21 @@
|
|
|
1
|
+
import type { BatchCommandResult } from '../interfaces/batch-result.js';
|
|
1
2
|
import { Protocol } from './protocol.js';
|
|
2
3
|
export declare class DatabaseError extends Error {
|
|
4
|
+
/**
|
|
5
|
+
* Which entry of a multi-statement submission the server rejected -
|
|
6
|
+
* PreparedStatement.executeBatch()'s parameter sets, or the statements
|
|
7
|
+
* given to Connection.pipeline(). Entries after this index never ran:
|
|
8
|
+
* PostgreSQL discards everything between an error and the single Sync
|
|
9
|
+
* that closes such a submission.
|
|
10
|
+
*/
|
|
11
|
+
failedIndex?: number;
|
|
12
|
+
/**
|
|
13
|
+
* The sets that had already completed when the batch failed, in
|
|
14
|
+
* submission order - only set by PreparedStatement.executeBatch(). They
|
|
15
|
+
* did run, but the batch shares one implicit transaction, so unless an
|
|
16
|
+
* explicit transaction was already open they are rolled back with it.
|
|
17
|
+
*/
|
|
18
|
+
batchResults?: BatchCommandResult[];
|
|
3
19
|
severity?: string;
|
|
4
20
|
code?: string;
|
|
5
21
|
detail?: string;
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
import { Protocol } from './protocol.js';
|
|
2
2
|
export class DatabaseError extends Error {
|
|
3
|
+
/**
|
|
4
|
+
* Which entry of a multi-statement submission the server rejected -
|
|
5
|
+
* PreparedStatement.executeBatch()'s parameter sets, or the statements
|
|
6
|
+
* given to Connection.pipeline(). Entries after this index never ran:
|
|
7
|
+
* PostgreSQL discards everything between an error and the single Sync
|
|
8
|
+
* that closes such a submission.
|
|
9
|
+
*/
|
|
10
|
+
failedIndex;
|
|
11
|
+
/**
|
|
12
|
+
* The sets that had already completed when the batch failed, in
|
|
13
|
+
* submission order - only set by PreparedStatement.executeBatch(). They
|
|
14
|
+
* did run, but the batch shares one implicit transaction, so unless an
|
|
15
|
+
* explicit transaction was already open they are rolled back with it.
|
|
16
|
+
*/
|
|
17
|
+
batchResults;
|
|
3
18
|
severity;
|
|
4
19
|
code;
|
|
5
20
|
detail;
|