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.
Files changed (80) hide show
  1. package/CHANGELOG.md +79 -1
  2. package/README.md +79 -13
  3. package/connection/connection.d.ts +97 -0
  4. package/connection/connection.js +141 -2
  5. package/connection/cursor.d.ts +2 -1
  6. package/connection/cursor.js +6 -6
  7. package/connection/intl-connection.d.ts +113 -3
  8. package/connection/intl-connection.js +530 -45
  9. package/connection/prepared-statement.d.ts +64 -1
  10. package/connection/prepared-statement.js +97 -6
  11. package/data-types/bool-type.js +0 -1
  12. package/data-types/box-type.js +0 -1
  13. package/data-types/bytea-type.js +5 -3
  14. package/data-types/char-type.js +2 -2
  15. package/data-types/circle-type.js +0 -1
  16. package/data-types/date-type.js +1 -2
  17. package/data-types/float4-type.js +4 -5
  18. package/data-types/float8-type.js +4 -6
  19. package/data-types/int2-type.js +2 -2
  20. package/data-types/int2-vector-type.js +3 -2
  21. package/data-types/int4-type.js +2 -2
  22. package/data-types/int8-type.js +2 -2
  23. package/data-types/json-type.js +2 -2
  24. package/data-types/jsonb-type.js +6 -5
  25. package/data-types/lseg-type.js +0 -1
  26. package/data-types/numeric-type.js +9 -4
  27. package/data-types/oid-type.js +2 -2
  28. package/data-types/oid-vector-type.js +3 -2
  29. package/data-types/point-type.js +0 -1
  30. package/data-types/time-type.js +1 -2
  31. package/data-types/timestamp-type.js +13 -3
  32. package/data-types/timestamptz-type.js +27 -10
  33. package/data-types/uuid-type.js +1 -2
  34. package/data-types/varchar-type.js +2 -2
  35. package/index.d.ts +4 -0
  36. package/index.js +4 -0
  37. package/interfaces/batch-result.d.ts +42 -0
  38. package/interfaces/batch-result.js +1 -0
  39. package/interfaces/command-result.d.ts +3 -2
  40. package/interfaces/copy-from-rows-options.d.ts +58 -0
  41. package/interfaces/copy-from-rows-options.js +1 -0
  42. package/interfaces/data-type.d.ts +0 -1
  43. package/interfaces/database-connection-params.d.ts +25 -0
  44. package/interfaces/pipeline-request.d.ts +16 -0
  45. package/interfaces/pipeline-request.js +1 -0
  46. package/interfaces/query-options.d.ts +18 -0
  47. package/interfaces/script-execute-options.d.ts +12 -0
  48. package/package.json +18 -3
  49. package/protocol/backend.js +6 -6
  50. package/protocol/buffer-reader.d.ts +7 -12
  51. package/protocol/buffer-reader.js +11 -58
  52. package/protocol/database-error.d.ts +16 -0
  53. package/protocol/database-error.js +15 -0
  54. package/protocol/frontend.js +86 -96
  55. package/protocol/pg-socket.d.ts +82 -33
  56. package/protocol/pg-socket.js +143 -86
  57. package/protocol/pgoutput.js +2 -2
  58. package/protocol/smart-buffer.d.ts +11 -29
  59. package/protocol/smart-buffer.js +19 -162
  60. package/types.d.ts +13 -1
  61. package/util/assert-integer.d.ts +43 -0
  62. package/util/assert-integer.js +58 -0
  63. package/util/bigint-methods.d.ts +0 -1
  64. package/util/bigint-methods.js +0 -22
  65. package/util/copy-from-rows.d.ts +56 -0
  66. package/util/copy-from-rows.js +95 -0
  67. package/util/decode-binaryarray.d.ts +1 -1
  68. package/util/decode-binaryarray.js +7 -7
  69. package/util/encode-binaryarray.js +6 -6
  70. package/util/encode-copy-binary.d.ts +48 -0
  71. package/util/encode-copy-binary.js +112 -0
  72. package/util/fast-parsefloat.d.ts +15 -0
  73. package/util/fast-parsefloat.js +141 -0
  74. package/util/get-parsers.js +4 -8
  75. package/util/parse-datetime.js +7 -0
  76. package/util/parse-pg-timestamp.d.ts +31 -0
  77. package/util/parse-pg-timestamp.js +199 -0
  78. package/util/parse-row.js +120 -0
  79. package/util/row-decoder.d.ts +49 -0
  80. 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
- let d = new Date((lo + hi * timeMul) / 1000 + timeShift);
47
- if (fetchAsString || !options.utcDates) {
48
- d = new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
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
- // See date-type.ts's decodeTextBuffer comment - same rationale. Note this
68
- // type's decodeText always parses first and only branches on
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) - delegating by reference preserves that as-is.
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) {
@@ -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.writeBuffer(b);
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.1.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"
@@ -124,7 +124,7 @@ function parseAuthentication(io, code, len) {
124
124
  case 5:
125
125
  return {
126
126
  kind: 'MD5Password',
127
- salt: io.readBuffer(len - 8),
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.readBuffer(len - 8),
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.readBuffer();
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.readBuffer(len - 4),
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.readBuffer(len - 6);
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.readBuffer(len) };
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
- export declare class BufferReader {
2
- buffer: Buffer;
3
- offset: number;
4
- constructor(buffer: Buffer);
5
- get length(): number;
6
- readUInt8(): number;
7
- readUInt16BE(): number;
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
- export class BufferReader {
2
- buffer;
3
- offset = 0;
4
- constructor(buffer) {
5
- this.buffer = buffer;
6
- }
7
- get length() {
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.offset);
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.offset, idx);
45
- this.offset = idx + 1;
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._checkReadable(len);
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;