postgrejs 3.3.0 → 3.5.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 (40) hide show
  1. package/CHANGELOG.md +55 -1
  2. package/README.md +68 -7
  3. package/connection/connection.d.ts +134 -0
  4. package/connection/connection.js +213 -2
  5. package/connection/cursor.d.ts +8 -0
  6. package/connection/cursor.js +17 -0
  7. package/connection/intl-connection.d.ts +118 -3
  8. package/connection/intl-connection.js +615 -31
  9. package/connection/pool.d.ts +16 -0
  10. package/connection/pool.js +24 -0
  11. package/connection/prepared-statement.d.ts +64 -1
  12. package/connection/prepared-statement.js +95 -5
  13. package/data-types/float4-type.js +2 -1
  14. package/data-types/float8-type.js +2 -1
  15. package/data-types/int2-type.js +2 -1
  16. package/data-types/int4-type.js +2 -1
  17. package/data-types/int8-type.js +2 -1
  18. package/data-types/numeric-type.js +7 -0
  19. package/data-types/oid-type.js +2 -1
  20. package/index.d.ts +3 -0
  21. package/index.js +3 -0
  22. package/interfaces/batch-result.d.ts +42 -0
  23. package/interfaces/batch-result.js +1 -0
  24. package/interfaces/copy-from-rows-options.d.ts +58 -0
  25. package/interfaces/copy-from-rows-options.js +1 -0
  26. package/interfaces/database-connection-params.d.ts +25 -0
  27. package/interfaces/pipeline-request.d.ts +16 -0
  28. package/interfaces/pipeline-request.js +1 -0
  29. package/interfaces/query-options.d.ts +6 -0
  30. package/package.json +5 -2
  31. package/protocol/database-error.d.ts +16 -0
  32. package/protocol/database-error.js +15 -0
  33. package/protocol/pg-socket.d.ts +76 -0
  34. package/protocol/pg-socket.js +130 -12
  35. package/util/assert-integer.d.ts +43 -0
  36. package/util/assert-integer.js +58 -0
  37. package/util/copy-from-rows.d.ts +56 -0
  38. package/util/copy-from-rows.js +95 -0
  39. package/util/encode-copy-binary.d.ts +48 -0
  40. package/util/encode-copy-binary.js +112 -0
@@ -0,0 +1,112 @@
1
+ import { encodeBinaryArray } from './encode-binaryarray.js';
2
+ /**
3
+ * `PGCOPY\n\377\r\n\0` followed by two int32 words: a flags field and the
4
+ * length of a header extension area. Bit 16 of the flags marks a stream
5
+ * that carries an OID per row - an obsolete variant PostgreSQL still reads
6
+ * but nothing should write - so both words are zero here.
7
+ */
8
+ export const COPY_BINARY_HEADER = Buffer.from([
9
+ 0x50, 0x47, 0x43, 0x4f, 0x50, 0x59, 0x0a, 0xff, 0x0d, 0x0a, 0x00, 0, 0, 0, 0,
10
+ 0, 0, 0, 0,
11
+ ]);
12
+ /** A field count of -1 where a row would start, ending the stream. */
13
+ export const COPY_BINARY_TRAILER = Buffer.from([0xff, 0xff]);
14
+ /**
15
+ * Appends one row to `io` in PostgreSQL's binary COPY format: an int16
16
+ * field count, then per field an int32 byte length followed by that many
17
+ * bytes, with -1 standing in for NULL.
18
+ *
19
+ * Each value is written by its own type's `encodeBinary`, which is the same
20
+ * function a binary query parameter goes through (see Frontend's Bind) -
21
+ * both are the type's `send` representation, so there is one encoder per
22
+ * type rather than a COPY-specific set.
23
+ *
24
+ * Binary COPY performs no conversion on the server: the bytes have to be
25
+ * exactly what the destination column's type expects. `dataTypeIds` must
26
+ * therefore be the column's own OIDs, which is why the caller obtains them
27
+ * from the server rather than inferring them from the JavaScript values.
28
+ *
29
+ * @param rowIndex Only used to say which row failed, since a value that
30
+ * cannot be encoded otherwise surfaces from the server as an opaque
31
+ * "incorrect binary data format" naming neither row nor column.
32
+ * @returns Whether the row was written - false only under `'skip'`, where
33
+ * the partial row has already been unwound.
34
+ */
35
+ export function encodeCopyBinaryRow(io, values, dataTypeIds, columnNames, typeMap, options, rowIndex, onInvalidValue = 'throw',
36
+ /** Incremented per value replaced under `'null'`; counted here rather
37
+ * than inferred by the caller, which cannot see inside a written row. */
38
+ stats) {
39
+ const rowStart = io.size;
40
+ const l = dataTypeIds.length;
41
+ io.writeInt16BE(l);
42
+ let i;
43
+ let v;
44
+ for (i = 0; i < l; i++) {
45
+ v = values[i];
46
+ if (v === null || v === undefined) {
47
+ io.writeInt32BE(-1);
48
+ continue;
49
+ }
50
+ const dt = typeMap.get(dataTypeIds[i]);
51
+ /* c8 ignore next 5 - unreachable: assertCopyBinaryEncodable() rejects
52
+ every column whose type has no encodeBinary before any row is
53
+ encoded, so this is a guard against a type map mutated mid-copy. */
54
+ if (!dt?.encodeBinary) {
55
+ throw new Error(`Column "${columnNames[i]}" has no binary encoder (type OID ${dataTypeIds[i]})`);
56
+ }
57
+ if (dt.encodeAsNull?.(v, options)) {
58
+ io.writeInt32BE(-1);
59
+ continue;
60
+ }
61
+ io.writeInt32BE(0); // placeholder, backfilled below
62
+ const dataOffset = io.position;
63
+ try {
64
+ if (dt.elementsOID) {
65
+ encodeBinaryArray(io, Array.isArray(v) ? v : [v], dt.elementsOID, options, dt.encodeBinary, dt.encodeCalculateDim);
66
+ }
67
+ else {
68
+ dt.encodeBinary(io, v, options);
69
+ }
70
+ }
71
+ catch (e) {
72
+ if (onInvalidValue === 'skip') {
73
+ // Unwind the partial row so the stream never carries half of it.
74
+ io.setSize(rowStart);
75
+ io.position = rowStart;
76
+ return false;
77
+ }
78
+ if (onInvalidValue === 'null') {
79
+ io.setSize(dataOffset);
80
+ io.position = dataOffset - 4;
81
+ io.writeInt32BE(-1);
82
+ if (stats)
83
+ stats.nulled++;
84
+ continue;
85
+ }
86
+ throw new Error(`Cannot encode row ${rowIndex}, column "${columnNames[i]}" (${dt.name}): ${e.message}`, { cause: e });
87
+ }
88
+ io.buffer.writeInt32BE(io.size - dataOffset, dataOffset - 4);
89
+ }
90
+ return true;
91
+ }
92
+ /**
93
+ * Fails before a single byte goes out when any column's type cannot be
94
+ * written in binary. Worth doing up front: once the server has answered
95
+ * CopyInResponse it is waiting for a complete stream, so discovering an
96
+ * unencodable column at row 900,000 means aborting a copy that was already
97
+ * most of the way done.
98
+ */
99
+ export function assertCopyBinaryEncodable(dataTypeIds, columnNames, typeMap) {
100
+ const missing = [];
101
+ const l = dataTypeIds.length;
102
+ let i;
103
+ for (i = 0; i < l; i++) {
104
+ const dt = typeMap.get(dataTypeIds[i]);
105
+ if (!dt?.encodeBinary)
106
+ missing.push(`"${columnNames[i]}" (OID ${dataTypeIds[i]})`);
107
+ }
108
+ if (missing.length) {
109
+ throw new Error(`Binary COPY cannot encode ${missing.join(', ')} - no binary encoder is ` +
110
+ `registered for that type. Use copyFrom() with a text format instead.`);
111
+ }
112
+ }