postgrejs 3.6.1 → 3.7.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 (63) hide show
  1. package/CHANGELOG.md +50 -6
  2. package/README.md +9 -83
  3. package/connection/intl-connection.d.ts +5 -3
  4. package/connection/intl-connection.js +43 -15
  5. package/connection/prepared-statement.js +2 -2
  6. package/constants.d.ts +60 -0
  7. package/constants.js +119 -1
  8. package/data-type-map.js +82 -0
  9. package/data-types/bit-type.d.ts +5 -0
  10. package/data-types/bit-type.js +91 -0
  11. package/data-types/box-type.js +9 -19
  12. package/data-types/circle-type.js +6 -16
  13. package/data-types/classes/geometric.d.ts +105 -0
  14. package/data-types/classes/geometric.js +197 -0
  15. package/data-types/classes/interval.d.ts +73 -0
  16. package/data-types/classes/interval.js +181 -0
  17. package/data-types/classes/numeric.d.ts +37 -0
  18. package/data-types/classes/numeric.js +47 -0
  19. package/data-types/classes/range.d.ts +74 -0
  20. package/data-types/classes/range.js +111 -0
  21. package/data-types/classes/type-oid.d.ts +34 -0
  22. package/data-types/classes/type-oid.js +45 -0
  23. package/data-types/inet-type.d.ts +5 -0
  24. package/data-types/inet-type.js +286 -0
  25. package/data-types/interval-type.d.ts +5 -0
  26. package/data-types/interval-type.js +79 -0
  27. package/data-types/jsonpath-type.d.ts +3 -0
  28. package/data-types/jsonpath-type.js +53 -0
  29. package/data-types/line-type.d.ts +3 -0
  30. package/data-types/line-type.js +41 -0
  31. package/data-types/lseg-type.js +9 -19
  32. package/data-types/macaddr-type.d.ts +5 -0
  33. package/data-types/macaddr-type.js +86 -0
  34. package/data-types/numeric-type.js +98 -69
  35. package/data-types/path-type.d.ts +5 -0
  36. package/data-types/path-type.js +139 -0
  37. package/data-types/pg-lsn-type.d.ts +3 -0
  38. package/data-types/pg-lsn-type.js +58 -0
  39. package/data-types/point-type.js +8 -13
  40. package/data-types/range-type.d.ts +23 -0
  41. package/data-types/range-type.js +342 -0
  42. package/data-types/snapshot-type.d.ts +5 -0
  43. package/data-types/snapshot-type.js +96 -0
  44. package/data-types/tid-type.d.ts +3 -0
  45. package/data-types/tid-type.js +50 -0
  46. package/data-types/timetz-type.d.ts +3 -0
  47. package/data-types/timetz-type.js +184 -0
  48. package/data-types/tsvector-type.d.ts +5 -0
  49. package/data-types/tsvector-type.js +216 -0
  50. package/data-types/xid-type.d.ts +7 -0
  51. package/data-types/xid-type.js +110 -0
  52. package/index.d.ts +4 -0
  53. package/index.js +4 -0
  54. package/interfaces/data-mapping-options.d.ts +26 -0
  55. package/interfaces/data-type.d.ts +8 -9
  56. package/package.json +1 -1
  57. package/protocol/connection-lost-error.d.ts +5 -3
  58. package/protocol/connection-lost-error.js +5 -3
  59. package/protocol/pg-socket.js +16 -2
  60. package/util/parse-array.js +17 -2
  61. package/util/resolve-column-formats.d.ts +2 -1
  62. package/util/resolve-column-formats.js +35 -8
  63. package/util/stringify-for-sql.js +37 -1
package/CHANGELOG.md CHANGED
@@ -1,6 +1,47 @@
1
1
  ## Changelog
2
2
 
3
- ### [v3.6.1](https://github.com/panates/postgrejs/compare/v3.6.0...v3.6.1) -
3
+ ### [v3.7.0](https://github.com/panates/postgrejs/compare/v3.6.1...v3.7.0) - 20 September 2026
4
+
5
+ #### Breaking Changes :warning:
6
+
7
+ - feat!: decode a numeric that a double cannot hold into a Numeric @Eray Hanoğlu
8
+ - build: let the changelog template see a breaking change @Eray Hanoğlu
9
+
10
+ #### 🚀 New Features
11
+
12
+ - feat: decode the network types @Eray Hanoğlu
13
+ - feat: decode line, path and polygon @Eray Hanoğlu
14
+ - feat: decode the system columns, and name the types that cannot be @Eray Hanoğlu
15
+ - feat: decode the range and multirange types @Eray Hanoğlu
16
+ - feat: decode the geometric types into classes of their own @Eray Hanoğlu
17
+ - feat: decode tsvector and tsquery @Eray Hanoğlu
18
+ - feat: decode interval @Eray Hanoğlu
19
+ - feat: decode bit, varbit and jsonpath @Eray Hanoğlu
20
+ - feat: decode timetz @Eray Hanoğlu
21
+ - feat: decode refcursor, pg_node_tree and the snapshot types @Eray Hanoğlu
22
+ - feat: add unknownTypesAsString @Eray Hanoğlu
23
+ - feat: let a decoded value carry the type it came from @Eray Hanoğlu
24
+ - feat: reject the in-flight query with ConnectionLostError too @Eray Hanoğlu
25
+
26
+ #### 🪲 Fixes
27
+
28
+ - fix: write an object as its own SQL literal, not as json @Eray Hanoğlu
29
+ - fix: complete the type OID table, and check it against the catalog @Eray Hanoğlu
30
+ - fix: recover when a recreated type invalidates a cached statement @Eray Hanoğlu
31
+ - fix: keep a quoted empty element when parsing an array literal @Eray Hanoğlu
32
+
33
+ #### 📖 Documentation Changes
34
+
35
+ - docs: cut the Features list back down @Eray Hanoğlu
36
+ - docs: drop the Features section @Eray Hanoğlu
37
+ - docs: bring the data type counts up to what is registered @Eray Hanoğlu
38
+ - docs: give the documentation link its own heading @Eray Hanoğlu
39
+
40
+ #### ⚡️ Performance Improvments
41
+
42
+ - perf: build a numeric's digits without a concatenation per digit @Eray Hanoğlu
43
+
44
+ ### [v3.6.1](https://github.com/panates/postgrejs/compare/v3.6.0...v3.6.1) - 20 September 2026
4
45
 
5
46
  #### 🚀 New Features
6
47
 
@@ -16,6 +57,10 @@
16
57
 
17
58
  ### [v3.6.0](https://github.com/panates/postgrejs/compare/v3.5.0...v3.6.0) - 20 September 2026
18
59
 
60
+ #### Breaking Changes :warning:
61
+
62
+ - feat!: fetch every row by default instead of the first 100 @Eray Hanoğlu
63
+
19
64
  #### 🚀 New Features
20
65
 
21
66
  - feat: make fetchAsString request text from the server @Eray Hanoğlu
@@ -35,10 +80,6 @@
35
80
 
36
81
  - docs: record what 3.6 changes for existing code @Eray Hanoğlu
37
82
 
38
- #### 💬 General Changes
39
-
40
- - feat!: fetch every row by default instead of the first 100 @Eray Hanoğlu
41
-
42
83
  ### [v3.5.0](https://github.com/panates/postgrejs/compare/v3.4.0...v3.5.0) - 16 September 2026
43
84
 
44
85
  #### 🚀 New Features
@@ -95,6 +136,10 @@
95
136
 
96
137
  ### [v3.3.0](https://github.com/panates/postgrejs/compare/v3.2.0...v3.3.0) - 14 September 2026
97
138
 
139
+ #### Breaking Changes :warning:
140
+
141
+ - feat!: give decodeBinary the value's length, not a slice of it @Eray Hanoğlu
142
+
98
143
  #### 🚀 New Features
99
144
 
100
145
  - feat: add first-class Bun support with dedicated benchmark suite @Eray Hanoğlu
@@ -123,7 +168,6 @@
123
168
  #### 💬 General Changes
124
169
 
125
170
  - bench: report near-ties as ties instead of ranking them @Eray Hanoğlu
126
- - feat!: give decodeBinary the value's length, not a slice of it @Eray Hanoğlu
127
171
  - bench: stop measuring type-declaration policy in the Extended Query scenarios @Eray Hanoğlu
128
172
  - bench: stop one stalled repeat from making every result a tie @Eray Hanoğlu
129
173
  - bench: document why concurrent Simple Query varies its literal @Eray Hanoğlu
package/README.md CHANGED
@@ -56,8 +56,7 @@ $ npm install postgrejs --save
56
56
 
57
57
  ## Documentation
58
58
 
59
- Please read :small_orange_diamond: [DOCUMENTATION](https://www.postgrejs.com/) :small_orange_diamond: for detailed
60
- usage.
59
+ ### Please read 🔸 [DOCUMENTATION](https://www.postgrejs.com/) 🔸 for detailed usage
61
60
 
62
61
  Upgrading from 3.5? See [doc/MIGRATION-v3.5-to-v3.6.md](doc/MIGRATION-v3.5-to-v3.6.md) - `query()` no longer stops at
63
62
  100 rows, and `fetchAsString` now returns the server's own text.
@@ -71,82 +70,6 @@ Upgrading from 3.5? See [doc/MIGRATION-v3.5-to-v3.6.md](doc/MIGRATION-v3.5-to-v3
71
70
  - **Rigorously tested:** A test suite covering the wire protocol, every data type, and connection-handling edge case,
72
71
  run on every push against PostgreSQL 12 through 18.
73
72
 
74
- ## Features
75
-
76
- - **Connection Management:** Supports both single connection and advanced pooling, providing scalability and efficient
77
- resource management. A connection that dies rather than being closed says so: `'close'` carries the reason, and a
78
- pooled one is reported on the pool's `'destroy'` and `'error'` events - so an admin kill or a failover is
79
- distinguishable from an ordinary eviction, including when the connection was sitting idle with no query to reject.
80
- The reason is a `ConnectionLostError` carrying the backend's `processID`, and `code` `'08006'` so branching on it
81
- needs no `instanceof`.
82
- - **Binary Wire Protocol:** Implements the full binary wire protocol for all PostgreSQL data types, ensuring robust and
83
- efficient data handling.
84
- - **Prepared Statements:** Named prepared statements for optimized query execution, and a per-connection cache that
85
- reuses one automatically for SQL the connection has run before - a repeated query costs `Bind`/`Execute` instead of
86
- parsing again, worth 3.2x on fifty concurrent calls and 2.9x again on a query inside an open transaction. On by
87
- default, `prepare: false` to opt out.
88
- - **Statement-Level Rollback:** Inside a transaction each statement runs under a savepoint of its own, so a failed
89
- statement leaves the transaction usable instead of aborting the whole block. The `SAVEPOINT`/`RELEASE` pair travels
90
- in the statement's own round trip rather than costing one each - 36µs for the pair, against 507µs sent separately.
91
- `rollbackOnError: false` to opt out.
92
- - **Complete Results:** `query()` returns every row the statement produced. A `fetchCount` limit is a limit rather
93
- than a silent cap: the result carries `suspended: true` when the server stopped at it, so a prefix can never be
94
- mistaken for the whole answer. `0` means unlimited, as it does in the protocol.
95
- - **Cursors:** Features fast double-link cache cursors for efficient data retrieval, iterable with `for await` a row
96
- at a time and closed when the loop ends - by exhaustion, a `break`, or a throw. A cursor reads through a portal, and
97
- a portal lives as long as the transaction that created it - `Pool.query()` keeps its connection out of the pool
98
- until the cursor closes, and on a bare `Connection` open the cursor inside a transaction if anything else will run
99
- on that connection meanwhile.
100
- - **Scoped Transactions:** `transaction(fn)` commits when the callback returns and rolls back when it throws, on a
101
- connection or straight from the pool. A call made while a transaction is already open takes a savepoint rather than
102
- a second `BEGIN`, so a nested scope that fails rolls back its own work and leaves the outer transaction standing.
103
- - **Batch Execution:** `executeBatch()` runs one prepared statement over many parameter sets under a single `Sync`,
104
- reporting each set's row count - 1000 updates in 20ms where the same calls pipelined individually take 188ms.
105
- - **Notifications:** High-level implementation for PostgreSQL notifications (LISTEN/NOTIFY), enabling real-time data
106
- updates. Channel names are quoted rather than pattern-matched, so any name PostgreSQL accepts works.
107
- - **Extensibility:** Extensible data-types and type mapping to accommodate custom requirements. A type can set
108
- `inferrable: false` to stay out of parameter type inference while still decoding its own columns.
109
- - **Parameter Binding:** Bind parameters with OID mappings for precise and efficient query execution.
110
- - **Array Handling:** Supports multidimensional arrays with fast binary encoding/decoding.
111
- - **Performance Optimization:** Low memory utilization and boosted performance through the use of shared buffers.
112
- - **Authorization:** Supports various password algorithms including Clear text, MD5, and SASL, ensuring secure
113
- authentication.
114
- - **Bulk Import/Export:** `COPY TO STDOUT` and `COPY FROM STDIN` as Node streams, with backpressure in both directions,
115
- plus `copyFromRows()`, which encodes rows straight into binary `COPY` - around 4x faster than the CSV equivalent and
116
- no text escaping to get wrong. Takes arrays or objects from anything iterable, so a file larger than memory streams in.
117
- - **Query Pipelining:** Pooled queries can share connections so a burst is not capped by pool size - opt-in per call.
118
- `pipeline()` goes further for a known set of statements: several different ones travel under a single `Sync`, so they
119
- cost one round trip instead of one each and commit or roll back together - around 2x faster than the same calls
120
- through `Promise.all()`, which is already pipelined. Statements the connection has run before bind to their cached
121
- prepared names, so a repeated set sends no `Parse` at all - worth 2.5x on twenty statements.
122
- - **Dynamic SQL:** A `sql` tag builds statements from composable fragments - values become parameters, names are quoted,
123
- and `sql.values()`/`sql.set()` write INSERT and UPDATE clauses from objects.
124
- - **Multiple Hosts:** A connection can list several servers and pick one by role
125
- (`target_session_attrs`), so a cluster that has failed over is found on the next connect.
126
- - **Large Objects:** File-like access to binary data stored outside the row - seek, partial reads, streams - for
127
- values past what a `bytea` column can hold.
128
- - **Logical Replication:** `LogicalReplication` streams committed row changes as an async iterable, decoding
129
- `pgoutput` itself, with client-side filtering and positions confirmed as you consume.
130
- - **Channel Binding:** SCRAM authentication binds itself to the TLS channel when the server offers it, the way libpq
131
- does by default, so a relayed login is detected even where the certificate is not verified.
132
- - **Two-phase commit:** `prepareTransaction()` leaves a transaction waiting under a name for `commitPrepared()`/
133
- `rollbackPrepared()`, from any connection.
134
- - **Cancellation:** Any call takes an `AbortSignal`, which also gives per-query timeouts via `AbortSignal.timeout()`.
135
- - **Flexible Data Retrieval:** Can return both array and object rows to suit different data processing needs.
136
- - **Values as Text:** `fetchAsString: [DataTypeOIDs.int8]` asks the server for those columns in its own text format
137
- and hands the bytes back unparsed - so `count(*)` arrives as `'3'`, one consistent type where a decoded `int8` is a
138
- `number` or a `BigInt` depending on magnitude. Any OID, arrays included. The string is PostgreSQL's own rendering
139
- rather than one reconstructed from the binary value, so it cannot drift from what the server would print.
140
- - **Resource Management:** Auto disposal of resources with the "using" syntax
141
- ([TC39 Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management)), ensuring
142
- efficient resource cleanup.
143
- - **Long Cancel Key:** Opt in to protocol 3.2 (PostgreSQL 18+) with `longCancelKey`, so a `cancel()` in progress can't
144
- be forged by an attacker guessing a short secret key.
145
- - **Legacy Function Call Protocol:** `callFunction()` calls a function by OID directly over the wire, bypassing SQL
146
- entirely - kept for protocol completeness even though `SELECT func(...)` covers the same ground.
147
- - **Graceful Protocol Renegotiation:** A server that doesn't recognize a requested protocol version or startup option
148
- reports back instead of erroring out, surfaced on `Connection.protocolNegotiation`.
149
-
150
73
  ## Feature Comparison
151
74
 
152
75
  How PostgreJS compares to [`pg`](https://github.com/brianc/node-postgres) (node-postgres) and
@@ -204,10 +127,10 @@ in · 🟡 partial or needs a separate package · ❌ not supported.
204
127
  | Multiple hosts | ✅ | ❌ | ✅ |
205
128
  | LISTEN/NOTIFY | ✅ | 🟡 <sup>15</sup> | ✅ |
206
129
  | ***Data types*** | | | |
207
- | Text encoders | 56 | generic <sup>16</sup> | 14 |
208
- | Text decoders | 56 | 44 | 12 <sup>17</sup> |
209
- | Binary encoders | 56 | ❌ | ❌ |
210
- | Binary decoders | 56 | 16 | ❌ |
130
+ | Text encoders | 125 | generic <sup>16</sup> | 14 |
131
+ | Text decoders | 125 | 44 | 12 <sup>17</sup> |
132
+ | Binary encoders | 121 <sup>27</sup> | ❌ | ❌ |
133
+ | Binary decoders | 125 | 16 | ❌ |
211
134
  | Multidimensional arrays | ✅ binary | 🟡 text <sup>18</sup> | 🟡 text |
212
135
  | ***Security*** | | | |
213
136
  | SSL/TLS | ✅ | ✅ | ✅ |
@@ -294,7 +217,10 @@ in · 🟡 partial or needs a separate package · ❌ not supported.
294
217
  a savepoint, so nesting needs nothing from the caller. postgres.js has `sql.begin(fn)` (`src/index.js`), where a
295
218
  nested scope is opened explicitly with `sql.savepoint(fn)` instead. pg has no such helper in `lib/` - `BEGIN` and
296
219
  `COMMIT` are statements the caller sends, and getting a transaction onto one connection is the caller's problem too.
297
-
220
+ - <sup>27</sup> Every registered type but `tsvector` and `tsquery`, which have none deliberately: the server's own
221
+ input parser is what sorts and deduplicates a vector and what defines a query's grammar, so encoding either here
222
+ would make the same text mean one thing written as a literal and another bound as a parameter. They are sent as
223
+ text instead, which is exact.
298
224
 
299
225
  ## Benchmarks
300
226
 
@@ -194,9 +194,11 @@ export declare class IntlConnection extends SafeEventEmitter {
194
194
  *
195
195
  * A cached statement can be invalidated under us - `alter table` between
196
196
  * two calls makes PostgreSQL answer 0A000, "cached plan must not change
197
- * result type". That is caught here: the entry is dropped and the query
198
- * runs again unprepared, so a migration against a live connection
199
- * recovers instead of failing every call from then on.
197
+ * result type", and a dropped and recreated type makes it answer XX000,
198
+ * "cache lookup failed for type". Both are caught here (see
199
+ * isStaleCachedPlan): the entry is dropped and the query runs again
200
+ * unprepared, so a migration against a live connection recovers instead
201
+ * of failing every call from then on.
200
202
  */
201
203
  queryCached(sql: string, paramTypes: Maybe<Maybe<OID>[]>, params: Maybe<Maybe<any>[]>, options: QueryOptions): Promise<QueryResult>;
202
204
  /**
@@ -28,6 +28,30 @@ function columnFormatsEqual(a, b) {
28
28
  return false;
29
29
  return true;
30
30
  }
31
+ /**
32
+ * Whether the server is saying that a statement this connection had under
33
+ * a name can no longer be executed as it stands, so the cache entry is
34
+ * stale and the query is worth running again unprepared.
35
+ *
36
+ * Two SQLSTATEs say it. `0A000` is the documented one - "cached plan must
37
+ * not change result type", after an `alter table`. `XX000` is what a
38
+ * dropped and recreated *type* produces ("cache lookup failed for type
39
+ * <oid>"): it is the server's catch-all internal_error rather than
40
+ * something specific, but it is rare enough in ordinary operation that
41
+ * retrying it costs nothing, and the alternative - matching the English
42
+ * message - breaks under a different `lc_messages` or a server version
43
+ * that rewords it.
44
+ *
45
+ * Deliberately narrow. Dropping the entry on *any* failure would also
46
+ * self-heal, but it would retire a perfectly good prepared statement
47
+ * every time an ordinary error came back - a unique violation on a hot
48
+ * upsert would keep costing the statement its name - and re-running a
49
+ * statement that failed for its own reasons buys nothing.
50
+ */
51
+ function isStaleCachedPlan(e) {
52
+ const code = e?.code;
53
+ return code === '0A000' || code === 'XX000';
54
+ }
31
55
  /**
32
56
  * Whether a command tag's row count describes rows the statement changed,
33
57
  * rather than rows it returned or moved. SELECT, FETCH, MOVE and COPY all
@@ -617,9 +641,11 @@ export class IntlConnection extends SafeEventEmitter {
617
641
  *
618
642
  * A cached statement can be invalidated under us - `alter table` between
619
643
  * two calls makes PostgreSQL answer 0A000, "cached plan must not change
620
- * result type". That is caught here: the entry is dropped and the query
621
- * runs again unprepared, so a migration against a live connection
622
- * recovers instead of failing every call from then on.
644
+ * result type", and a dropped and recreated type makes it answer XX000,
645
+ * "cache lookup failed for type". Both are caught here (see
646
+ * isStaleCachedPlan): the entry is dropped and the query runs again
647
+ * unprepared, so a migration against a live connection recovers instead
648
+ * of failing every call from then on.
623
649
  */
624
650
  async queryCached(sql, paramTypes, params, options) {
625
651
  const savepoint = this._inlineSavepointFor(sql, options);
@@ -663,7 +689,7 @@ export class IntlConnection extends SafeEventEmitter {
663
689
  return await this.executeReused(cached.name, cached.fields, paramTypes, params, options, savepoint);
664
690
  }
665
691
  catch (e) {
666
- if (e?.code !== '0A000')
692
+ if (!isStaleCachedPlan(e))
667
693
  throw e;
668
694
  this._preparedCache.delete(key);
669
695
  // ROLLBACK TO leaves the savepoint itself in place, so the retry
@@ -683,7 +709,10 @@ export class IntlConnection extends SafeEventEmitter {
683
709
  // Parse+Describe round trip per connection instead of leaving every
684
710
  // call until the statement earns a name asking for the whole row as
685
711
  // text (what queryOnce() falls back to).
686
- if (!options.fetchAsString?.length && !this._earnsAName(key))
712
+ // unknownTypesAsString needs the columns known before the Bind for
713
+ // the same reason fetchAsString does, so it earns a name the same way.
714
+ const needsFields = !!options.fetchAsString?.length || !!options.unknownTypesAsString;
715
+ if (!needsFields && !this._earnsAName(key))
687
716
  return this.queryOnce(sql, paramTypes, params, options, savepoint);
688
717
  const name = 'C_' + ++this._preparedCounter;
689
718
  // A Parse that fails caches nothing and reports itself; the statement
@@ -771,7 +800,7 @@ export class IntlConnection extends SafeEventEmitter {
771
800
  // _queryCached() prepares a fetchAsString query on first sight
772
801
  // precisely so it can send per-column codes from the second call on
773
802
  // (from the first, for every connection that has seen the SQL).
774
- const columnFormat = options.fetchAsString?.length
803
+ const columnFormat = options.fetchAsString?.length || options.unknownTypesAsString
775
804
  ? DataFormat.text
776
805
  : options.columnFormat != null
777
806
  ? options.columnFormat
@@ -1029,8 +1058,8 @@ export class IntlConnection extends SafeEventEmitter {
1029
1058
  // per-column codes; the rest fall back to asking for the whole row
1030
1059
  // as text, exactly as queryOnce() does and for the same reason.
1031
1060
  plan.columnFormat = plan.fields
1032
- ? resolveColumnFormats(plan.fields, options)
1033
- : options.fetchAsString?.length
1061
+ ? resolveColumnFormats(plan.fields, options, typeMap)
1062
+ : options.fetchAsString?.length || options.unknownTypesAsString
1034
1063
  ? DataFormat.text
1035
1064
  : options.columnFormat != null
1036
1065
  ? options.columnFormat
@@ -1131,11 +1160,10 @@ export class IntlConnection extends SafeEventEmitter {
1131
1160
  }
1132
1161
  catch (e) {
1133
1162
  // A cached statement can be invalidated between two pipelines the
1134
- // same way a cached single query can (0A000, "cached plan must not
1135
- // change result type"). Drop what this pipeline reused and run it
1136
- // again unprepared - once, since the second attempt has nothing
1137
- // cached left to reuse.
1138
- if (e?.code !== '0A000' || !cachedKeys.length)
1163
+ // same way a cached single query can - see isStaleCachedPlan().
1164
+ // Drop what this pipeline reused and run it again unprepared -
1165
+ // once, since the second attempt has nothing cached left to reuse.
1166
+ if (!isStaleCachedPlan(e) || !cachedKeys.length)
1139
1167
  throw e;
1140
1168
  for (const k of cachedKeys)
1141
1169
  this._preparedCache.delete(k);
@@ -1180,7 +1208,7 @@ export class IntlConnection extends SafeEventEmitter {
1180
1208
  const rowDecoder = resolveRowDecoder(options);
1181
1209
  let parsers;
1182
1210
  let resultFields;
1183
- const columnFormat = resolveColumnFormats(cachedFields, options);
1211
+ const columnFormat = resolveColumnFormats(cachedFields, options, typeMap);
1184
1212
  if (cachedFields) {
1185
1213
  const resolved = this._resolveReusedParsers(cachedFields, typeMap, options, columnFormat);
1186
1214
  parsers = resolved.parsers;
@@ -1291,7 +1319,7 @@ export class IntlConnection extends SafeEventEmitter {
1291
1319
  // RowDescription is already in hand, so fetchAsString's OID list can
1292
1320
  // become the per-column result format codes this Bind carries, with
1293
1321
  // no extra round trip to find out what the columns are.
1294
- const columnFormat = resolveColumnFormats(cachedFields, options);
1322
+ const columnFormat = resolveColumnFormats(cachedFields, options, typeMap);
1295
1323
  if (cachedFields) {
1296
1324
  const resolved = this._resolveReusedParsers(cachedFields, typeMap, options, columnFormat);
1297
1325
  parsers = resolved.parsers;
@@ -211,9 +211,9 @@ export class PreparedStatement extends SafeEventEmitter {
211
211
  // prepare() already fetched this statement's RowDescription, so
212
212
  // fetchAsString's OID list can become per-column result format
213
213
  // codes on the Bind below with no round trip of its own.
214
- const columnFormat = resolveColumnFormats(this._fields, options);
215
- const fields = await portal.bindAndRetrieveFields(options.params, options, columnFormat);
216
214
  const typeMap = options.typeMap || GlobalTypeMap;
215
+ const columnFormat = resolveColumnFormats(this._fields, options, typeMap);
216
+ const fields = await portal.bindAndRetrieveFields(options.params, options, columnFormat);
217
217
  const parsers = getParsers(typeMap, fields, options);
218
218
  const resultFields = wrapRowDescription(typeMap, fields, columnFormat, options);
219
219
  const result = {
package/constants.d.ts CHANGED
@@ -27,6 +27,7 @@ export declare const DataTypeOIDs: {
27
27
  oidvector: number;
28
28
  json: number;
29
29
  xml: number;
30
+ pg_node_tree: number;
30
31
  point: number;
31
32
  lseg: number;
32
33
  path: number;
@@ -42,6 +43,7 @@ export declare const DataTypeOIDs: {
42
43
  money: number;
43
44
  macaddr: number;
44
45
  inet: number;
46
+ aclitem: number;
45
47
  bpchar: number;
46
48
  varchar: number;
47
49
  date: number;
@@ -70,14 +72,40 @@ export declare const DataTypeOIDs: {
70
72
  anyelement: number;
71
73
  anynonarray: number;
72
74
  uuid: number;
75
+ txid_snapshot: number;
76
+ pg_lsn: number;
77
+ pg_ndistinct: number;
78
+ pg_dependencies: number;
79
+ tsvector: number;
80
+ tsquery: number;
81
+ gtsvector: number;
82
+ regconfig: number;
83
+ regdictionary: number;
73
84
  jsonb: number;
74
85
  anyrange: number;
75
86
  int4range: number;
76
87
  numrange: number;
77
88
  tsrange: number;
89
+ tstzrange: number;
90
+ /** @deprecated Misspelling of `tstzrange`, kept so it keeps resolving. */
78
91
  rstzrange: number;
79
92
  daterange: number;
80
93
  int8range: number;
94
+ jsonpath: number;
95
+ regnamespace: number;
96
+ regrole: number;
97
+ regcollation: number;
98
+ int4multirange: number;
99
+ nummultirange: number;
100
+ tsmultirange: number;
101
+ tstzmultirange: number;
102
+ datemultirange: number;
103
+ int8multirange: number;
104
+ pg_brin_bloom_summary: number;
105
+ pg_brin_minmax_multi_summary: number;
106
+ pg_mcv_list: number;
107
+ pg_snapshot: number;
108
+ xid8: number;
81
109
  _xml: number;
82
110
  _json: number;
83
111
  _xid8: number;
@@ -110,6 +138,7 @@ export declare const DataTypeOIDs: {
110
138
  _float8: number;
111
139
  _polygon: number;
112
140
  _oid: number;
141
+ _aclitem: number;
113
142
  _macaddr: number;
114
143
  _inet: number;
115
144
  _timestamp: number;
@@ -122,7 +151,38 @@ export declare const DataTypeOIDs: {
122
151
  _timetz: number;
123
152
  _bit: number;
124
153
  _varbit: number;
154
+ _refcursor: number;
155
+ _regprocedure: number;
156
+ _regoper: number;
157
+ _regoperator: number;
158
+ _regclass: number;
159
+ _regtype: number;
160
+ _record: number;
161
+ _txid_snapshot: number;
125
162
  _uuid: number;
163
+ _pg_lsn: number;
164
+ _tsvector: number;
165
+ _gtsvector: number;
166
+ _tsquery: number;
167
+ _regconfig: number;
168
+ _regdictionary: number;
126
169
  _jsonb: number;
170
+ _int4range: number;
171
+ _numrange: number;
172
+ _tsrange: number;
173
+ _tstzrange: number;
174
+ _daterange: number;
175
+ _int8range: number;
176
+ _jsonpath: number;
177
+ _regnamespace: number;
178
+ _regrole: number;
179
+ _regcollation: number;
180
+ _pg_snapshot: number;
181
+ _int4multirange: number;
182
+ _nummultirange: number;
183
+ _tsmultirange: number;
184
+ _tstzmultirange: number;
185
+ _datemultirange: number;
186
+ _int8multirange: number;
127
187
  };
128
188
  export declare const DataTypeNames: Record<string, string>;
package/constants.js CHANGED
@@ -30,6 +30,7 @@ export const DataTypeOIDs = {
30
30
  oidvector: 30,
31
31
  json: 114,
32
32
  xml: 142,
33
+ pg_node_tree: 194,
33
34
  point: 600,
34
35
  lseg: 601,
35
36
  path: 602,
@@ -45,6 +46,7 @@ export const DataTypeOIDs = {
45
46
  money: 790,
46
47
  macaddr: 829,
47
48
  inet: 869,
49
+ aclitem: 1033,
48
50
  bpchar: 1042,
49
51
  varchar: 1043,
50
52
  date: 1082,
@@ -73,14 +75,40 @@ export const DataTypeOIDs = {
73
75
  anyelement: 2283,
74
76
  anynonarray: 2776,
75
77
  uuid: 2950,
78
+ txid_snapshot: 2970,
79
+ pg_lsn: 3220,
80
+ pg_ndistinct: 3361,
81
+ pg_dependencies: 3402,
82
+ tsvector: 3614,
83
+ tsquery: 3615,
84
+ gtsvector: 3642,
85
+ regconfig: 3734,
86
+ regdictionary: 3769,
76
87
  jsonb: 3802,
77
88
  anyrange: 3831,
78
89
  int4range: 3904,
79
90
  numrange: 3906,
80
91
  tsrange: 3908,
92
+ tstzrange: 3910,
93
+ /** @deprecated Misspelling of `tstzrange`, kept so it keeps resolving. */
81
94
  rstzrange: 3910,
82
95
  daterange: 3912,
83
96
  int8range: 3926,
97
+ jsonpath: 4072,
98
+ regnamespace: 4089,
99
+ regrole: 4096,
100
+ regcollation: 4191,
101
+ int4multirange: 4451,
102
+ nummultirange: 4532,
103
+ tsmultirange: 4533,
104
+ tstzmultirange: 4534,
105
+ datemultirange: 4535,
106
+ int8multirange: 4536,
107
+ pg_brin_bloom_summary: 4600,
108
+ pg_brin_minmax_multi_summary: 4601,
109
+ pg_mcv_list: 5017,
110
+ pg_snapshot: 5038,
111
+ xid8: 5069,
84
112
  _xml: 143,
85
113
  _json: 199,
86
114
  _xid8: 271,
@@ -113,6 +141,7 @@ export const DataTypeOIDs = {
113
141
  _float8: 1022,
114
142
  _polygon: 1027,
115
143
  _oid: 1028,
144
+ _aclitem: 1034,
116
145
  _macaddr: 1040,
117
146
  _inet: 1041,
118
147
  _timestamp: 1115,
@@ -125,8 +154,39 @@ export const DataTypeOIDs = {
125
154
  _timetz: 1270,
126
155
  _bit: 1561,
127
156
  _varbit: 1563,
157
+ _refcursor: 2201,
158
+ _regprocedure: 2207,
159
+ _regoper: 2208,
160
+ _regoperator: 2209,
161
+ _regclass: 2210,
162
+ _regtype: 2211,
163
+ _record: 2287,
164
+ _txid_snapshot: 2949,
128
165
  _uuid: 2951,
166
+ _pg_lsn: 3221,
167
+ _tsvector: 3643,
168
+ _gtsvector: 3644,
169
+ _tsquery: 3645,
170
+ _regconfig: 3735,
171
+ _regdictionary: 3770,
129
172
  _jsonb: 3807,
173
+ _int4range: 3905,
174
+ _numrange: 3907,
175
+ _tsrange: 3909,
176
+ _tstzrange: 3911,
177
+ _daterange: 3913,
178
+ _int8range: 3927,
179
+ _jsonpath: 4073,
180
+ _regnamespace: 4090,
181
+ _regrole: 4097,
182
+ _regcollation: 4192,
183
+ _pg_snapshot: 5039,
184
+ _int4multirange: 6150,
185
+ _nummultirange: 6151,
186
+ _tsmultirange: 6152,
187
+ _tstzmultirange: 6153,
188
+ _datemultirange: 6155,
189
+ _int8multirange: 6157,
130
190
  };
131
191
  export const DataTypeNames = {
132
192
  [DataTypeOIDs.bool]: 'bool',
@@ -146,6 +206,7 @@ export const DataTypeNames = {
146
206
  [DataTypeOIDs.oidvector]: 'oidvector',
147
207
  [DataTypeOIDs.json]: 'json',
148
208
  [DataTypeOIDs.xml]: 'xml',
209
+ [DataTypeOIDs.pg_node_tree]: 'pg_node_tree',
149
210
  [DataTypeOIDs.point]: 'point',
150
211
  [DataTypeOIDs.lseg]: 'lseg',
151
212
  [DataTypeOIDs.path]: 'path',
@@ -161,6 +222,7 @@ export const DataTypeNames = {
161
222
  [DataTypeOIDs.money]: 'money',
162
223
  [DataTypeOIDs.macaddr]: 'macaddr',
163
224
  [DataTypeOIDs.inet]: 'inet',
225
+ [DataTypeOIDs.aclitem]: 'aclitem',
164
226
  [DataTypeOIDs.bpchar]: 'bpchar',
165
227
  [DataTypeOIDs.varchar]: 'varchar',
166
228
  [DataTypeOIDs.date]: 'date',
@@ -189,14 +251,38 @@ export const DataTypeNames = {
189
251
  [DataTypeOIDs.anyelement]: 'anyelement',
190
252
  [DataTypeOIDs.anynonarray]: 'anynonarray',
191
253
  [DataTypeOIDs.uuid]: 'uuid',
254
+ [DataTypeOIDs.txid_snapshot]: 'txid_snapshot',
255
+ [DataTypeOIDs.pg_lsn]: 'pg_lsn',
256
+ [DataTypeOIDs.pg_ndistinct]: 'pg_ndistinct',
257
+ [DataTypeOIDs.pg_dependencies]: 'pg_dependencies',
258
+ [DataTypeOIDs.tsvector]: 'tsvector',
259
+ [DataTypeOIDs.tsquery]: 'tsquery',
260
+ [DataTypeOIDs.gtsvector]: 'gtsvector',
261
+ [DataTypeOIDs.regconfig]: 'regconfig',
262
+ [DataTypeOIDs.regdictionary]: 'regdictionary',
192
263
  [DataTypeOIDs.jsonb]: 'jsonb',
193
264
  [DataTypeOIDs.anyrange]: 'anyrange',
194
265
  [DataTypeOIDs.int4range]: 'int4range',
195
266
  [DataTypeOIDs.numrange]: 'numrange',
196
267
  [DataTypeOIDs.tsrange]: 'tsrange',
197
- [DataTypeOIDs.rstzrange]: 'rstzrange',
268
+ [DataTypeOIDs.tstzrange]: 'tstzrange',
198
269
  [DataTypeOIDs.daterange]: 'daterange',
199
270
  [DataTypeOIDs.int8range]: 'int8range',
271
+ [DataTypeOIDs.jsonpath]: 'jsonpath',
272
+ [DataTypeOIDs.regnamespace]: 'regnamespace',
273
+ [DataTypeOIDs.regrole]: 'regrole',
274
+ [DataTypeOIDs.regcollation]: 'regcollation',
275
+ [DataTypeOIDs.int4multirange]: 'int4multirange',
276
+ [DataTypeOIDs.nummultirange]: 'nummultirange',
277
+ [DataTypeOIDs.tsmultirange]: 'tsmultirange',
278
+ [DataTypeOIDs.tstzmultirange]: 'tstzmultirange',
279
+ [DataTypeOIDs.datemultirange]: 'datemultirange',
280
+ [DataTypeOIDs.int8multirange]: 'int8multirange',
281
+ [DataTypeOIDs.pg_brin_bloom_summary]: 'pg_brin_bloom_summary',
282
+ [DataTypeOIDs.pg_brin_minmax_multi_summary]: 'pg_brin_minmax_multi_summary',
283
+ [DataTypeOIDs.pg_mcv_list]: 'pg_mcv_list',
284
+ [DataTypeOIDs.pg_snapshot]: 'pg_snapshot',
285
+ [DataTypeOIDs.xid8]: 'xid8',
200
286
  [DataTypeOIDs._xml]: '_xml',
201
287
  [DataTypeOIDs._json]: '_json',
202
288
  [DataTypeOIDs._xid8]: '_xid8',
@@ -229,6 +315,7 @@ export const DataTypeNames = {
229
315
  [DataTypeOIDs._float8]: '_float8',
230
316
  [DataTypeOIDs._polygon]: '_polygon',
231
317
  [DataTypeOIDs._oid]: '_oid',
318
+ [DataTypeOIDs._aclitem]: '_aclitem',
232
319
  [DataTypeOIDs._macaddr]: '_macaddr',
233
320
  [DataTypeOIDs._inet]: '_inet',
234
321
  [DataTypeOIDs._timestamp]: '_timestamp',
@@ -241,6 +328,37 @@ export const DataTypeNames = {
241
328
  [DataTypeOIDs._timetz]: '_timetz',
242
329
  [DataTypeOIDs._bit]: '_bit',
243
330
  [DataTypeOIDs._varbit]: '_varbit',
331
+ [DataTypeOIDs._refcursor]: '_refcursor',
332
+ [DataTypeOIDs._regprocedure]: '_regprocedure',
333
+ [DataTypeOIDs._regoper]: '_regoper',
334
+ [DataTypeOIDs._regoperator]: '_regoperator',
335
+ [DataTypeOIDs._regclass]: '_regclass',
336
+ [DataTypeOIDs._regtype]: '_regtype',
337
+ [DataTypeOIDs._record]: '_record',
338
+ [DataTypeOIDs._txid_snapshot]: '_txid_snapshot',
244
339
  [DataTypeOIDs._uuid]: '_uuid',
340
+ [DataTypeOIDs._pg_lsn]: '_pg_lsn',
341
+ [DataTypeOIDs._tsvector]: '_tsvector',
342
+ [DataTypeOIDs._gtsvector]: '_gtsvector',
343
+ [DataTypeOIDs._tsquery]: '_tsquery',
344
+ [DataTypeOIDs._regconfig]: '_regconfig',
345
+ [DataTypeOIDs._regdictionary]: '_regdictionary',
245
346
  [DataTypeOIDs._jsonb]: '_jsonb',
347
+ [DataTypeOIDs._int4range]: '_int4range',
348
+ [DataTypeOIDs._numrange]: '_numrange',
349
+ [DataTypeOIDs._tsrange]: '_tsrange',
350
+ [DataTypeOIDs._tstzrange]: '_tstzrange',
351
+ [DataTypeOIDs._daterange]: '_daterange',
352
+ [DataTypeOIDs._int8range]: '_int8range',
353
+ [DataTypeOIDs._jsonpath]: '_jsonpath',
354
+ [DataTypeOIDs._regnamespace]: '_regnamespace',
355
+ [DataTypeOIDs._regrole]: '_regrole',
356
+ [DataTypeOIDs._regcollation]: '_regcollation',
357
+ [DataTypeOIDs._pg_snapshot]: '_pg_snapshot',
358
+ [DataTypeOIDs._int4multirange]: '_int4multirange',
359
+ [DataTypeOIDs._nummultirange]: '_nummultirange',
360
+ [DataTypeOIDs._tsmultirange]: '_tsmultirange',
361
+ [DataTypeOIDs._tstzmultirange]: '_tstzmultirange',
362
+ [DataTypeOIDs._datemultirange]: '_datemultirange',
363
+ [DataTypeOIDs._int8multirange]: '_int8multirange',
246
364
  };