postgrejs 2.23.1 → 3.0.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/CHANGELOG.md +171 -1
- package/LICENSE +26 -17
- package/README.md +195 -175
- package/connection/connection.d.ts +169 -16
- package/connection/connection.js +318 -56
- package/connection/copy-stream.d.ts +88 -0
- package/connection/copy-stream.js +244 -0
- package/connection/cursor.js +20 -13
- package/connection/intl-connection.d.ts +113 -5
- package/connection/intl-connection.js +500 -70
- package/connection/large-object.d.ts +65 -0
- package/connection/large-object.js +151 -0
- package/connection/logical-replication.d.ts +121 -0
- package/connection/logical-replication.js +279 -0
- package/connection/pool.d.ts +61 -4
- package/connection/pool.js +177 -29
- package/connection/portal.d.ts +18 -4
- package/connection/portal.js +53 -59
- package/connection/prepared-statement.d.ts +22 -1
- package/connection/prepared-statement.js +129 -109
- package/data-type-map.js +4 -2
- package/data-types/bool-type.js +14 -10
- package/data-types/box-type.js +15 -8
- package/data-types/bytea-type.js +9 -5
- package/data-types/char-type.js +11 -5
- package/data-types/circle-type.js +15 -7
- package/data-types/date-type.js +25 -19
- package/data-types/float4-type.js +10 -3
- package/data-types/float8-type.js +12 -3
- package/data-types/int2-type.js +9 -4
- package/data-types/int2-vector-type.js +9 -4
- package/data-types/int4-type.js +11 -5
- package/data-types/int8-type.js +22 -7
- package/data-types/json-type.js +17 -8
- package/data-types/jsonb-type.js +20 -14
- package/data-types/lseg-type.js +16 -8
- package/data-types/numeric-type.d.ts +8 -0
- package/data-types/numeric-type.js +118 -9
- package/data-types/oid-type.d.ts +0 -1
- package/data-types/oid-type.js +9 -10
- package/data-types/oid-vector-type.d.ts +9 -0
- package/data-types/oid-vector-type.js +51 -0
- package/data-types/point-type.js +14 -6
- package/data-types/time-type.js +20 -13
- package/data-types/timestamp-type.js +32 -25
- package/data-types/timestamptz-type.js +33 -21
- package/data-types/uuid-type.js +21 -11
- package/data-types/varchar-type.js +16 -4
- package/index.d.ts +5 -0
- package/index.js +5 -0
- package/interfaces/command-result.d.ts +2 -1
- package/interfaces/data-type.d.ts +5 -3
- package/interfaces/database-connection-params.d.ts +108 -0
- package/interfaces/query-options.d.ts +23 -0
- package/interfaces/script-execute-options.d.ts +23 -0
- package/interfaces/script-result.d.ts +3 -2
- package/package.json +2 -3
- package/protocol/backend.d.ts +6 -1
- package/protocol/backend.js +70 -45
- package/protocol/buffer-reader.d.ts +0 -2
- package/protocol/buffer-reader.js +3 -10
- package/protocol/cert-signature.d.ts +12 -0
- package/protocol/cert-signature.js +114 -0
- package/protocol/frontend.d.ts +16 -0
- package/protocol/frontend.js +70 -11
- package/protocol/pg-socket.d.ts +220 -9
- package/protocol/pg-socket.js +539 -102
- package/protocol/pgoutput.d.ts +76 -0
- package/protocol/pgoutput.js +155 -0
- package/protocol/protocol.d.ts +3 -4
- package/protocol/protocol.js +1 -1
- package/protocol/sasl.d.ts +11 -1
- package/protocol/sasl.js +36 -5
- package/protocol/smart-buffer.d.ts +0 -2
- package/protocol/smart-buffer.js +11 -16
- package/types.d.ts +5 -3
- package/util/abort-signal.d.ts +34 -0
- package/util/abort-signal.js +76 -0
- package/util/array-calculatedim.js +3 -1
- package/util/connection-config.js +77 -3
- package/util/decode-binaryarray.d.ts +1 -1
- package/util/decode-binaryarray.js +15 -6
- package/util/encode-binaryarray.js +7 -3
- package/util/escape-identifier.d.ts +14 -0
- package/util/escape-identifier.js +32 -0
- package/util/escape-literal.js +3 -0
- package/util/fast-parseint.d.ts +1 -0
- package/util/fast-parseint.js +12 -17
- package/util/format-datetime.d.ts +10 -0
- package/util/format-datetime.js +71 -0
- package/util/get-parsers.js +31 -10
- package/util/parse-array.js +2 -2
- package/util/parse-bytea.d.ts +2 -0
- package/util/parse-bytea.js +83 -0
- package/util/parse-datetime.d.ts +3 -1
- package/util/parse-datetime.js +86 -17
- package/util/parse-row.d.ts +3 -1
- package/util/parse-row.js +60 -5
- package/util/parse-time.js +8 -1
- package/util/sql-tag.d.ts +60 -0
- package/util/sql-tag.js +202 -0
- package/util/starts-transaction.d.ts +38 -0
- package/util/starts-transaction.js +148 -0
- package/util/stringify-arrayliteral.js +13 -1
- package/util/wrap-row-description.js +13 -4
- package/util/convert-row-to-object.d.ts +0 -2
- package/util/convert-row-to-object.js +0 -9
package/protocol/pg-socket.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import net from 'node:net';
|
|
2
|
+
import tls from 'node:tls';
|
|
1
3
|
import { ConnectionState } from '../constants.js';
|
|
2
4
|
import type { ConnectionConfiguration } from '../interfaces/database-connection-params.js';
|
|
3
5
|
import { SafeEventEmitter } from '../safe-event-emitter.js';
|
|
@@ -18,33 +20,242 @@ export declare class PgSocket extends SafeEventEmitter {
|
|
|
18
20
|
private _saslSession?;
|
|
19
21
|
private _processID?;
|
|
20
22
|
private _secretKey?;
|
|
23
|
+
private _captureQueue;
|
|
24
|
+
private _pendingWrites;
|
|
25
|
+
private _flushScheduled;
|
|
26
|
+
private _hosts;
|
|
27
|
+
private _hostIndex;
|
|
28
|
+
private _sessionAttrsChecked;
|
|
29
|
+
private _standbyState?;
|
|
21
30
|
constructor(options: ConnectionConfiguration);
|
|
22
31
|
get state(): ConnectionState;
|
|
23
32
|
get processID(): Maybe<number>;
|
|
24
33
|
get secretKey(): Maybe<number>;
|
|
25
34
|
get sessionParameters(): Record<string, string>;
|
|
26
35
|
connect(): void;
|
|
36
|
+
protected _connectToHost(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Negotiates TLS on an already TCP-connected `socket`, if configured -
|
|
39
|
+
* shared between the long-lived connection above (_connectToHost) and
|
|
40
|
+
* cancel() below, which needs the exact same host/TLS handling for its
|
|
41
|
+
* own short-lived socket, just without ever sending a StartupMessage
|
|
42
|
+
* afterwards. Resolves `onReady` with whichever socket ends up ready to
|
|
43
|
+
* speak the PostgreSQL protocol: the plain one, or its TLS upgrade.
|
|
44
|
+
*/
|
|
45
|
+
protected _negotiateTls(socket: net.Socket, target: {
|
|
46
|
+
host: string;
|
|
47
|
+
port?: number;
|
|
48
|
+
}, onReady: (socket: net.Socket | tls.TLSSocket) => void, onError: (err: Error) => void): void;
|
|
49
|
+
/**
|
|
50
|
+
* Asks the server to cancel whatever this session is currently running.
|
|
51
|
+
*
|
|
52
|
+
* Opens its own short-lived connection and closes it again: a backend busy
|
|
53
|
+
* with a query is not reading its own socket, so the request cannot travel
|
|
54
|
+
* down the connection it is meant to interrupt. The server answers nothing
|
|
55
|
+
* - it either finds a matching session and signals it or does not - so
|
|
56
|
+
* this resolves once the bytes are out, and the cancelled query reports
|
|
57
|
+
* the outcome itself, as an ordinary error on its own connection.
|
|
58
|
+
*
|
|
59
|
+
* No StartupMessage or authentication is ever sent here - the
|
|
60
|
+
* CancelRequest is the only message this socket carries, and it is
|
|
61
|
+
* self-authorized by the processID/secretKey pair BackendKeyData handed
|
|
62
|
+
* out to the session being cancelled, not by a separate login. TLS is
|
|
63
|
+
* still negotiated via _negotiateTls() when configured, because a
|
|
64
|
+
* `hostssl` pg_hba.conf rule can reject a plaintext connection outright
|
|
65
|
+
* before the server ever reads what request it carries - and the target
|
|
66
|
+
* is `_hosts[_hostIndex]`, the host this session actually ended up
|
|
67
|
+
* connected to, not `options.host`, which after a multi-host failover may
|
|
68
|
+
* name a candidate this session never used.
|
|
69
|
+
*/
|
|
70
|
+
cancel(): Promise<void>;
|
|
27
71
|
close(): void;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
72
|
+
sendExecuteMessage(args: Frontend.ExecuteMessageArgs, cb: CaptureCallback): Promise<any>;
|
|
73
|
+
sendCloseMessage(args: Frontend.CloseMessageArgs, cb: CaptureCallback): Promise<any>;
|
|
74
|
+
/**
|
|
75
|
+
* Sends Parse+Bind+Describe+Execute+Sync as a single write with a single
|
|
76
|
+
* FIFO capture entry, instead of 5 separate sendXMessage() round trips -
|
|
77
|
+
* the one-shot Extended Query fast path (IntlConnection.queryOnce()).
|
|
78
|
+
* Callers pass unnamed statement/portal (omit statement/portal/name) so
|
|
79
|
+
* no Close message is needed at all: PostgreSQL auto-clears an unnamed
|
|
80
|
+
* statement/portal at the next Parse/Bind referencing the unnamed name.
|
|
81
|
+
*/
|
|
82
|
+
sendExtendedQueryMessages(args: {
|
|
83
|
+
parse: Frontend.ParseMessageArgs;
|
|
84
|
+
bind: Frontend.BindMessageArgs;
|
|
85
|
+
describe: Frontend.DescribeMessageArgs;
|
|
86
|
+
execute: Frontend.ExecuteMessageArgs;
|
|
87
|
+
}, cb: CaptureCallback): Promise<any>;
|
|
88
|
+
/**
|
|
89
|
+
* Parse + Describe(statement) + Sync as a single round trip - used by
|
|
90
|
+
* PreparedStatement.prepare() instead of a separate awaited Parse then a
|
|
91
|
+
* separate awaited Sync, and fetches the RowDescription/NoData in the
|
|
92
|
+
* same round trip so PreparedStatement can cache it instead of every
|
|
93
|
+
* later execute() re-Describing its own portal.
|
|
94
|
+
*/
|
|
95
|
+
sendPrepareMessages(args: {
|
|
96
|
+
parse: Frontend.ParseMessageArgs;
|
|
97
|
+
describe: Frontend.DescribeMessageArgs;
|
|
98
|
+
}, cb: CaptureCallback): Promise<any>;
|
|
99
|
+
/**
|
|
100
|
+
* Bind + Execute + Sync as a single round trip, against an UNNAMED
|
|
101
|
+
* portal (args.bind.portal/args.execute.portal left unset) - used by
|
|
102
|
+
* PreparedStatement._execute() to reuse an already-prepared (named)
|
|
103
|
+
* statement without the per-call Describe/Close that Portal's own
|
|
104
|
+
* bind()/retrieveFields()/execute()/close() sequence needs for a
|
|
105
|
+
* freshly-created named portal. No Close message is needed: PostgreSQL
|
|
106
|
+
* auto-clears an unnamed portal at the next Bind naming it.
|
|
107
|
+
*/
|
|
108
|
+
sendBindExecuteMessages(args: {
|
|
109
|
+
bind: Frontend.BindMessageArgs;
|
|
110
|
+
execute: Frontend.ExecuteMessageArgs;
|
|
111
|
+
}, cb: CaptureCallback): Promise<any>;
|
|
112
|
+
/**
|
|
113
|
+
* Bind + Describe(portal) + Flush as a single round trip (NOT Sync - see
|
|
114
|
+
* Portal.bindAndRetrieveFields()'s doc comment for why a Sync here would
|
|
115
|
+
* be unsafe: it would commit an implicit/autocommit transaction and
|
|
116
|
+
* destroy the just-bound named portal before any fetch() could use it).
|
|
117
|
+
* Used by PreparedStatement._execute()'s cursor branch instead of two
|
|
118
|
+
* separately-awaited Portal.bind()/retrieveFields() round trips.
|
|
119
|
+
*/
|
|
120
|
+
sendBindDescribeMessages(args: {
|
|
121
|
+
bind: Frontend.BindMessageArgs;
|
|
122
|
+
describe: Frontend.DescribeMessageArgs;
|
|
123
|
+
}, cb: CaptureCallback): Promise<any>;
|
|
124
|
+
/**
|
|
125
|
+
* Close + Sync under ONE capture, rather than a Close capture followed by
|
|
126
|
+
* a separate Sync capture. That split is unsafe after an ErrorResponse:
|
|
127
|
+
* the server then skips every message until Sync, so the only reply is
|
|
128
|
+
* the Sync's ReadyForQuery - which the FIFO hands to the *Close* capture
|
|
129
|
+
* (the older entry), making it fail with "unexpected response message
|
|
130
|
+
* (Z)" and leaving the Sync capture orphaned, to silently swallow the
|
|
131
|
+
* first message of whatever request comes next. With one capture,
|
|
132
|
+
* ReadyForQuery is simply this request's end marker whether or not the
|
|
133
|
+
* Close itself was honoured.
|
|
134
|
+
*/
|
|
135
|
+
sendCloseAndSyncMessages(args: Frontend.CloseMessageArgs, cb: CaptureCallback): Promise<any>;
|
|
136
|
+
/**
|
|
137
|
+
* Close(portal) + Close(statement) + Sync as a single round trip - used
|
|
138
|
+
* by PreparedStatement._maybeCloseWithPortal() when a Cursor's close()
|
|
139
|
+
* brings the owning PreparedStatement's refcount to 0, instead of two
|
|
140
|
+
* separately-batched Close+Sync round trips (Portal.close() then
|
|
141
|
+
* PreparedStatement._close()). Sync here is safe/intended: this is final
|
|
142
|
+
* teardown, no portal needs to survive past it.
|
|
143
|
+
*/
|
|
144
|
+
sendClosePortalAndStatementMessages(args: {
|
|
145
|
+
portal: Frontend.CloseMessageArgs;
|
|
146
|
+
statement: Frontend.CloseMessageArgs;
|
|
147
|
+
}, cb: CaptureCallback): Promise<any>;
|
|
148
|
+
sendQueryMessage(sql: string, cb: CaptureCallback): Promise<any>;
|
|
149
|
+
/**
|
|
150
|
+
* COPY IN data. Unlike every other send*() here this pushes nothing onto
|
|
151
|
+
* the capture queue: while a COPY is in progress the server answers no
|
|
152
|
+
* individual CopyData message, so the response still belongs to the
|
|
153
|
+
* Query capture that opened the copy.
|
|
154
|
+
*
|
|
155
|
+
* Returns false when the socket's buffer is full, exactly as
|
|
156
|
+
* net.Socket.write() does - the caller is expected to stop writing until
|
|
157
|
+
* `cb` fires, which is what CopyFromStream hands straight to its own
|
|
158
|
+
* Writable callback.
|
|
159
|
+
*/
|
|
160
|
+
sendCopyData(data: Buffer, cb?: Callback): boolean;
|
|
161
|
+
/** Ends a COPY IN normally; the server replies CommandComplete. */
|
|
162
|
+
sendCopyDone(cb?: Callback): boolean;
|
|
163
|
+
/**
|
|
164
|
+
* Aborts a COPY IN. The server discards the copy, reports `message` as an
|
|
165
|
+
* ErrorResponse and returns to its normal state - without this a failed
|
|
166
|
+
* import would leave the connection waiting for data forever.
|
|
167
|
+
*/
|
|
168
|
+
sendCopyFail(message: string, cb?: Callback): boolean;
|
|
169
|
+
/**
|
|
170
|
+
* Stops reading from the socket, so a COPY OUT consumer that cannot keep
|
|
171
|
+
* up doesn't buffer the whole export in memory. Safe to call repeatedly.
|
|
172
|
+
*/
|
|
173
|
+
pause(): void;
|
|
174
|
+
resume(): void;
|
|
34
175
|
sendFlushMessage(cb?: Callback): void;
|
|
35
176
|
sendTerminateMessage(cb?: Callback): void;
|
|
36
|
-
sendSyncMessage():
|
|
37
|
-
|
|
177
|
+
sendSyncMessage(cb: CaptureCallback): Promise<any>;
|
|
178
|
+
/**
|
|
179
|
+
* The only way anything outside this class can receive a correlated
|
|
180
|
+
* backend response. Sends `data` and pushes `cb` onto the FIFO capture
|
|
181
|
+
* queue in the same call, so a response can never arrive before its
|
|
182
|
+
* capturer is registered, and a capturer can never be registered without
|
|
183
|
+
* a message actually going out for it - there is no separate, decoupled
|
|
184
|
+
* "start listening" step to race or misuse.
|
|
185
|
+
*/
|
|
186
|
+
private _sendAndCapture;
|
|
38
187
|
protected _removeListeners(): void;
|
|
39
188
|
protected _reset(): void;
|
|
40
189
|
protected _handleConnect(): void;
|
|
190
|
+
/**
|
|
191
|
+
* Called once the server is ready. With `targetSessionAttrs` set, the
|
|
192
|
+
* session has to be checked before it is handed over: a server that does
|
|
193
|
+
* not match is dropped and the next candidate tried, which is how
|
|
194
|
+
* `read-write` finds whichever node is currently the primary.
|
|
195
|
+
*/
|
|
196
|
+
protected _finishConnect(): void;
|
|
197
|
+
/** Accepts this server, or drops it and moves to the next candidate. */
|
|
198
|
+
protected _applySessionAttrs(wanted: string, standby: boolean, readOnly: boolean): void;
|
|
41
199
|
protected _handleClose(): void;
|
|
42
200
|
protected _handleError(err: unknown): void;
|
|
201
|
+
/** Rejects and clears every still-open capture, e.g. on close/error. */
|
|
202
|
+
private _failPendingCaptures;
|
|
43
203
|
protected _handleData(data: Buffer): void;
|
|
204
|
+
/**
|
|
205
|
+
* Routes one backend message to the capture at the front of the FIFO -
|
|
206
|
+
* the oldest still-open request, i.e. the one whose turn it is given the
|
|
207
|
+
* order messages were written to the socket. This *is* the request/
|
|
208
|
+
* response correlation, since the wire protocol has no id of its own.
|
|
209
|
+
* The same entry keeps receiving messages (ParseComplete, BindComplete,
|
|
210
|
+
* RowDescription, DataRow*, CommandComplete, ReadyForQuery, ...) until
|
|
211
|
+
* its callback calls `done()`, at which point it is dequeued and the
|
|
212
|
+
* next entry becomes the one messages are routed to.
|
|
213
|
+
*/
|
|
214
|
+
private _dispatch;
|
|
44
215
|
protected _resolvePassword(cb: (password: string) => void): void;
|
|
45
216
|
protected _handleAuthenticationMessage(msg?: any): void;
|
|
217
|
+
/**
|
|
218
|
+
* tls-server-end-point: the server certificate hashed with the algorithm
|
|
219
|
+
* its own signature used (RFC 5929), which is why the DER has to be read
|
|
220
|
+
* rather than one of Node's fixed fingerprints taken.
|
|
221
|
+
*/
|
|
222
|
+
protected _channelBindingData(socket: tls.TLSSocket): Buffer;
|
|
46
223
|
protected _handleParameterStatus(msg: Protocol.ParameterStatusMessage): void;
|
|
47
224
|
protected _handleBackendKeyData(msg: Protocol.BackendKeyDataMessage): void;
|
|
48
225
|
protected _handleCommandComplete(msg: any): Protocol.CommandCompleteMessage;
|
|
49
|
-
|
|
226
|
+
/**
|
|
227
|
+
* Queues `data` for the socket instead of writing it straight through:
|
|
228
|
+
* everything handed to _send() during the same synchronous burst (e.g.
|
|
229
|
+
* many concurrent query() calls fired via Promise.all over one
|
|
230
|
+
* connection) is flushed together on the next tick, corked, so Node
|
|
231
|
+
* turns the whole batch into a single underlying writev rather than one
|
|
232
|
+
* socket write per call. Measured against postgres.js, which coalesces
|
|
233
|
+
* the same way at the application level (its connection.js write()/
|
|
234
|
+
* nextWrite() pair, flushing on a 1KB threshold or setImmediate): 50
|
|
235
|
+
* concurrent prepared executes cost it 3 socket writes where this cost
|
|
236
|
+
* us 50, and that write path was the single largest non-idle item in a
|
|
237
|
+
* CPU profile of the scenario.
|
|
238
|
+
*
|
|
239
|
+
* nextTick rather than setImmediate, deliberately: it still batches a
|
|
240
|
+
* whole synchronous burst, but a lone query doesn't have to wait for the
|
|
241
|
+
* event loop's check phase before its bytes go out - which would trade
|
|
242
|
+
* away the sequential/single-query scenarios to win the concurrent ones.
|
|
243
|
+
*
|
|
244
|
+
* Returns whether the socket could accept the data at all; the write
|
|
245
|
+
* itself is reported through `cb` (and a socket that dies before the
|
|
246
|
+
* flush rejects every pending capture via _failPendingCaptures()).
|
|
247
|
+
*/
|
|
248
|
+
protected _send(data: Buffer | Buffer[], cb?: Callback): boolean;
|
|
249
|
+
/**
|
|
250
|
+
* Writes COPY bytes straight through instead of queueing them for the
|
|
251
|
+
* next tick like _send() does. Two reasons: during a copy the capture
|
|
252
|
+
* queue holds exactly one entry (the Query that opened it), so _send()'s
|
|
253
|
+
* "batch only when more than one request is in flight" test would never
|
|
254
|
+
* fire and every chunk would be written on its own anyway; and the
|
|
255
|
+
* caller needs write()'s own return value to know when to stop, which a
|
|
256
|
+
* deferred write cannot give it.
|
|
257
|
+
*/
|
|
258
|
+
protected _sendCopy(data: Buffer | Buffer[], cb?: Callback): boolean;
|
|
259
|
+
/** Arrow property, not a method: used as a bare process.nextTick callback. */
|
|
260
|
+
private _flushPendingWrites;
|
|
50
261
|
}
|