postgrejs 3.8.0 → 3.10.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 (67) hide show
  1. package/CHANGELOG.md +59 -1
  2. package/README.md +50 -0
  3. package/connection/connection.d.ts +14 -2
  4. package/connection/connection.js +63 -11
  5. package/connection/intl-connection.d.ts +164 -6
  6. package/connection/intl-connection.js +558 -37
  7. package/connection/pool.d.ts +30 -6
  8. package/connection/pool.js +22 -3
  9. package/connection/prepared-statement.js +22 -2
  10. package/data-type-map.d.ts +16 -0
  11. package/data-type-map.js +56 -12
  12. package/data-types/circle-type.js +5 -2
  13. package/data-types/classes/geometric.d.ts +49 -7
  14. package/data-types/classes/geometric.js +59 -11
  15. package/data-types/classes/interval.d.ts +40 -16
  16. package/data-types/classes/interval.js +68 -40
  17. package/data-types/classes/numeric.d.ts +6 -0
  18. package/data-types/classes/numeric.js +8 -0
  19. package/data-types/classes/range.d.ts +6 -1
  20. package/data-types/classes/range.js +6 -1
  21. package/data-types/date-type.js +2 -2
  22. package/data-types/interval-type.js +1 -1
  23. package/data-types/money-type.d.ts +38 -0
  24. package/data-types/money-type.js +212 -0
  25. package/data-types/numeric-type.d.ts +2 -0
  26. package/data-types/numeric-type.js +22 -11
  27. package/data-types/temporal-types.d.ts +19 -0
  28. package/data-types/temporal-types.js +520 -0
  29. package/data-types/timestamp-type.js +2 -2
  30. package/data-types/timestamptz-type.js +2 -2
  31. package/index.d.ts +3 -0
  32. package/index.js +3 -0
  33. package/interfaces/data-mapping-options.d.ts +126 -4
  34. package/interfaces/database-connection-params.d.ts +32 -5
  35. package/interfaces/query-options.d.ts +32 -0
  36. package/interfaces/script-execute-options.d.ts +32 -0
  37. package/interfaces/transaction-options.d.ts +27 -0
  38. package/interfaces/transaction-options.js +1 -0
  39. package/package.json +1 -1
  40. package/protocol/database-error.d.ts +15 -0
  41. package/protocol/database-error.js +19 -0
  42. package/protocol/frontend.js +1 -1
  43. package/protocol/pg-socket.js +7 -10
  44. package/util/array-leaf.d.ts +10 -0
  45. package/util/array-leaf.js +22 -0
  46. package/util/connection-config.js +11 -1
  47. package/util/date-style.d.ts +47 -0
  48. package/util/date-style.js +123 -0
  49. package/util/decimal-as-string.d.ts +11 -0
  50. package/util/decimal-as-string.js +30 -0
  51. package/util/fetch-as-string.d.ts +33 -0
  52. package/util/fetch-as-string.js +122 -0
  53. package/util/get-parsers.js +18 -1
  54. package/util/parse-datetime.d.ts +4 -3
  55. package/util/parse-datetime.js +34 -9
  56. package/util/resolve-column-formats.d.ts +5 -11
  57. package/util/resolve-column-formats.js +28 -24
  58. package/util/row-decoder.d.ts +24 -4
  59. package/util/row-decoder.js +25 -10
  60. package/util/sql-tag.js +2 -1
  61. package/util/stringify-for-sql.js +6 -5
  62. package/util/temporal.d.ts +47 -0
  63. package/util/temporal.js +61 -0
  64. package/util/transaction-command.d.ts +7 -0
  65. package/util/transaction-command.js +32 -0
  66. package/util/unspecified-param.d.ts +18 -8
  67. package/util/unspecified-param.js +22 -14
package/CHANGELOG.md CHANGED
@@ -1,6 +1,64 @@
1
1
  ## Changelog
2
2
 
3
- ### [v3.8.0](https://github.com/panates/postgrejs/compare/v3.7.0...v3.8.0) -
3
+ ### [v3.10.0](https://github.com/panates/postgrejs/compare/v3.9.0...v3.10.0) -
4
+
5
+ #### Breaking Changes :warning:
6
+
7
+ - feat!: serialise the value classes as their fields @Eray Hanoğlu
8
+
9
+ #### 🚀 New Features
10
+
11
+ - feat: decode the date/time types into Temporal values on request @Eray Hanoğlu
12
+ - feat: let fetchAsString ask for a scalar without its arrays @Eray Hanoğlu
13
+ - feat: decode money and numeric as their exact decimal string on request @Eray Hanoğlu
14
+ - feat: let fetchAsString name an array column by its element type @Eray Hanoğlu
15
+ - feat: report a lost connection on 'error', not only on 'close' @Eray Hanoğlu
16
+ - feat: name Circle's radius `radius`, as pg does @Eray Hanoğlu
17
+
18
+ #### 🪲 Fixes
19
+
20
+ - fix: stop declaring an element type for an array of numbers @Eray Hanoğlu
21
+ - fix: sign only the interval components that have one, and add toPostgres() @Eray Hanoğlu
22
+ - fix: read the database out of a `postgresql://` URL @Eray Hanoğlu
23
+
24
+ ### [v3.9.0](https://github.com/panates/postgrejs/compare/v3.8.0...v3.9.0) - 22 September 2026
25
+
26
+ #### 🚀 New Features
27
+
28
+ - feat: decode money, by asking the server what a minor unit is @Eray Hanoğlu
29
+ - feat: pipeline by default, and let a connection opt out of it @Eray Hanoğlu
30
+ - feat: take the transaction's modes on startTransaction() @Eray Hanoğlu
31
+ - feat: let a connection answer the data-mapping options once @Eray Hanoğlu
32
+ - feat: keep the server's own error text on serverMessage @Eray Hanoğlu
33
+
34
+ #### 🪲 Fixes
35
+
36
+ - fix: read a text date in the DateStyle the server said it wrote @Eray Hanoğlu
37
+ - fix: let SET TRANSACTION run with rollbackOnError on @Eray Hanoğlu
38
+ - fix: ask for money's scale on the two paths that decoded before asking @Eray Hanoğlu
39
+ - fix: name a statement once, not once per caller in a burst @Eray Hanoğlu
40
+ - fix: keep a pooled connection unshared unless the caller asks @Eray Hanoğlu
41
+ - fix: type an array from the first value inside it, not from value[0] @Eray Hanoğlu
42
+ - fix: answer an empty statement instead of raising @Eray Hanoğlu
43
+
44
+ #### 📖 Documentation Changes
45
+
46
+ - docs: list the ORM adapters that run on this client @Eray Hanoğlu
47
+
48
+ #### 🛠 Refactoring and Updates
49
+
50
+ - refactor: let a row decoder declare its own rowType @Eray Hanoğlu
51
+
52
+ #### ⚡️ Performance Improvments
53
+
54
+ - perf: walk fewer types to infer a parameter, and write once per statement @Eray Hanoğlu
55
+ - perf: stop paying for a text row twice @Eray Hanoğlu
56
+
57
+ #### 💬 General Changes
58
+
59
+ - bench: regenerate the reports, and pin the adapter's options @Eray Hanoğlu
60
+
61
+ ### [v3.8.0](https://github.com/panates/postgrejs/compare/v3.7.0...v3.8.0) - 21 September 2026
4
62
 
5
63
  #### 🚀 New Features
6
64
 
package/README.md CHANGED
@@ -48,6 +48,56 @@ prepared statements, server-side cursors, LISTEN/NOTIFY, bulk `COPY` streams, lo
48
48
  two-phase commit, multi-host failover, and SCRAM channel binding - all in the one package, written in
49
49
  strictly-typed TypeScript from the ground up.
50
50
 
51
+ ### 🔌 Bring Your Own ORM
52
+
53
+ PostgreJS is a driver, not a framework, so what you build on top of it stays your choice:
54
+
55
+ <!-- One cell per adapter, so each renders as its own card: a table because
56
+ GitHub strips CSS, and this is the one layout that survives everywhere
57
+ the README is read. The logos come from postgrejs.com rather than being
58
+ hotlinked from each project, and Drizzle's follows the reader's theme. -->
59
+ <table>
60
+ <tr>
61
+ <td align="center" width="230" valign="top">
62
+ <a href="https://www.sqbjs.org"><img src="https://www.postgrejs.com/img/sqb-logo.svg" alt="SQB" height="60"></a><br><br>
63
+ <b><a href="https://www.sqbjs.org">SQB</a></b><br>
64
+ <a href="https://www.npmjs.com/package/@sqb/postgres"><code>@sqb/postgres</code></a><br>
65
+ <sub>native driver</sub>
66
+ </td>
67
+ <td align="center" width="230" valign="top">
68
+ <a href="https://kysely.dev"><img src="https://www.postgrejs.com/img/kysely-logo.svg" alt="Kysely" height="60"></a><br><br>
69
+ <b><a href="https://kysely.dev">Kysely</a></b><br>
70
+ <a href="https://github.com/panates/postgrejs-kysely"><code>kysely-postgrejs</code></a><br>
71
+ <sub>dialect</sub>
72
+ </td>
73
+ <td align="center" width="230" valign="top">
74
+ <a href="https://orm.drizzle.team"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.postgrejs.com/img/drizzle-logo-dark.svg"><img src="https://www.postgrejs.com/img/drizzle-logo-light.svg" alt="Drizzle ORM" height="34"></picture></a><br><br>
75
+ <b><a href="https://orm.drizzle.team">Drizzle ORM</a></b><br>
76
+ <a href="https://github.com/panates/postgrejs-drizzle"><code>drizzle-postgrejs</code></a><br>
77
+ <sub>driver</sub>
78
+ </td>
79
+ </tr>
80
+ <tr>
81
+ <td align="center" width="230" valign="top">
82
+ <a href="https://typeorm.io"><img src="https://www.postgrejs.com/img/typeorm-icon.png" alt="TypeORM" height="60"></a><br><br>
83
+ <b><a href="https://typeorm.io">TypeORM</a></b><br>
84
+ <a href="https://github.com/panates/postgrejs-typeorm"><code>typeorm-postgrejs</code></a><br>
85
+ <sub>driver</sub>
86
+ </td>
87
+ <td align="center" width="230" valign="top">
88
+ <a href="https://www.prisma.io"><img src="https://www.postgrejs.com/img/prisma-icon.svg" alt="Prisma" height="60"></a><br><br>
89
+ <b><a href="https://www.prisma.io">Prisma</a></b><br>
90
+ <a href="https://github.com/panates/postgrejs-prisma"><code>prisma-postgrejs</code></a><br>
91
+ <sub>driver adapter</sub>
92
+ </td>
93
+ <td width="230"></td>
94
+ </tr>
95
+ </table>
96
+
97
+ Each adapter hands the compiled SQL straight to this client, with no `pg` left anywhere in the chain, and each is
98
+ compared query by query against the driver it replaces - and, where the project ships a suite of its own, run
99
+ against that too. So adopting one is a change to how the connection is created and nothing else.
100
+
51
101
  ## Installation
52
102
 
53
103
  ```bash
@@ -9,6 +9,7 @@ import type { QueryResult } from '../interfaces/query-result.js';
9
9
  import type { ScriptExecuteOptions } from '../interfaces/script-execute-options.js';
10
10
  import type { ScriptResult } from '../interfaces/script-result.js';
11
11
  import type { StatementPrepareOptions } from '../interfaces/statement-prepare-options.js';
12
+ import type { TransactionOptions } from '../interfaces/transaction-options.js';
12
13
  import type { DatabaseError } from '../protocol/database-error.js';
13
14
  import type { Protocol } from '../protocol/protocol.js';
14
15
  import { SafeEventEmitter } from '../safe-event-emitter.js';
@@ -281,7 +282,7 @@ export declare class Connection extends SafeEventEmitter implements AsyncDisposa
281
282
  /**
282
283
  * Starts a transaction
283
284
  */
284
- startTransaction(): Promise<void>;
285
+ startTransaction(options?: TransactionOptions): Promise<void>;
285
286
  /**
286
287
  * Runs `fn` inside a transaction and commits when it returns, or rolls
287
288
  * back and rethrows when it throws - the try/catch every caller of
@@ -309,7 +310,7 @@ export declare class Connection extends SafeEventEmitter implements AsyncDisposa
309
310
  * `fn` is handed this same connection: every statement it runs on it is
310
311
  * inside the transaction, and one it runs on another connection is not.
311
312
  */
312
- transaction<T>(fn: (connection: this) => Promise<T>): Promise<T>;
313
+ transaction<T>(fn: (connection: this) => Promise<T>, options?: TransactionOptions): Promise<T>;
313
314
  /**
314
315
  * Commits current transaction.
315
316
  * @param immediate - Commits right away, ignoring how many nested
@@ -370,6 +371,11 @@ export declare class Connection extends SafeEventEmitter implements AsyncDisposa
370
371
  listen(channel: string, callback: NotificationCallback): Promise<void>;
371
372
  unListen(channel: string): Promise<void>;
372
373
  unListenAll(): Promise<void>;
374
+ /**
375
+ * Whether a statement asked for the wire to itself - `pipeline: false`
376
+ * on the call, or on the connection when the call says nothing.
377
+ */
378
+ protected _isExclusive(pipeline: Maybe<boolean>): boolean;
373
379
  protected _query(sql: string, options?: QueryOptions): Promise<QueryResult>;
374
380
  /**
375
381
  * A large object's descriptor is only valid inside the transaction that
@@ -381,6 +387,12 @@ export declare class Connection extends SafeEventEmitter implements AsyncDisposa
381
387
  protected _openLargeObject(oid: number, mode: number, ownsTransaction: boolean): Promise<LargeObject>;
382
388
  protected _handleNotification(msg: NotificationMessage): void;
383
389
  protected _close(): Promise<void>;
390
+ /**
391
+ * Adds the source excerpt the server's `position` points at to
392
+ * `message`, so an error reads in a terminal without the caller doing
393
+ * anything. `err.serverMessage` keeps the undecorated text for
394
+ * anything that parses it.
395
+ */
384
396
  protected _handleError(err: DatabaseError, script: string): DatabaseError;
385
397
  /**
386
398
  * Remembers where a call came from, so the error it may reject with points
@@ -1,5 +1,4 @@
1
1
  import { ConnectionState, DataTypeOIDs } from '../constants.js';
2
- import { GlobalTypeMap } from '../data-type-map.js';
3
2
  import { SafeEventEmitter } from '../safe-event-emitter.js';
4
3
  import { withAbortSignal } from '../util/abort-signal.js';
5
4
  import { normalizeChannelName } from '../util/channel-name.js';
@@ -159,9 +158,17 @@ export class Connection extends SafeEventEmitter {
159
158
  sql = sql.stringify({ ...options, typeMap: options?.typeMap });
160
159
  if (this.listenerCount('execute'))
161
160
  this.emit('execute', sql, options);
162
- return withAbortSignal(options?.signal, () => this._intlCon.cancel(), () => this._captureErrorStack(this._intlCon.execute(sql, options), this.execute, options?.asyncErrorHandling).catch((e) => {
163
- throw this._handleError(e, sql);
164
- }));
161
+ let release = this._intlCon.enterWire(this._isExclusive(options?.pipeline));
162
+ if (typeof release !== 'function')
163
+ release = await release;
164
+ try {
165
+ return await withAbortSignal(options?.signal, () => this._intlCon.cancel(), () => this._captureErrorStack(this._intlCon.execute(sql, options), this.execute, options?.asyncErrorHandling).catch((e) => {
166
+ throw this._handleError(e, sql);
167
+ }));
168
+ }
169
+ finally {
170
+ release();
171
+ }
165
172
  }
166
173
  /**
167
174
  * The legacy Function Call sub-protocol - calls a function by OID
@@ -200,7 +207,15 @@ export class Connection extends SafeEventEmitter {
200
207
  /* c8 ignore stop */
201
208
  if (this.listenerCount('query'))
202
209
  this.emit('query', sql, options);
203
- return withAbortSignal(options?.signal, () => this._intlCon.cancel(), () => this._query(sql, options));
210
+ let release = this._intlCon.enterWire(this._isExclusive(options?.pipeline));
211
+ if (typeof release !== 'function')
212
+ release = await release;
213
+ try {
214
+ return await withAbortSignal(options?.signal, () => this._intlCon.cancel(), () => this._query(sql, options));
215
+ }
216
+ finally {
217
+ release();
218
+ }
204
219
  }
205
220
  /**
206
221
  * Runs a `COPY ... TO STDOUT` and returns its output as a stream of the
@@ -479,8 +494,8 @@ export class Connection extends SafeEventEmitter {
479
494
  /**
480
495
  * Starts a transaction
481
496
  */
482
- startTransaction() {
483
- return this._captureErrorStack(this._intlCon.startTransaction());
497
+ startTransaction(options) {
498
+ return this._captureErrorStack(this._intlCon.startTransaction(options));
484
499
  }
485
500
  /**
486
501
  * Runs `fn` inside a transaction and commits when it returns, or rolls
@@ -509,10 +524,19 @@ export class Connection extends SafeEventEmitter {
509
524
  * `fn` is handed this same connection: every statement it runs on it is
510
525
  * inside the transaction, and one it runs on another connection is not.
511
526
  */
512
- async transaction(fn) {
513
- if (this._intlCon.inTransaction)
527
+ async transaction(fn, options) {
528
+ // A call inside a transaction becomes a savepoint scope, which has
529
+ // no BEGIN to carry modes - see startTransaction(), which refuses
530
+ // them for the same reason rather than applying them to somebody
531
+ // else's transaction.
532
+ if (this._intlCon.inTransaction) {
533
+ if (options)
534
+ throw new Error('transaction() cannot set transaction modes inside a transaction ' +
535
+ 'that is already open - the inner scope is a savepoint, and the ' +
536
+ 'modes belong to the BEGIN that opened the outer one');
514
537
  return await this._savepointScope(fn);
515
- await this.startTransaction();
538
+ }
539
+ await this.startTransaction(options);
516
540
  try {
517
541
  const result = await fn(this);
518
542
  await this.commit();
@@ -630,8 +654,22 @@ export class Connection extends SafeEventEmitter {
630
654
  await this._captureErrorStack(this.query('UNLISTEN *'));
631
655
  }
632
656
  }
657
+ /**
658
+ * Whether a statement asked for the wire to itself - `pipeline: false`
659
+ * on the call, or on the connection when the call says nothing.
660
+ */
661
+ _isExclusive(pipeline) {
662
+ return pipeline != null
663
+ ? !pipeline
664
+ : this._intlCon.config.pipeline === false;
665
+ }
633
666
  async _query(sql, options) {
634
- const typeMap = options?.typeMap || GlobalTypeMap;
667
+ // Only the type map, not withDefaults(): the parameter types are
668
+ // decided here, before the options are merged, and merging them here
669
+ // would change what the merge means - a fetchAsString list that came
670
+ // from the connection deliberately takes a cheaper route than one
671
+ // named on the call.
672
+ const typeMap = this._intlCon.resolveTypeMap(options);
635
673
  const paramTypes = options?.params?.map(prm => prm instanceof BindParam
636
674
  ? prm.oid
637
675
  : // A Date and a string go out with no declared type, so the
@@ -644,6 +682,14 @@ export class Connection extends SafeEventEmitter {
644
682
  isUnspecifiedParam(prm)
645
683
  ? 0
646
684
  : typeMap.determine(prm));
685
+ // A money parameter is written as an int64 of minor units, so the
686
+ // scale has to be known before the Bind goes out - the probe fired
687
+ // at connect answers in time for every result, but not necessarily
688
+ // for the encode of the very first statement.
689
+ if (paramTypes &&
690
+ (paramTypes.includes(DataTypeOIDs.money) ||
691
+ paramTypes.includes(DataTypeOIDs._money)))
692
+ await this._intlCon.ensureMoneyFormat();
647
693
  const effectiveAutoCommit = options?.autoCommit != null
648
694
  ? options.autoCommit
649
695
  : this._intlCon.config.autoCommit;
@@ -716,6 +762,12 @@ export class Connection extends SafeEventEmitter {
716
762
  await this._captureErrorStack(this._intlCon.close());
717
763
  this._closing = false;
718
764
  }
765
+ /**
766
+ * Adds the source excerpt the server's `position` points at to
767
+ * `message`, so an error reads in a terminal without the caller doing
768
+ * anything. `err.serverMessage` keeps the undecorated text for
769
+ * anything that parses it.
770
+ */
719
771
  _handleError(err, script) {
720
772
  if (err.position != null) {
721
773
  const i1 = script.lastIndexOf('\n', err.position - 1) + 1;
@@ -2,7 +2,8 @@ import { ConnectionState } from '../constants.js';
2
2
  import type { DataTypeMap } from '../data-type-map.js';
3
3
  import type { BatchResult } from '../interfaces/batch-result.js';
4
4
  import type { CopyFromRowsOptions, CopyFromRowsResult } from '../interfaces/copy-from-rows-options.js';
5
- import type { ConnectionConfiguration } from '../interfaces/database-connection-params.js';
5
+ import type { DataMappingOptions, MoneyFormat } from '../interfaces/data-mapping-options.js';
6
+ import type { ConnectionConfiguration, ConnectionMappingDefaults } from '../interfaces/database-connection-params.js';
6
7
  import type { FieldInfo } from '../interfaces/field-info.js';
7
8
  import type { FunctionCallOptions } from '../interfaces/function-call-options.js';
8
9
  import type { FunctionCallResult } from '../interfaces/function-call-result.js';
@@ -10,13 +11,29 @@ import type { QueryOptions } from '../interfaces/query-options.js';
10
11
  import type { QueryResult } from '../interfaces/query-result.js';
11
12
  import type { ScriptExecuteOptions } from '../interfaces/script-execute-options.js';
12
13
  import type { ScriptResult } from '../interfaces/script-result.js';
14
+ import type { TransactionOptions } from '../interfaces/transaction-options.js';
13
15
  import { PgSocket } from '../protocol/pg-socket.js';
14
16
  import { Protocol } from '../protocol/protocol.js';
15
17
  import { SafeEventEmitter } from '../safe-event-emitter.js';
16
18
  import type { AnyParseFunction, Maybe, OID } from '../types.js';
17
19
  import { type CopyRowSource } from '../util/copy-from-rows.js';
20
+ import { type PgDateStyle } from '../util/date-style.js';
21
+ import { type RowDecoder } from '../util/row-decoder.js';
18
22
  import type { Connection } from './connection.js';
19
23
  import { CopyFromStream, CopyToStream } from './copy-stream.js';
24
+ interface PreparedCacheEntry {
25
+ name: string;
26
+ fields?: Protocol.RowDescription[];
27
+ }
28
+ /** See IntlConnection._decodeDeferredRows(). */
29
+ interface DeferredRows {
30
+ target: {
31
+ rows?: any[];
32
+ };
33
+ raw: Protocol.DataRowMessage[];
34
+ parsers: AnyParseFunction[];
35
+ fields: any;
36
+ }
20
37
  export declare class IntlConnection extends SafeEventEmitter {
21
38
  /**
22
39
  * Server-side prepared statements this connection has built, keyed by
@@ -29,6 +46,15 @@ export declare class IntlConnection extends SafeEventEmitter {
29
46
  * this is per connection and dies with it.
30
47
  */
31
48
  private _preparedCache;
49
+ /**
50
+ * The names being given out right now, one per SQL. A burst of the
51
+ * same statement arrives before any of it is prepared, and without
52
+ * this every call in the burst prepares its own copy: measured at 50
53
+ * concurrent `select $1::int4`, 25 Parse+Describe round trips and 25
54
+ * named statements left on the server that this map's one entry could
55
+ * never close again.
56
+ */
57
+ private _preparing;
32
58
  /** SQL seen once but not yet prepared - see PREPARE_AFTER_USES. */
33
59
  private _preparedCandidates;
34
60
  private _preparedCounter;
@@ -38,6 +64,29 @@ export declare class IntlConnection extends SafeEventEmitter {
38
64
  protected _savepointDepths: Map<string, number>;
39
65
  protected _config: ConnectionConfiguration;
40
66
  protected _onErrorSavePoint: string;
67
+ /**
68
+ * The data-mapping options this connection was configured with, or
69
+ * undefined when it was given none - which is the common case, and
70
+ * the one that must not pay for this.
71
+ */
72
+ protected readonly _mappingDefaults?: ConnectionMappingDefaults;
73
+ /** The session's DateStyle as last reported, and what it parsed to. */
74
+ protected _dateStyleRaw?: string;
75
+ protected _dateStyle?: PgDateStyle;
76
+ /** The session's TimeZone as last reported, once checked. */
77
+ protected _timeZoneRaw?: string;
78
+ protected _timeZone?: string;
79
+ /** The server's own money rendering - see ensureMoneyFormat(). */
80
+ protected _moneyFormat?: MoneyFormat;
81
+ protected _moneyFormatPromise?: Promise<void>;
82
+ /** Whether the socket has been up, which is what makes a close a loss. */
83
+ protected _live: boolean;
84
+ /** Statements currently holding the wire - see enterWire(). */
85
+ protected _wireUsers: number;
86
+ protected _wireIdleWaiters?: (() => void)[];
87
+ protected _wireLock?: Promise<void>;
88
+ /** Bound once: enterWire()'s fast path hands out this same function. */
89
+ protected _releaseWire: () => void;
41
90
  transactionStatus: string;
42
91
  socket: PgSocket;
43
92
  owner?: SafeEventEmitter;
@@ -74,7 +123,7 @@ export declare class IntlConnection extends SafeEventEmitter {
74
123
  * that point). A matching number of commit() calls is then needed to
75
124
  * actually commit - see commit().
76
125
  */
77
- startTransaction(): Promise<void>;
126
+ startTransaction(options?: TransactionOptions): Promise<void>;
78
127
  /**
79
128
  * Starts a savepoint, or - if one under the same `name` is already open -
80
129
  * marks a nested level of it. Mirrors startTransaction(): only the
@@ -142,6 +191,49 @@ export declare class IntlConnection extends SafeEventEmitter {
142
191
  rollbackToSavepoint(name: string): Promise<void>;
143
192
  /** Asks the server to cancel whatever this session is running. */
144
193
  cancel(): Promise<void>;
194
+ /**
195
+ * Claims the wire for one statement, and hands back the function that
196
+ * releases it.
197
+ *
198
+ * Several statements share it by default: PostgreSQL correlates
199
+ * responses to requests by order, so a connection can carry more than
200
+ * one at a time and a caller that does not wait for each reply is
201
+ * measurably faster. `exclusive` is `pipeline: false` - the statement
202
+ * waits until nothing else is running here, and nothing else starts
203
+ * until it releases.
204
+ *
205
+ * Returns the release function itself rather than a promise of one
206
+ * whenever it can be taken without waiting, which is every statement
207
+ * on a connection nobody has asked to serialise - the common case, and
208
+ * the one that must not pay for this.
209
+ */
210
+ enterWire(exclusive?: boolean): (() => void) | Promise<() => void>;
211
+ /**
212
+ * Asks the server how it renders money, once per connection.
213
+ *
214
+ * `money` travels as an int64 of the smallest currency unit, and how
215
+ * many of those make one unit is `lc_monetary` - which the server
216
+ * does not report among its startup parameters, so `1234` on the wire
217
+ * is $12.34, ¥1234 or 1.234 KWD depending on a setting only the server
218
+ * knows. Asking it to render a value it already knows is the whole
219
+ * answer, and needs no locale data on this side.
220
+ *
221
+ * `1` is the value asked for because it cannot carry a thousands
222
+ * separator: whatever separator comes back can only be the decimal
223
+ * one, and the digits after it can only be the fraction. `$1.00` is
224
+ * two, `¥1` is none.
225
+ */
226
+ ensureMoneyFormat(): Promise<void>;
227
+ /**
228
+ * Whether these columns need the server's money format and this
229
+ * connection has not asked for it yet.
230
+ *
231
+ * The scan costs a look at each column's OID, and only until the
232
+ * answer is in - from then on the first test ends it.
233
+ */
234
+ needsMoneyFormat(fields: Maybe<{
235
+ dataTypeId: OID;
236
+ }[]>, options?: DataMappingOptions): boolean;
145
237
  ref(): void;
146
238
  unref(): boolean;
147
239
  assertConnected(): void;
@@ -204,11 +296,22 @@ export declare class IntlConnection extends SafeEventEmitter {
204
296
  /**
205
297
  * The savepoint rollbackOnError calls for, or undefined when this call
206
298
  * needs none: outside a transaction there is nothing to roll back to,
207
- * and a statement that is itself a transaction command manages its own
208
- * boundaries (wrapping COMMIT in a savepoint would be nonsense).
299
+ * a statement that is itself a transaction command manages its own
300
+ * boundaries (wrapping COMMIT in a savepoint would be nonsense), and
301
+ * PostgreSQL refuses `SET TRANSACTION` inside one outright.
209
302
  */
210
303
  protected _inlineSavepointFor(sql: string, options: QueryOptions): Maybe<string>;
211
- protected _queryCached(sql: string, paramTypes: Maybe<Maybe<OID>[]>, params: Maybe<Maybe<any>[]>, options: QueryOptions, savepoint: Maybe<string>): Promise<QueryResult>;
304
+ protected _queryCached(sql: string, paramTypes: Maybe<Maybe<OID>[]>, params: Maybe<Maybe<any>[]>, options: QueryOptions, savepoint: Maybe<string>,
305
+ /** Whether the CALL asked for text columns, not the connection. */
306
+ callWantsFields: boolean): Promise<QueryResult>;
307
+ /**
308
+ * Gives this SQL a name and caches it, once, however many callers are
309
+ * waiting. A Parse that fails caches nothing and reports itself; the
310
+ * statement is simply never reused. It runs outside the savepoint, as
311
+ * the prepare() the transaction path used to do ahead of its own
312
+ * wrapper.
313
+ */
314
+ protected _prepareForCache(key: string, sql: string, paramTypes: Maybe<Maybe<OID>[]>): Promise<PreparedCacheEntry>;
212
315
  /**
213
316
  * Counts one more use of this SQL and says whether it has now been seen
214
317
  * often enough to be worth preparing under a name.
@@ -283,6 +386,61 @@ export declare class IntlConnection extends SafeEventEmitter {
283
386
  executeBatchReused(statementName: string, cachedFields: Protocol.RowDescription[] | undefined, paramTypes: Maybe<Maybe<OID>[]>, paramSets: Maybe<any>[][], options: QueryOptions): Promise<BatchResult>;
284
387
  executeReused(statementName: string, cachedFields: Protocol.RowDescription[] | undefined, paramTypes: Maybe<Maybe<OID>[]>, params: Maybe<Maybe<any>[]>, options: QueryOptions, savepoint?: string): Promise<QueryResult>;
285
388
  emit(event: string | symbol, ...args: any[]): boolean;
286
- protected _onError(err: Error): void;
389
+ /**
390
+ * The slow half of enterWire(): either an exclusive statement, or an
391
+ * ordinary one arriving while an exclusive statement holds the wire.
392
+ *
393
+ * The claim itself is synchronous on purpose. Each waiter wakes in its
394
+ * own microtask and runs to its next `await` without interruption, so
395
+ * re-reading `_wireLock` and assigning it in the same stretch is what
396
+ * makes two waiters unable to both believe they took it.
397
+ */
398
+ protected _enterWireQueued(exclusive: boolean): Promise<() => void>;
399
+ /**
400
+ * `options` with whatever this connection can answer for it: the
401
+ * data-mapping defaults it was configured with, and the money format
402
+ * it has learned.
403
+ *
404
+ * At most one shallow copy per statement, and only when there is
405
+ * something to fill in - a connection configured with nothing and no
406
+ * money in sight hands the caller's own object straight back.
407
+ */
408
+ /**
409
+ * Rows left raw because a money column's scale was not in yet.
410
+ *
411
+ * Two paths decode inside the message loop, where there is no longer
412
+ * anywhere to ask the server anything: the Simple Query protocol and
413
+ * a pipeline. Rather than read those against a scale nobody
414
+ * confirmed, they set the rows aside and this reads them once the
415
+ * loop is over and the question can be asked.
416
+ */
417
+ protected _decodeDeferredRows(deferred: DeferredRows[], rowDecoder: RowDecoder, options: QueryOptions): Promise<QueryOptions>;
418
+ /**
419
+ * The type map a statement is parsed and its parameters typed with:
420
+ * the call's, else the connection's, with whatever `temporalTypes`
421
+ * asks for registered on top of it.
422
+ */
423
+ resolveTypeMap(options?: ConnectionMappingDefaults): DataTypeMap;
424
+ withDefaults<T extends DataMappingOptions>(options: T): T;
425
+ /**
426
+ * The session's DateStyle, when it is not ISO.
427
+ *
428
+ * Read off the reported parameters rather than cached once: `SET
429
+ * DateStyle` is answered with a fresh ParameterStatus, so the string
430
+ * changes under us and a connection that changes it mid-session must
431
+ * not go on decoding by the old one. The comparison is against the
432
+ * same string the socket holds, so it costs a read and a pointer
433
+ * compare while nothing changes - which is always, for the ISO
434
+ * default that needs no parsing at all.
435
+ */
436
+ /**
437
+ * The zone `timestamptz` values are given when they decode to a
438
+ * Temporal.ZonedDateTime. Checked when the server's answer changes, so
439
+ * that a zone nothing can resolve is reported against the setting it
440
+ * came from instead of from inside a decode.
441
+ */
442
+ protected _currentTimeZone(): Maybe<string>;
443
+ protected _currentDateStyle(): Maybe<PgDateStyle>;
287
444
  }
288
445
  export declare function getIntlConnection(connection: Connection): IntlConnection;
446
+ export {};