postgrejs 3.12.0 → 3.12.2
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/README.md +1 -1
- package/connection/bind-param.d.ts +21 -0
- package/connection/bind-param.js +21 -0
- package/connection/connection.d.ts +136 -0
- package/connection/connection.js +132 -5
- package/connection/copy-stream.d.ts +2 -0
- package/connection/copy-stream.js +2 -0
- package/connection/cursor.d.ts +67 -5
- package/connection/cursor.js +88 -15
- package/connection/intl-connection.d.ts +14 -0
- package/connection/intl-connection.js +95 -15
- package/connection/large-object.d.ts +18 -0
- package/connection/large-object.js +17 -0
- package/connection/logical-replication.d.ts +15 -0
- package/connection/logical-replication.js +6 -0
- package/connection/pool.d.ts +80 -0
- package/connection/pool.js +82 -9
- package/connection/portal.d.ts +37 -0
- package/connection/portal.js +29 -0
- package/connection/prepared-statement.d.ts +68 -0
- package/connection/prepared-statement.js +71 -2
- package/constants.d.ts +18 -0
- package/constants.js +18 -0
- package/data-type-map.d.ts +38 -0
- package/data-type-map.js +38 -0
- package/data-types/bit-type.d.ts +4 -0
- package/data-types/bit-type.js +4 -0
- package/data-types/bool-type.d.ts +2 -0
- package/data-types/bool-type.js +2 -0
- package/data-types/box-type.d.ts +2 -0
- package/data-types/box-type.js +2 -0
- package/data-types/bytea-type.d.ts +2 -0
- package/data-types/bytea-type.js +2 -0
- package/data-types/char-type.d.ts +2 -0
- package/data-types/char-type.js +2 -0
- package/data-types/circle-type.d.ts +2 -0
- package/data-types/circle-type.js +2 -0
- package/data-types/date-type.d.ts +2 -0
- package/data-types/date-type.js +2 -0
- package/data-types/float4-type.d.ts +2 -0
- package/data-types/float4-type.js +2 -0
- package/data-types/float8-type.d.ts +2 -0
- package/data-types/float8-type.js +2 -0
- package/data-types/inet-type.d.ts +4 -0
- package/data-types/inet-type.js +4 -0
- package/data-types/int2-type.d.ts +2 -0
- package/data-types/int2-type.js +2 -0
- package/data-types/int2-vector-type.d.ts +2 -0
- package/data-types/int2-vector-type.js +2 -0
- package/data-types/int4-type.d.ts +2 -0
- package/data-types/int4-type.js +2 -0
- package/data-types/int8-type.d.ts +2 -0
- package/data-types/int8-type.js +2 -0
- package/data-types/interval-type.d.ts +9 -0
- package/data-types/interval-type.js +9 -0
- package/data-types/json-type.d.ts +2 -0
- package/data-types/json-type.js +2 -0
- package/data-types/jsonb-type.d.ts +2 -0
- package/data-types/jsonb-type.js +2 -0
- package/data-types/jsonpath-type.d.ts +2 -0
- package/data-types/jsonpath-type.js +2 -0
- package/data-types/line-type.d.ts +2 -0
- package/data-types/line-type.js +2 -0
- package/data-types/lseg-type.d.ts +2 -0
- package/data-types/lseg-type.js +2 -0
- package/data-types/macaddr-type.d.ts +4 -0
- package/data-types/macaddr-type.js +4 -0
- package/data-types/money-type.d.ts +1 -0
- package/data-types/money-type.js +17 -10
- package/data-types/numeric-type.d.ts +2 -0
- package/data-types/numeric-type.js +2 -0
- package/data-types/oid-type.d.ts +2 -0
- package/data-types/oid-type.js +2 -0
- package/data-types/oid-vector-type.d.ts +1 -0
- package/data-types/oid-vector-type.js +1 -0
- package/data-types/path-type.d.ts +4 -0
- package/data-types/path-type.js +4 -0
- package/data-types/pg-lsn-type.d.ts +2 -0
- package/data-types/pg-lsn-type.js +2 -0
- package/data-types/point-type.d.ts +2 -0
- package/data-types/point-type.js +2 -0
- package/data-types/range-type.d.ts +4 -0
- package/data-types/range-type.js +4 -0
- package/data-types/snapshot-type.d.ts +4 -0
- package/data-types/snapshot-type.js +4 -0
- package/data-types/tid-type.d.ts +2 -0
- package/data-types/tid-type.js +2 -0
- package/data-types/time-type.d.ts +2 -0
- package/data-types/time-type.js +2 -0
- package/data-types/timestamp-type.d.ts +2 -0
- package/data-types/timestamp-type.js +2 -0
- package/data-types/timestamptz-type.d.ts +2 -0
- package/data-types/timestamptz-type.js +2 -0
- package/data-types/timetz-type.d.ts +2 -0
- package/data-types/timetz-type.js +2 -0
- package/data-types/tsvector-type.d.ts +4 -0
- package/data-types/tsvector-type.js +4 -0
- package/data-types/uuid-type.d.ts +2 -0
- package/data-types/uuid-type.js +2 -0
- package/data-types/varchar-type.d.ts +2 -0
- package/data-types/varchar-type.js +2 -0
- package/data-types/xid-type.d.ts +6 -0
- package/data-types/xid-type.js +6 -0
- package/interfaces/command-result.d.ts +7 -0
- package/interfaces/copy-from-rows-options.d.ts +4 -0
- package/interfaces/data-mapping-options.d.ts +6 -0
- package/interfaces/data-type.d.ts +37 -0
- package/interfaces/database-connection-params.d.ts +31 -0
- package/interfaces/field-info.d.ts +8 -0
- package/interfaces/function-call-options.d.ts +1 -0
- package/interfaces/function-call-result.d.ts +6 -0
- package/interfaces/pipeline-request.d.ts +2 -0
- package/interfaces/query-options.d.ts +7 -0
- package/interfaces/query-result.d.ts +7 -0
- package/interfaces/script-execute-options.d.ts +4 -0
- package/interfaces/script-result.d.ts +1 -0
- package/interfaces/statement-prepare-options.d.ts +1 -0
- package/package.json +5 -5
- package/protocol/backend.d.ts +6 -0
- package/protocol/backend.js +35 -5
- package/protocol/cert-signature.d.ts +8 -0
- package/protocol/cert-signature.js +8 -0
- package/protocol/database-error.d.ts +8 -0
- package/protocol/database-error.js +8 -0
- package/protocol/frontend.d.ts +16 -0
- package/protocol/frontend.js +13 -6
- package/protocol/pg-socket.d.ts +10 -0
- package/protocol/pg-socket.js +14 -7
- package/protocol/pgoutput.d.ts +15 -0
- package/protocol/pgoutput.js +7 -0
- package/protocol/protocol.d.ts +50 -2
- package/protocol/protocol.js +17 -1
- package/protocol/sasl.d.ts +22 -0
- package/protocol/sasl.js +21 -0
- package/protocol/smart-buffer.d.ts +4 -0
- package/safe-event-emitter.d.ts +7 -0
- package/safe-event-emitter.js +7 -0
- package/types.d.ts +21 -0
- package/util/array-calculatedim.d.ts +10 -0
- package/util/array-calculatedim.js +10 -0
- package/util/bigint-methods.d.ts +7 -0
- package/util/bigint-methods.js +9 -0
- package/util/config-from-env.d.ts +10 -0
- package/util/config-from-env.js +10 -0
- package/util/connection-config.d.ts +17 -0
- package/util/connection-config.js +17 -0
- package/util/copy-from-rows.d.ts +12 -0
- package/util/copy-from-rows.js +9 -0
- package/util/decimal-as-string.d.ts +6 -0
- package/util/decimal-as-string.js +6 -0
- package/util/decode-binaryarray.d.ts +9 -0
- package/util/decode-binaryarray.js +9 -0
- package/util/escape-literal.d.ts +11 -0
- package/util/escape-literal.js +13 -0
- package/util/fast-parseint.d.ts +14 -0
- package/util/fast-parseint.js +14 -0
- package/util/format-datetime.d.ts +26 -0
- package/util/format-datetime.js +26 -0
- package/util/get-parsers.d.ts +9 -0
- package/util/get-parsers.js +9 -0
- package/util/hex-text.d.ts +13 -21
- package/util/hex-text.js +24 -21
- package/util/local-date.d.ts +2 -41
- package/util/local-date.js +39 -41
- package/util/parse-array.d.ts +8 -0
- package/util/parse-array.js +8 -0
- package/util/parse-bytea.d.ts +15 -0
- package/util/parse-bytea.js +15 -0
- package/util/parse-datetime.d.ts +26 -0
- package/util/parse-datetime.js +26 -0
- package/util/parse-row.d.ts +23 -2
- package/util/parse-row.js +56 -36
- package/util/parse-time.d.ts +10 -0
- package/util/parse-time.js +10 -0
- package/util/resolve-column-formats.d.ts +1 -0
- package/util/row-decoder.d.ts +32 -0
- package/util/row-decoder.js +22 -0
- package/util/stringify-arrayliteral.d.ts +33 -0
- package/util/stringify-arrayliteral.js +220 -20
- package/util/stringify-for-sql.d.ts +17 -0
- package/util/stringify-for-sql.js +17 -0
- package/util/wrap-row-description.d.ts +10 -0
- package/util/wrap-row-description.js +10 -0
- package/CHANGELOG.md +0 -1453
package/README.md
CHANGED
|
@@ -62,7 +62,7 @@ PostgreJS is a driver, not a framework, so what you build on top of it stays you
|
|
|
62
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
63
|
<b><a href="https://www.sqbjs.org">SQB</a></b><br>
|
|
64
64
|
<a href="https://www.npmjs.com/package/@sqb/postgres"><code>@sqb/postgres</code></a><br>
|
|
65
|
-
<sub>
|
|
65
|
+
<sub>first-party adapter</sub>
|
|
66
66
|
</td>
|
|
67
67
|
<td align="center" width="230" valign="top">
|
|
68
68
|
<a href="https://kysely.dev"><img src="https://www.postgrejs.com/img/kysely-logo.svg" alt="Kysely" height="60"></a><br><br>
|
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
import type { OID } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* A parameter with its type named, for the cases where the value cannot
|
|
4
|
+
* say what it is.
|
|
5
|
+
*
|
|
6
|
+
* An ordinary parameter is sent untyped and the server resolves it from
|
|
7
|
+
* where it lands, which is what makes a string work as a `json`, a
|
|
8
|
+
* `uuid` or an enum without being told. This is for when that is not
|
|
9
|
+
* enough: a value with no context to be resolved from (`$1 is null`),
|
|
10
|
+
* or a large numeric array, which keeps the binary encoding only when
|
|
11
|
+
* its type is declared.
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* await connection.query('insert into t (v) values ($1)', {
|
|
15
|
+
* params: [new BindParam(DataTypeOIDs._float8, bigArray)],
|
|
16
|
+
* });
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
2
19
|
export declare class BindParam {
|
|
3
20
|
oid: OID;
|
|
4
21
|
value: any;
|
|
22
|
+
/**
|
|
23
|
+
* @param oid The type to declare for this parameter.
|
|
24
|
+
* @param value The value itself.
|
|
25
|
+
*/
|
|
5
26
|
constructor(oid: OID, value: any);
|
|
6
27
|
}
|
package/connection/bind-param.js
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A parameter with its type named, for the cases where the value cannot
|
|
3
|
+
* say what it is.
|
|
4
|
+
*
|
|
5
|
+
* An ordinary parameter is sent untyped and the server resolves it from
|
|
6
|
+
* where it lands, which is what makes a string work as a `json`, a
|
|
7
|
+
* `uuid` or an enum without being told. This is for when that is not
|
|
8
|
+
* enough: a value with no context to be resolved from (`$1 is null`),
|
|
9
|
+
* or a large numeric array, which keeps the binary encoding only when
|
|
10
|
+
* its type is declared.
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* await connection.query('insert into t (v) values ($1)', {
|
|
14
|
+
* params: [new BindParam(DataTypeOIDs._float8, bigArray)],
|
|
15
|
+
* });
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
1
18
|
export class BindParam {
|
|
2
19
|
oid;
|
|
3
20
|
value;
|
|
21
|
+
/**
|
|
22
|
+
* @param oid The type to declare for this parameter.
|
|
23
|
+
* @param value The value itself.
|
|
24
|
+
*/
|
|
4
25
|
constructor(oid, value) {
|
|
5
26
|
this.oid = oid;
|
|
6
27
|
this.value = value;
|
|
@@ -21,14 +21,48 @@ import { IntlConnection } from './intl-connection.js';
|
|
|
21
21
|
import { LargeObject } from './large-object.js';
|
|
22
22
|
import type { Pool } from './pool.js';
|
|
23
23
|
import { PreparedStatement } from './prepared-statement.js';
|
|
24
|
+
/** One `NOTIFY` as the server delivered it: its channel, payload and sender. */
|
|
24
25
|
export type NotificationMessage = Protocol.NotificationResponseMessage;
|
|
26
|
+
/** What `listen()` calls with each notification on its channel. */
|
|
25
27
|
export type NotificationCallback = (msg: NotificationMessage) => any;
|
|
28
|
+
/**
|
|
29
|
+
* One session on one server.
|
|
30
|
+
*
|
|
31
|
+
* Built either from a configuration object, a connection string, or
|
|
32
|
+
* nothing at all - in which case the environment answers for it, the
|
|
33
|
+
* same variables `psql` reads (`PGHOST`, `PGDATABASE`, `PGUSER`, and the
|
|
34
|
+
* rest). `connect()` opens it and `close()` ends it; a connection taken
|
|
35
|
+
* from a `Pool` returns there instead.
|
|
36
|
+
*
|
|
37
|
+
* ```ts
|
|
38
|
+
* const connection = new Connection('postgres://localhost/mydb');
|
|
39
|
+
* await connection.connect();
|
|
40
|
+
* const result = await connection.query('select * from customers where id = $1', {
|
|
41
|
+
* params: [42],
|
|
42
|
+
* });
|
|
43
|
+
* await connection.close();
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* `await using` closes it at the end of the scope, and every query
|
|
47
|
+
* method accepts an `AbortSignal`.
|
|
48
|
+
*
|
|
49
|
+
* Emits `connecting`, `ready`, `close`, `terminate`, `error`, `notice`
|
|
50
|
+
* and `debug`.
|
|
51
|
+
*/
|
|
26
52
|
export declare class Connection extends SafeEventEmitter implements AsyncDisposable {
|
|
27
53
|
protected _pool?: Pool;
|
|
28
54
|
protected _intlCon: IntlConnection;
|
|
29
55
|
protected _notificationListeners?: SafeEventEmitter;
|
|
30
56
|
protected _closing: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* @param pool The pool this connection belongs to.
|
|
59
|
+
* @param intlCon The internals it is a handle on.
|
|
60
|
+
*/
|
|
31
61
|
constructor(pool: Pool, intlCon: IntlConnection);
|
|
62
|
+
/**
|
|
63
|
+
* @param config How to reach the server - an object, a connection
|
|
64
|
+
* string, or nothing to take it all from the environment.
|
|
65
|
+
*/
|
|
32
66
|
constructor(config?: ConnectionConfiguration | string);
|
|
33
67
|
/**
|
|
34
68
|
* Returns configuration object
|
|
@@ -64,6 +98,12 @@ export declare class Connection extends SafeEventEmitter implements AsyncDisposa
|
|
|
64
98
|
* Returns the secret key of the current session
|
|
65
99
|
*/
|
|
66
100
|
get secretKey(): Maybe<Buffer>;
|
|
101
|
+
/**
|
|
102
|
+
* How many queries this connection is running right now.
|
|
103
|
+
*
|
|
104
|
+
* More than one only when they were pipelined; a connection answers
|
|
105
|
+
* them in order either way.
|
|
106
|
+
*/
|
|
67
107
|
get runningQueryCount(): number;
|
|
68
108
|
/**
|
|
69
109
|
* Connects to the server
|
|
@@ -101,6 +141,30 @@ export declare class Connection extends SafeEventEmitter implements AsyncDisposa
|
|
|
101
141
|
callFunction(functionId: OID, args: Maybe<Buffer>[], options?: FunctionCallOptions & {
|
|
102
142
|
signal?: AbortSignal;
|
|
103
143
|
}): Promise<FunctionCallResult>;
|
|
144
|
+
/**
|
|
145
|
+
* Runs one statement and returns its result.
|
|
146
|
+
*
|
|
147
|
+
* Parameters are sent separately from the SQL - `$1`, `$2` and so on -
|
|
148
|
+
* so nothing has to be escaped into the text. A statement seen a few
|
|
149
|
+
* times is prepared and reused on this connection without being asked
|
|
150
|
+
* for, and `cursor: true` returns a `Cursor` instead of the rows.
|
|
151
|
+
*
|
|
152
|
+
* ```ts
|
|
153
|
+
* const result = await connection.query(
|
|
154
|
+
* 'select id, name from customers where city = $1',
|
|
155
|
+
* { params: ['Berlin'], objectRows: true },
|
|
156
|
+
* );
|
|
157
|
+
* result.rows; // [{ id: 1, name: '...' }, ...]
|
|
158
|
+
* ```
|
|
159
|
+
*
|
|
160
|
+
* A statement built with the `sql` tag carries its own parameters and
|
|
161
|
+
* is passed on its own.
|
|
162
|
+
*
|
|
163
|
+
* @param sql The statement, or one built with the `sql` tag.
|
|
164
|
+
* @param options Parameters, row shape, type mapping, cursor, signal.
|
|
165
|
+
* @returns The rows, the command tag, and what the columns were.
|
|
166
|
+
* @throws DatabaseError When the server refuses the statement.
|
|
167
|
+
*/
|
|
104
168
|
query(sql: string | QueryRequest, options?: QueryOptions): Promise<QueryResult>;
|
|
105
169
|
/**
|
|
106
170
|
* Runs a `COPY ... TO STDOUT` and returns its output as a stream of the
|
|
@@ -233,7 +297,54 @@ export declare class Connection extends SafeEventEmitter implements AsyncDisposa
|
|
|
233
297
|
* @param options Applied to every statement.
|
|
234
298
|
*/
|
|
235
299
|
pipeline(requests: (string | QueryRequest | PipelineRequest)[], options?: QueryOptions): Promise<QueryResult[]>;
|
|
300
|
+
/**
|
|
301
|
+
* Bulk-loads rows into a table over `COPY ... FROM STDIN`, in
|
|
302
|
+
* PostgreSQL's binary format.
|
|
303
|
+
*
|
|
304
|
+
* The fastest way to write many rows: one statement carrying a stream
|
|
305
|
+
* of them, instead of an INSERT or a bind per row. Values are encoded
|
|
306
|
+
* from their JavaScript types against the table's own columns, so
|
|
307
|
+
* nothing has to be formatted by the caller.
|
|
308
|
+
*
|
|
309
|
+
* ```ts
|
|
310
|
+
* await connection.copyFromRows('customers', [
|
|
311
|
+
* [1, 'Ada', new Date()],
|
|
312
|
+
* [2, 'Grace', new Date()],
|
|
313
|
+
* ]);
|
|
314
|
+
* ```
|
|
315
|
+
*
|
|
316
|
+
* `source` can be an array, an iterable, or an async iterable - a
|
|
317
|
+
* stream of rows is never held whole.
|
|
318
|
+
*
|
|
319
|
+
* @param table The destination table, optionally schema-qualified.
|
|
320
|
+
* @param source The rows to load.
|
|
321
|
+
* @param options Which columns, how to encode them, a signal.
|
|
322
|
+
* @returns How many rows the server took.
|
|
323
|
+
* @throws DatabaseError When a row is refused, which ends the copy.
|
|
324
|
+
*/
|
|
236
325
|
copyFromRows(table: string, source: CopyRowSource, options?: CopyFromRowsOptions): Promise<CopyFromRowsResult>;
|
|
326
|
+
/**
|
|
327
|
+
* Opens a `COPY ... FROM STDIN` and hands back the stream to write it
|
|
328
|
+
* into, for a payload the caller formats itself.
|
|
329
|
+
*
|
|
330
|
+
* `copyFromRows()` is the one to reach for when the rows are
|
|
331
|
+
* JavaScript values; this is for bytes already in the format the
|
|
332
|
+
* statement names - CSV a caller produced, or a binary payload from
|
|
333
|
+
* somewhere else.
|
|
334
|
+
*
|
|
335
|
+
* ```ts
|
|
336
|
+
* const stream = await connection.copyFrom(
|
|
337
|
+
* 'copy customers from stdin (format csv)',
|
|
338
|
+
* );
|
|
339
|
+
* stream.write('1,Ada\n');
|
|
340
|
+
* await stream.end();
|
|
341
|
+
* ```
|
|
342
|
+
*
|
|
343
|
+
* @param sql The `COPY ... FROM STDIN` statement.
|
|
344
|
+
* @returns A writable stream; `end()` completes the copy and resolves
|
|
345
|
+
* with what the server took.
|
|
346
|
+
* @throws DatabaseError When the statement itself is refused.
|
|
347
|
+
*/
|
|
237
348
|
copyFrom(sql: string): Promise<CopyFromStream>;
|
|
238
349
|
/**
|
|
239
350
|
* Creates a PreparedStatement instance
|
|
@@ -368,8 +479,33 @@ export declare class Connection extends SafeEventEmitter implements AsyncDisposa
|
|
|
368
479
|
* releaseSavepoint().
|
|
369
480
|
*/
|
|
370
481
|
releaseSavepoint(name: string, immediate?: boolean): Promise<void>;
|
|
482
|
+
/**
|
|
483
|
+
* Subscribes to a `NOTIFY` channel, sending `LISTEN` the first time
|
|
484
|
+
* this connection hears of it.
|
|
485
|
+
*
|
|
486
|
+
* Several callbacks can share a channel; only the first costs a round
|
|
487
|
+
* trip. The channel name is quoted for the server, so it may be
|
|
488
|
+
* anything a string can hold.
|
|
489
|
+
*
|
|
490
|
+
* ```ts
|
|
491
|
+
* await connection.listen('order_placed', msg => {
|
|
492
|
+
* console.log(msg.payload);
|
|
493
|
+
* });
|
|
494
|
+
* ```
|
|
495
|
+
*
|
|
496
|
+
* @param channel The channel to subscribe to.
|
|
497
|
+
* @param callback Called with each notification on it.
|
|
498
|
+
*/
|
|
371
499
|
listen(channel: string, callback: NotificationCallback): Promise<void>;
|
|
500
|
+
/**
|
|
501
|
+
* Drops every callback on one channel and sends `UNLISTEN` for it.
|
|
502
|
+
*
|
|
503
|
+
* Does nothing when the channel was never listened to.
|
|
504
|
+
*
|
|
505
|
+
* @param channel The channel to unsubscribe from.
|
|
506
|
+
*/
|
|
372
507
|
unListen(channel: string): Promise<void>;
|
|
508
|
+
/** Drops every callback on every channel, with one `UNLISTEN *`. */
|
|
373
509
|
unListenAll(): Promise<void>;
|
|
374
510
|
/**
|
|
375
511
|
* Whether a statement asked for the wire to itself - `pipeline: false`
|
package/connection/connection.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { updateErrorMessage } from '@jsopen/objects';
|
|
1
2
|
import { ConnectionState, DataTypeOIDs } from '../constants.js';
|
|
2
3
|
import { SafeEventEmitter } from '../safe-event-emitter.js';
|
|
3
4
|
import { withAbortSignal } from '../util/abort-signal.js';
|
|
@@ -12,6 +13,30 @@ import { PreparedStatement } from './prepared-statement.js';
|
|
|
12
13
|
const CAPTURE_STACK_TRACE_LIMIT = 5;
|
|
13
14
|
/** Names the savepoint a nested transaction() scope takes. */
|
|
14
15
|
let transactionScopeCounter = 0;
|
|
16
|
+
/**
|
|
17
|
+
* One session on one server.
|
|
18
|
+
*
|
|
19
|
+
* Built either from a configuration object, a connection string, or
|
|
20
|
+
* nothing at all - in which case the environment answers for it, the
|
|
21
|
+
* same variables `psql` reads (`PGHOST`, `PGDATABASE`, `PGUSER`, and the
|
|
22
|
+
* rest). `connect()` opens it and `close()` ends it; a connection taken
|
|
23
|
+
* from a `Pool` returns there instead.
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* const connection = new Connection('postgres://localhost/mydb');
|
|
27
|
+
* await connection.connect();
|
|
28
|
+
* const result = await connection.query('select * from customers where id = $1', {
|
|
29
|
+
* params: [42],
|
|
30
|
+
* });
|
|
31
|
+
* await connection.close();
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* `await using` closes it at the end of the scope, and every query
|
|
35
|
+
* method accepts an `AbortSignal`.
|
|
36
|
+
*
|
|
37
|
+
* Emits `connecting`, `ready`, `close`, `terminate`, `error`, `notice`
|
|
38
|
+
* and `debug`.
|
|
39
|
+
*/
|
|
15
40
|
export class Connection extends SafeEventEmitter {
|
|
16
41
|
_pool;
|
|
17
42
|
_intlCon;
|
|
@@ -78,6 +103,12 @@ export class Connection extends SafeEventEmitter {
|
|
|
78
103
|
get secretKey() {
|
|
79
104
|
return this._intlCon.secretKey;
|
|
80
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* How many queries this connection is running right now.
|
|
108
|
+
*
|
|
109
|
+
* More than one only when they were pipelined; a connection answers
|
|
110
|
+
* them in order either way.
|
|
111
|
+
*/
|
|
81
112
|
get runningQueryCount() {
|
|
82
113
|
return this._intlCon.runningQueryCount;
|
|
83
114
|
}
|
|
@@ -187,6 +218,30 @@ export class Connection extends SafeEventEmitter {
|
|
|
187
218
|
callFunction(functionId, args, options) {
|
|
188
219
|
return withAbortSignal(options?.signal, () => this._intlCon.cancel(), () => this._captureErrorStack(this._intlCon.callFunction(functionId, args, options), this.callFunction));
|
|
189
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* Runs one statement and returns its result.
|
|
223
|
+
*
|
|
224
|
+
* Parameters are sent separately from the SQL - `$1`, `$2` and so on -
|
|
225
|
+
* so nothing has to be escaped into the text. A statement seen a few
|
|
226
|
+
* times is prepared and reused on this connection without being asked
|
|
227
|
+
* for, and `cursor: true` returns a `Cursor` instead of the rows.
|
|
228
|
+
*
|
|
229
|
+
* ```ts
|
|
230
|
+
* const result = await connection.query(
|
|
231
|
+
* 'select id, name from customers where city = $1',
|
|
232
|
+
* { params: ['Berlin'], objectRows: true },
|
|
233
|
+
* );
|
|
234
|
+
* result.rows; // [{ id: 1, name: '...' }, ...]
|
|
235
|
+
* ```
|
|
236
|
+
*
|
|
237
|
+
* A statement built with the `sql` tag carries its own parameters and
|
|
238
|
+
* is passed on its own.
|
|
239
|
+
*
|
|
240
|
+
* @param sql The statement, or one built with the `sql` tag.
|
|
241
|
+
* @param options Parameters, row shape, type mapping, cursor, signal.
|
|
242
|
+
* @returns The rows, the command tag, and what the columns were.
|
|
243
|
+
* @throws DatabaseError When the server refuses the statement.
|
|
244
|
+
*/
|
|
190
245
|
async query(sql, options) {
|
|
191
246
|
if (sql instanceof QueryRequest) {
|
|
192
247
|
if (options?.params)
|
|
@@ -389,6 +444,31 @@ export class Connection extends SafeEventEmitter {
|
|
|
389
444
|
throw this._handleError(e, i != null && normalized[i] ? normalized[i].sql : normalized[0].sql);
|
|
390
445
|
});
|
|
391
446
|
}
|
|
447
|
+
/**
|
|
448
|
+
* Bulk-loads rows into a table over `COPY ... FROM STDIN`, in
|
|
449
|
+
* PostgreSQL's binary format.
|
|
450
|
+
*
|
|
451
|
+
* The fastest way to write many rows: one statement carrying a stream
|
|
452
|
+
* of them, instead of an INSERT or a bind per row. Values are encoded
|
|
453
|
+
* from their JavaScript types against the table's own columns, so
|
|
454
|
+
* nothing has to be formatted by the caller.
|
|
455
|
+
*
|
|
456
|
+
* ```ts
|
|
457
|
+
* await connection.copyFromRows('customers', [
|
|
458
|
+
* [1, 'Ada', new Date()],
|
|
459
|
+
* [2, 'Grace', new Date()],
|
|
460
|
+
* ]);
|
|
461
|
+
* ```
|
|
462
|
+
*
|
|
463
|
+
* `source` can be an array, an iterable, or an async iterable - a
|
|
464
|
+
* stream of rows is never held whole.
|
|
465
|
+
*
|
|
466
|
+
* @param table The destination table, optionally schema-qualified.
|
|
467
|
+
* @param source The rows to load.
|
|
468
|
+
* @param options Which columns, how to encode them, a signal.
|
|
469
|
+
* @returns How many rows the server took.
|
|
470
|
+
* @throws DatabaseError When a row is refused, which ends the copy.
|
|
471
|
+
*/
|
|
392
472
|
async copyFromRows(table, source, options) {
|
|
393
473
|
/* c8 ignore start */
|
|
394
474
|
if (this.listenerCount('debug')) {
|
|
@@ -404,6 +484,28 @@ export class Connection extends SafeEventEmitter {
|
|
|
404
484
|
throw this._handleError(e, `COPY ${table} FROM STDIN (FORMAT binary)`);
|
|
405
485
|
});
|
|
406
486
|
}
|
|
487
|
+
/**
|
|
488
|
+
* Opens a `COPY ... FROM STDIN` and hands back the stream to write it
|
|
489
|
+
* into, for a payload the caller formats itself.
|
|
490
|
+
*
|
|
491
|
+
* `copyFromRows()` is the one to reach for when the rows are
|
|
492
|
+
* JavaScript values; this is for bytes already in the format the
|
|
493
|
+
* statement names - CSV a caller produced, or a binary payload from
|
|
494
|
+
* somewhere else.
|
|
495
|
+
*
|
|
496
|
+
* ```ts
|
|
497
|
+
* const stream = await connection.copyFrom(
|
|
498
|
+
* 'copy customers from stdin (format csv)',
|
|
499
|
+
* );
|
|
500
|
+
* stream.write('1,Ada\n');
|
|
501
|
+
* await stream.end();
|
|
502
|
+
* ```
|
|
503
|
+
*
|
|
504
|
+
* @param sql The `COPY ... FROM STDIN` statement.
|
|
505
|
+
* @returns A writable stream; `end()` completes the copy and resolves
|
|
506
|
+
* with what the server took.
|
|
507
|
+
* @throws DatabaseError When the statement itself is refused.
|
|
508
|
+
*/
|
|
407
509
|
async copyFrom(sql) {
|
|
408
510
|
/* c8 ignore start */
|
|
409
511
|
if (this.listenerCount('debug')) {
|
|
@@ -625,22 +727,45 @@ export class Connection extends SafeEventEmitter {
|
|
|
625
727
|
releaseSavepoint(name, immediate) {
|
|
626
728
|
return this._captureErrorStack(this._intlCon.releaseSavepoint(name, immediate));
|
|
627
729
|
}
|
|
730
|
+
/**
|
|
731
|
+
* Subscribes to a `NOTIFY` channel, sending `LISTEN` the first time
|
|
732
|
+
* this connection hears of it.
|
|
733
|
+
*
|
|
734
|
+
* Several callbacks can share a channel; only the first costs a round
|
|
735
|
+
* trip. The channel name is quoted for the server, so it may be
|
|
736
|
+
* anything a string can hold.
|
|
737
|
+
*
|
|
738
|
+
* ```ts
|
|
739
|
+
* await connection.listen('order_placed', msg => {
|
|
740
|
+
* console.log(msg.payload);
|
|
741
|
+
* });
|
|
742
|
+
* ```
|
|
743
|
+
*
|
|
744
|
+
* @param channel The channel to subscribe to.
|
|
745
|
+
* @param callback Called with each notification on it.
|
|
746
|
+
*/
|
|
747
|
+
/* This used to test whether ANY channel had a listener rather than
|
|
748
|
+
this one, so a second channel added after the first never had its
|
|
749
|
+
own LISTEN sent and never received anything - verified live, only
|
|
750
|
+
the first channel ever appeared in pg_stat_activity's query text. */
|
|
628
751
|
async listen(channel, callback) {
|
|
629
752
|
channel = normalizeChannelName(channel);
|
|
630
753
|
if (!this._notificationListeners) {
|
|
631
754
|
this._notificationListeners = new SafeEventEmitter();
|
|
632
755
|
this._intlCon.on('notification', (msg) => this._handleNotification(msg));
|
|
633
756
|
}
|
|
634
|
-
// Bug: this used to check whether ANY channel already had a listener,
|
|
635
|
-
// not this one specifically - so a second, different channel added
|
|
636
|
-
// after the first never got its own LISTEN sent at all, and never
|
|
637
|
-
// received a notification for it (verified live: only the first
|
|
638
|
-
// channel ever showed up in pg_stat_activity's query text).
|
|
639
757
|
const alreadyListening = !!this._notificationListeners.listenerCount(channel);
|
|
640
758
|
this._notificationListeners.on(channel, callback);
|
|
641
759
|
if (!alreadyListening)
|
|
642
760
|
await this._captureErrorStack(this.query('LISTEN ' + escapeIdentifier(channel)));
|
|
643
761
|
}
|
|
762
|
+
/**
|
|
763
|
+
* Drops every callback on one channel and sends `UNLISTEN` for it.
|
|
764
|
+
*
|
|
765
|
+
* Does nothing when the channel was never listened to.
|
|
766
|
+
*
|
|
767
|
+
* @param channel The channel to unsubscribe from.
|
|
768
|
+
*/
|
|
644
769
|
async unListen(channel) {
|
|
645
770
|
channel = normalizeChannelName(channel);
|
|
646
771
|
if (this._notificationListeners?.listenerCount(channel)) {
|
|
@@ -648,6 +773,7 @@ export class Connection extends SafeEventEmitter {
|
|
|
648
773
|
await this._captureErrorStack(this.query('UNLISTEN ' + escapeIdentifier(channel)));
|
|
649
774
|
}
|
|
650
775
|
}
|
|
776
|
+
/** Drops every callback on every channel, with one `UNLISTEN *`. */
|
|
651
777
|
async unListenAll() {
|
|
652
778
|
if (this._notificationListeners?.eventNames().length) {
|
|
653
779
|
this._notificationListeners.removeAllListeners();
|
|
@@ -780,6 +906,7 @@ export class Connection extends SafeEventEmitter {
|
|
|
780
906
|
err.message += `\n${String(err.lineNr - 1).padStart(3)}| ${lines[err.lineNr - 2]}`;
|
|
781
907
|
err.message += `\n${String(err.lineNr).padStart(3)}| ${err.line}\n .${'-'.repeat(Math.max(err.colNr - 1, 0))}^`;
|
|
782
908
|
}
|
|
909
|
+
updateErrorMessage(err, err.message);
|
|
783
910
|
return err;
|
|
784
911
|
}
|
|
785
912
|
/**
|
|
@@ -27,6 +27,7 @@ export declare class CopyToStream extends Readable {
|
|
|
27
27
|
protected _discarding: boolean;
|
|
28
28
|
protected _settled: boolean;
|
|
29
29
|
protected _paused: boolean;
|
|
30
|
+
/** @param socket The socket the copy is running on. */
|
|
30
31
|
constructor(socket: PgSocket);
|
|
31
32
|
/**
|
|
32
33
|
* Handles the copy's backend messages. Passed straight to
|
|
@@ -68,6 +69,7 @@ export declare class CopyFromStream extends Writable {
|
|
|
68
69
|
protected _completed?: (err?: Error) => void;
|
|
69
70
|
protected _copyEnded: boolean;
|
|
70
71
|
protected _settled: boolean;
|
|
72
|
+
/** @param socket The socket the copy is running on. */
|
|
71
73
|
constructor(socket: PgSocket);
|
|
72
74
|
/**
|
|
73
75
|
* Handles the copy's backend messages. Passed straight to
|
|
@@ -27,6 +27,7 @@ export class CopyToStream extends Readable {
|
|
|
27
27
|
_discarding = false;
|
|
28
28
|
_settled = false;
|
|
29
29
|
_paused = false;
|
|
30
|
+
/** @param socket The socket the copy is running on. */
|
|
30
31
|
constructor(socket) {
|
|
31
32
|
super();
|
|
32
33
|
this._socket = socket;
|
|
@@ -148,6 +149,7 @@ export class CopyFromStream extends Writable {
|
|
|
148
149
|
_completed;
|
|
149
150
|
_copyEnded = false;
|
|
150
151
|
_settled = false;
|
|
152
|
+
/** @param socket The socket the copy is running on. */
|
|
151
153
|
constructor(socket) {
|
|
152
154
|
super();
|
|
153
155
|
this._socket = socket;
|
package/connection/cursor.d.ts
CHANGED
|
@@ -4,6 +4,32 @@ import { SafeEventEmitter } from '../safe-event-emitter.js';
|
|
|
4
4
|
import type { AnyParseFunction, Maybe, Row } from '../types.js';
|
|
5
5
|
import type { Portal } from './portal.js';
|
|
6
6
|
import type { PreparedStatement } from './prepared-statement.js';
|
|
7
|
+
/**
|
|
8
|
+
* A result read a batch at a time instead of all at once.
|
|
9
|
+
*
|
|
10
|
+
* Returned by `Connection.query()`/`PreparedStatement.execute()` when
|
|
11
|
+
* `cursor: true` is passed, and backed by a server-side portal: rows are
|
|
12
|
+
* fetched `fetchCount` at a time (100 by default) as they are asked for,
|
|
13
|
+
* so a result larger than memory can be read through without ever
|
|
14
|
+
* holding it.
|
|
15
|
+
*
|
|
16
|
+
* The cursor closes itself when the rows run out, and `for await`
|
|
17
|
+
* closes it however the loop ends. Anything else - breaking out of a
|
|
18
|
+
* manual `next()` loop, an error in the middle - wants `close()`, or
|
|
19
|
+
* `await using`, which calls it.
|
|
20
|
+
*
|
|
21
|
+
* ```ts
|
|
22
|
+
* const result = await connection.query('select * from big_table', {
|
|
23
|
+
* cursor: true,
|
|
24
|
+
* fetchCount: 500,
|
|
25
|
+
* });
|
|
26
|
+
* for await (const row of result.cursor!) {
|
|
27
|
+
* // one row at a time; 500 arrive per round trip
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* Emits `fetch` with each batch as it arrives, and `close` once.
|
|
32
|
+
*/
|
|
7
33
|
export declare class Cursor extends SafeEventEmitter implements AsyncDisposable {
|
|
8
34
|
private readonly _statement;
|
|
9
35
|
private readonly _portal;
|
|
@@ -13,21 +39,57 @@ export declare class Cursor extends SafeEventEmitter implements AsyncDisposable
|
|
|
13
39
|
private _taskQueue;
|
|
14
40
|
private _rows;
|
|
15
41
|
private _closed;
|
|
42
|
+
/** What the columns of every row this cursor returns are. */
|
|
16
43
|
readonly fields: FieldInfo[];
|
|
17
44
|
constructor(statement: PreparedStatement, portal: Portal, fields: FieldInfo[], parsers: AnyParseFunction[], queryOptions: QueryOptions);
|
|
45
|
+
/**
|
|
46
|
+
* The shape of the rows this cursor hands back - `'array'`,
|
|
47
|
+
* `'object'`, or `'custom'` when a `RowDecoder` of the caller's own is
|
|
48
|
+
* producing them.
|
|
49
|
+
*/
|
|
18
50
|
get rowType(): 'array' | 'object' | 'custom';
|
|
51
|
+
/**
|
|
52
|
+
* Whether the cursor is finished: the rows ran out, `close()` was
|
|
53
|
+
* called, or the portal was lost.
|
|
54
|
+
*/
|
|
19
55
|
get isClosed(): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* The next row, or `undefined` once there are none left.
|
|
58
|
+
*
|
|
59
|
+
* Fetches a batch from the server when the current one is used up, and
|
|
60
|
+
* closes the cursor when the server answers with nothing.
|
|
61
|
+
*
|
|
62
|
+
* @returns The next row, or `undefined` at the end.
|
|
63
|
+
*/
|
|
20
64
|
next(): Promise<Maybe<Row>>;
|
|
65
|
+
/**
|
|
66
|
+
* Up to `nRows` rows, fetching as many batches as it takes.
|
|
67
|
+
*
|
|
68
|
+
* Shorter than asked for only at the end of the result, and empty once
|
|
69
|
+
* the cursor is closed - which is how the end is told apart from a
|
|
70
|
+
* batch boundary.
|
|
71
|
+
*
|
|
72
|
+
* @param nRows How many rows to read at most.
|
|
73
|
+
* @returns The rows read, in order.
|
|
74
|
+
*/
|
|
21
75
|
fetch(nRows: number): Promise<Row[]>;
|
|
76
|
+
/**
|
|
77
|
+
* Closes the cursor and releases the portal behind it.
|
|
78
|
+
*
|
|
79
|
+
* Idempotent, and called automatically when the rows run out or a
|
|
80
|
+
* `for await` loop ends. Emits `close`.
|
|
81
|
+
*/
|
|
22
82
|
close(): Promise<void>;
|
|
83
|
+
/** Reads one batch from the portal and queues it up for the callers. */
|
|
23
84
|
private _fetchRows;
|
|
24
85
|
/**
|
|
25
|
-
* Iterates the remaining rows,
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
86
|
+
* Iterates the remaining rows, a batch at a time, and closes the cursor
|
|
87
|
+
* when the loop ends - whether it ran out of rows, broke early, or the
|
|
88
|
+
* body threw.
|
|
89
|
+
*
|
|
90
|
+
* @returns An iterator over the rows left to read.
|
|
30
91
|
*/
|
|
31
92
|
[Symbol.asyncIterator](): AsyncIterableIterator<Row>;
|
|
93
|
+
/** Closes the cursor, so `await using` can own one. */
|
|
32
94
|
[Symbol.asyncDispose](): Promise<void>;
|
|
33
95
|
}
|