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.
- package/CHANGELOG.md +59 -1
- package/README.md +50 -0
- package/connection/connection.d.ts +14 -2
- package/connection/connection.js +63 -11
- package/connection/intl-connection.d.ts +164 -6
- package/connection/intl-connection.js +558 -37
- package/connection/pool.d.ts +30 -6
- package/connection/pool.js +22 -3
- package/connection/prepared-statement.js +22 -2
- package/data-type-map.d.ts +16 -0
- package/data-type-map.js +56 -12
- package/data-types/circle-type.js +5 -2
- package/data-types/classes/geometric.d.ts +49 -7
- package/data-types/classes/geometric.js +59 -11
- package/data-types/classes/interval.d.ts +40 -16
- package/data-types/classes/interval.js +68 -40
- package/data-types/classes/numeric.d.ts +6 -0
- package/data-types/classes/numeric.js +8 -0
- package/data-types/classes/range.d.ts +6 -1
- package/data-types/classes/range.js +6 -1
- package/data-types/date-type.js +2 -2
- package/data-types/interval-type.js +1 -1
- package/data-types/money-type.d.ts +38 -0
- package/data-types/money-type.js +212 -0
- package/data-types/numeric-type.d.ts +2 -0
- package/data-types/numeric-type.js +22 -11
- package/data-types/temporal-types.d.ts +19 -0
- package/data-types/temporal-types.js +520 -0
- package/data-types/timestamp-type.js +2 -2
- package/data-types/timestamptz-type.js +2 -2
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/interfaces/data-mapping-options.d.ts +126 -4
- package/interfaces/database-connection-params.d.ts +32 -5
- package/interfaces/query-options.d.ts +32 -0
- package/interfaces/script-execute-options.d.ts +32 -0
- package/interfaces/transaction-options.d.ts +27 -0
- package/interfaces/transaction-options.js +1 -0
- package/package.json +1 -1
- package/protocol/database-error.d.ts +15 -0
- package/protocol/database-error.js +19 -0
- package/protocol/frontend.js +1 -1
- package/protocol/pg-socket.js +7 -10
- package/util/array-leaf.d.ts +10 -0
- package/util/array-leaf.js +22 -0
- package/util/connection-config.js +11 -1
- package/util/date-style.d.ts +47 -0
- package/util/date-style.js +123 -0
- package/util/decimal-as-string.d.ts +11 -0
- package/util/decimal-as-string.js +30 -0
- package/util/fetch-as-string.d.ts +33 -0
- package/util/fetch-as-string.js +122 -0
- package/util/get-parsers.js +18 -1
- package/util/parse-datetime.d.ts +4 -3
- package/util/parse-datetime.js +34 -9
- package/util/resolve-column-formats.d.ts +5 -11
- package/util/resolve-column-formats.js +28 -24
- package/util/row-decoder.d.ts +24 -4
- package/util/row-decoder.js +25 -10
- package/util/sql-tag.js +2 -1
- package/util/stringify-for-sql.js +6 -5
- package/util/temporal.d.ts +47 -0
- package/util/temporal.js +61 -0
- package/util/transaction-command.d.ts +7 -0
- package/util/transaction-command.js +32 -0
- package/util/unspecified-param.d.ts +18 -8
- package/util/unspecified-param.js +22 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,64 @@
|
|
|
1
1
|
## Changelog
|
|
2
2
|
|
|
3
|
-
### [v3.
|
|
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
|
|
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
|
package/connection/connection.js
CHANGED
|
@@ -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
|
-
|
|
163
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
-
*
|
|
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
|
|
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
|
-
|
|
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 {};
|