@m2k-5f/pgtx 2.7.3 → 2.8.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/README.md +24 -13
- package/dist/connection.d.ts +1 -1
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +105 -65
- package/dist/error.d.ts +2 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +11 -0
- package/dist/protocol/connection-request-writer.d.ts +87 -4
- package/dist/protocol/connection-request-writer.d.ts.map +1 -1
- package/dist/protocol/connection-request-writer.js +310 -86
- package/dist/protocol/connection-response-reader.d.ts +72 -15
- package/dist/protocol/connection-response-reader.d.ts.map +1 -1
- package/dist/protocol/connection-response-reader.js +264 -246
- package/dist/protocol/constants.js +8 -8
- package/dist/protocol/types.d.ts +14 -0
- package/dist/protocol/types.d.ts.map +1 -0
- package/dist/protocol/types.js +264 -0
- package/dist/query.d.ts +23 -9
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +32 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,37 +50,48 @@ Benchmarks run on GitHub Actions (Ubuntu, 2 vCPUs), reproducible, sources in thi
|
|
|
50
50
|
|
|
51
51
|
Bun.sql is Bun's own built-in driver, written in native code and generally treated as the speed baseline in that ecosystem. Pgtx stays ahead of it at every concurrency level tested — the gap doesn't come from JS-vs-native, it comes from the protocol implementation.
|
|
52
52
|
|
|
53
|
-
**How:** everything you fire concurrently against the same connection gets folded into one pipelined write — Parse/Bind/Execute for every query in the batch goes out in a single `socket.write()`, and results get demuxed as they come back, in order, without buffering rows you haven't asked for yet. Prepared statements are cached and deduplicated automatically, row descriptions are cached alongside them
|
|
53
|
+
**How:** everything you fire concurrently against the same connection gets folded into one pipelined write — Parse/Bind/Execute for every query in the batch goes out in a single `socket.write()`, and results get demuxed as they come back, in order, without buffering rows you haven't asked for yet. Prepared statements are cached and deduplicated automatically, row descriptions are cached alongside them. None of this requires you to change how you write queries.
|
|
54
|
+
|
|
54
55
|
|
|
55
56
|
## The parts worth knowing about
|
|
56
57
|
|
|
57
58
|
|
|
58
|
-
###
|
|
59
|
+
### Error handling
|
|
60
|
+
|
|
61
|
+
Every query returns a `Future<T[], PostgresError>` instead of a bare `Promise`. `await` works as usual, while `Future` also provides typed error handling and recovery without a `try/catch` pyramid.
|
|
59
62
|
|
|
60
|
-
|
|
63
|
+
Queries in the same pipeline are isolated from each other. Each query gets its own `Sync`, so an error in one query does not affect other queries that were sent in the same batch.
|
|
61
64
|
|
|
62
65
|
```typescript
|
|
63
66
|
const [a, b] = await Promise.allSettled([
|
|
64
67
|
pool.execute`UPDATE accounts SET balance = balance + 100 WHERE id = ${1}`,
|
|
65
68
|
pool.execute`INSERT INTO accounts (id) VALUES (${1})` // duplicate key, fails
|
|
66
69
|
])
|
|
67
|
-
// a: fulfilled, the balance update is committed regardless of b's outcome
|
|
68
|
-
```
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
### Errors you can pattern-match on
|
|
71
|
+
// a: fulfilled — the balance update is committed
|
|
72
|
+
// b: rejected — the duplicate key error only affects this query
|
|
73
|
+
```
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
Errors can be matched and recovered directly on the `Future`:
|
|
76
76
|
|
|
77
77
|
```typescript
|
|
78
|
-
const users = await pool.query<User>`
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
const users = await pool.query<User>`
|
|
79
|
+
SELECT * FROM users WHERE id = ${1}
|
|
80
|
+
`
|
|
81
|
+
.recoverIf(err => err.code === '42P01', []) // undefined_table → []
|
|
82
|
+
.recoverIf(err => err.code === '23505', []) // unique_violation → []
|
|
81
83
|
.tapErr(err => logger.error(err))
|
|
82
84
|
```
|
|
83
85
|
|
|
86
|
+
This isolation is per statement, not atomicity across multiple statements. If several queries must succeed or fail together, use `begin()` and `savepoint()`.
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
### PostgreSQL Type Support
|
|
90
|
+
|
|
91
|
+
The driver provides **100% support for PostgreSQL data types using the full binary protocol**. All supported types are encoded and decoded directly in PostgreSQL's binary wire format, without falling back to text-based parsing.
|
|
92
|
+
|
|
93
|
+
For a complete list of supported PostgreSQL types, their JavaScript input/output types, and string formats, see the [PostgreSQL Data Types](./DATATYPES.md) reference.
|
|
94
|
+
|
|
84
95
|
|
|
85
96
|
### Transactions and savepoints
|
|
86
97
|
|
package/dist/connection.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export declare class Connection {
|
|
|
17
17
|
private _writer;
|
|
18
18
|
private _sheduled;
|
|
19
19
|
private _queue;
|
|
20
|
+
private _executingCounter;
|
|
20
21
|
private _closing;
|
|
21
22
|
private _closed;
|
|
22
23
|
private _reconnecting;
|
|
@@ -28,7 +29,6 @@ export declare class Connection {
|
|
|
28
29
|
private _nextStatement;
|
|
29
30
|
private _registerShedule;
|
|
30
31
|
private _shedule;
|
|
31
|
-
private _parseQuery;
|
|
32
32
|
private _registerQuery;
|
|
33
33
|
private constructor();
|
|
34
34
|
/**
|
package/dist/connection.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiC,uBAAuB,EAAuC,GAAG,EAAiB,MAAM,SAAS,CAAA;AACzI,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAK3C,OAAO,EAAS,MAAM,EAAM,MAAM,eAAe,CAAA;AACjD,OAAO,EAAkD,aAAa,EAAE,MAAM,SAAS,CAAA;AAevF;;;;;;;;;GASG;AACH,qBAAa,UAAU;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IAEzC,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,MAAM,CAA6B;
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiC,uBAAuB,EAAuC,GAAG,EAAiB,MAAM,SAAS,CAAA;AACzI,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAK3C,OAAO,EAAS,MAAM,EAAM,MAAM,eAAe,CAAA;AACjD,OAAO,EAAkD,aAAa,EAAE,MAAM,SAAS,CAAA;AAevF;;;;;;;;;GASG;AACH,qBAAa,UAAU;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IAEzC,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,iBAAiB,CAAI;IAE7B,OAAO,CAAC,QAAQ,CAAsD;IACtE,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,aAAa,CAA2C;IAEhE,OAAO,CAAC,OAAO,CAAiB;IAEhC,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,QAAQ,CAA8D;IAE9E,OAAO,CAAC,mBAAmB,CAAyD;IACpF,OAAO,CAAC,YAAY,CAAI;IAExB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,cAAc;IA6BtB,OAAO;IAYP;;;OAGG;IACH,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,uBAAuB;IAkB1C;;;;;;OAMG;IACH,KAAK,CAAC,CAAC,SAAS,GAAG,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAatE,OAAO,CAAC,aAAa;IA+DrB;;;;;OAKG;IACH,OAAO,CAAC,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAazD,OAAO,CAAC,eAAe;IA+DvB;;;;;;OAMG;IACH,MAAM,CAAC,CAAC,SAAS,GAAG,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IA2BvE,OAAO,CAAC,cAAc;IAkEtB;;;;;;;OAOG;IACH,KAAK,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC;IAoB7D,2EAA2E;IAC3E,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,MAAW;IAOhD,sFAAsF;IACtF,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI;IAe/D,4EAA4E;IAC5E,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC;IAoB/F,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,iBAAiB;IA8BzB,OAAO,CAAC,qBAAqB;IAW7B,OAAO,KAAK,aAAa,GAExB;IAGD,OAAO,CAAC,aAAa;IA6HrB,kDAAkD;IAClD,IAAI,QAAQ,YAEX;IAGD,mDAAmD;IACnD,IAAI,QAAQ,YAEX;IAGD;;OAEG;IACH,KAAK;CAwBR"}
|
package/dist/connection.js
CHANGED
|
@@ -3,7 +3,7 @@ import { compileSqlTemplate } from "./utils";
|
|
|
3
3
|
import { Transaction } from "./transaction";
|
|
4
4
|
import { SocketConnector } from "./protocol/socket-connector";
|
|
5
5
|
import { Queue } from "./queue";
|
|
6
|
-
import { CollectQuery, StreamQuery, ExecuteQuery } from "./query";
|
|
6
|
+
import { CollectQuery, StreamQuery, ExecuteQuery, ParseQuery } from "./query";
|
|
7
7
|
import { sql } from ".";
|
|
8
8
|
import { Begin, Future, Ok } from 'fluent-future';
|
|
9
9
|
import { ErrConnectionClosed, ErrConnectionReconnecting } from "./error";
|
|
@@ -39,28 +39,35 @@ export class Connection {
|
|
|
39
39
|
_shedule() {
|
|
40
40
|
if (this._reconnecting)
|
|
41
41
|
return;
|
|
42
|
-
this._socket.write(this._writer);
|
|
42
|
+
this._writer.hasMore && this._socket.write(this._writer);
|
|
43
43
|
this._writer.clear();
|
|
44
44
|
this._sheduled = false;
|
|
45
45
|
}
|
|
46
|
-
_parseQuery(query) {
|
|
47
|
-
this._registerShedule();
|
|
48
|
-
this._writer
|
|
49
|
-
.writeParse(query.statement, query.text)
|
|
50
|
-
.writeDescribe(DescribeType.Statement, query.statement);
|
|
51
|
-
}
|
|
52
46
|
_registerQuery(query) {
|
|
53
47
|
this._registerShedule();
|
|
54
|
-
|
|
48
|
+
if (query instanceof ParseQuery) {
|
|
49
|
+
this._writer
|
|
50
|
+
.writeParse(query.meta.statement, query.text)
|
|
51
|
+
.writeDescribe(DescribeType.Statement, query.meta.statement)
|
|
52
|
+
.writeSync();
|
|
53
|
+
this._queue.push(query);
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
const err = this._writer
|
|
57
|
+
.writeBind("", query.meta, query.args);
|
|
58
|
+
if (err)
|
|
59
|
+
return err;
|
|
55
60
|
this._writer
|
|
56
|
-
.writeBind("", query.statement, query.args, this._parsed[query.text]?.parameters)
|
|
57
61
|
.writeExecute("")
|
|
58
62
|
.writeSync();
|
|
63
|
+
this._queue.push(query);
|
|
64
|
+
return null;
|
|
59
65
|
}
|
|
60
66
|
constructor(socket, config) {
|
|
61
67
|
this._writer = ConnectionRequestBuffer.new(65536);
|
|
62
68
|
this._sheduled = false;
|
|
63
69
|
this._queue = new Queue();
|
|
70
|
+
this._executingCounter = 0;
|
|
64
71
|
this._closing = null;
|
|
65
72
|
this._closed = false;
|
|
66
73
|
this._reconnecting = null;
|
|
@@ -112,23 +119,34 @@ export class Connection {
|
|
|
112
119
|
+ `${args.length !== 0 ? `\x1b[36m│\x1b[0m \x1b[90mArguments:\x1b[0m [${args}]\n` : ''}`
|
|
113
120
|
+ `\x1b[36m└────────────────────────────────────────────────\x1b[0m`);
|
|
114
121
|
}
|
|
122
|
+
this._executingCounter++;
|
|
115
123
|
const parsed = this._parsed[text];
|
|
116
124
|
if (parsed) {
|
|
117
|
-
const query = new CollectQuery(parsed
|
|
118
|
-
this._registerQuery(query);
|
|
125
|
+
const query = new CollectQuery(parsed, text, args, parsed.columns, resolvers, this.config.queryTimeout);
|
|
126
|
+
const err = this._registerQuery(query);
|
|
127
|
+
if (err) {
|
|
128
|
+
this._executingCounter--;
|
|
129
|
+
query.error(err);
|
|
130
|
+
return query.resolvers.future;
|
|
131
|
+
}
|
|
119
132
|
return query.resolvers.future;
|
|
120
133
|
}
|
|
134
|
+
if (!this._parsing[text]) {
|
|
135
|
+
const parseQuery = new ParseQuery({ statement: this._nextStatement(), columns: EMPTY_ARRAY, parameters: EMPTY_ARRAY }, text, Future.withResolvers(), this.config.queryTimeout);
|
|
136
|
+
this._registerQuery(parseQuery);
|
|
137
|
+
this._parsing[text] = parseQuery.resolvers.future;
|
|
138
|
+
}
|
|
121
139
|
const parsing = this._parsing[text];
|
|
122
|
-
|
|
123
|
-
const query = new CollectQuery(
|
|
124
|
-
this._registerQuery(query);
|
|
140
|
+
return parsing.andThen(meta => {
|
|
141
|
+
const query = new CollectQuery(meta, text, args, meta.columns, resolvers, this.config.queryTimeout);
|
|
142
|
+
const err = this._registerQuery(query);
|
|
143
|
+
if (err) {
|
|
144
|
+
this._executingCounter--;
|
|
145
|
+
query.error(err);
|
|
146
|
+
return query.resolvers.future;
|
|
147
|
+
}
|
|
125
148
|
return query.resolvers.future;
|
|
126
|
-
}
|
|
127
|
-
const query = new CollectQuery(this._nextStatement(), text, args, null, this.config.queryTimeout, resolvers);
|
|
128
|
-
this._parsing[text] = query.statement;
|
|
129
|
-
this._parseQuery(query);
|
|
130
|
-
this._registerQuery(query);
|
|
131
|
-
return query.resolvers.future;
|
|
149
|
+
});
|
|
132
150
|
}
|
|
133
151
|
/**
|
|
134
152
|
* Like {@link query}, but for statements that don't return rows (INSERT/UPDATE/DDL/etc).
|
|
@@ -152,23 +170,34 @@ export class Connection {
|
|
|
152
170
|
+ `${args.length !== 0 ? `\x1b[35m│\x1b[0m \x1b[90mArguments:\x1b[0m [${args}]\n` : ''}`
|
|
153
171
|
+ `\x1b[35m└────────────────────────────────────────────────\x1b[0m`);
|
|
154
172
|
}
|
|
173
|
+
this._executingCounter++;
|
|
155
174
|
const parsed = this._parsed[text];
|
|
156
175
|
if (parsed) {
|
|
157
|
-
const query = new ExecuteQuery(parsed
|
|
158
|
-
this._registerQuery(query);
|
|
176
|
+
const query = new ExecuteQuery(parsed, text, args, resolvers, this.config.queryTimeout);
|
|
177
|
+
const err = this._registerQuery(query);
|
|
178
|
+
if (err) {
|
|
179
|
+
this._executingCounter--;
|
|
180
|
+
query.error(err);
|
|
181
|
+
return query.resolvers.future;
|
|
182
|
+
}
|
|
159
183
|
return query.resolvers.future;
|
|
160
184
|
}
|
|
185
|
+
if (!this._parsing[text]) {
|
|
186
|
+
const parseQuery = new ParseQuery({ statement: this._nextStatement(), columns: EMPTY_ARRAY, parameters: EMPTY_ARRAY }, text, Future.withResolvers(), this.config.queryTimeout);
|
|
187
|
+
this._registerQuery(parseQuery);
|
|
188
|
+
this._parsing[text] = parseQuery.resolvers.future;
|
|
189
|
+
}
|
|
161
190
|
const parsing = this._parsing[text];
|
|
162
|
-
|
|
163
|
-
const query = new ExecuteQuery(
|
|
164
|
-
this._registerQuery(query);
|
|
191
|
+
return parsing.andThen(meta => {
|
|
192
|
+
const query = new ExecuteQuery(meta, text, args, resolvers, this.config.queryTimeout);
|
|
193
|
+
const err = this._registerQuery(query);
|
|
194
|
+
if (err) {
|
|
195
|
+
this._executingCounter--;
|
|
196
|
+
query.error(err);
|
|
197
|
+
return query.resolvers.future;
|
|
198
|
+
}
|
|
165
199
|
return query.resolvers.future;
|
|
166
|
-
}
|
|
167
|
-
const query = new ExecuteQuery(this._nextStatement(), text, args, this.config.queryTimeout, resolvers);
|
|
168
|
-
this._parsing[text] = query.statement;
|
|
169
|
-
this._parseQuery(query);
|
|
170
|
-
this._registerQuery(query);
|
|
171
|
-
return query.resolvers.future;
|
|
200
|
+
});
|
|
172
201
|
}
|
|
173
202
|
/**
|
|
174
203
|
* Streams query results as a `ReadableStream`, without buffering rows in memory.
|
|
@@ -203,22 +232,36 @@ export class Connection {
|
|
|
203
232
|
+ `${args.length !== 0 ? `\x1b[34m│\x1b[0m \x1b[90mArguments:\x1b[0m [${args}]\n` : ''}`
|
|
204
233
|
+ `\x1b[34m└────────────────────────────────────────────────\x1b[0m`);
|
|
205
234
|
}
|
|
235
|
+
this._executingCounter++;
|
|
206
236
|
const parsed = this._parsed[text];
|
|
207
237
|
if (parsed) {
|
|
208
|
-
const query = new StreamQuery(parsed
|
|
209
|
-
this._registerQuery(query);
|
|
238
|
+
const query = new StreamQuery(parsed, text, args, controller, parsed.columns, this.config.queryTimeout);
|
|
239
|
+
const err = this._registerQuery(query);
|
|
240
|
+
if (err) {
|
|
241
|
+
this._executingCounter--;
|
|
242
|
+
controller.error(err);
|
|
243
|
+
}
|
|
210
244
|
return;
|
|
211
245
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
this.
|
|
216
|
-
return;
|
|
246
|
+
if (!this._parsing[text]) {
|
|
247
|
+
const parseQuery = new ParseQuery({ statement: this._nextStatement(), columns: EMPTY_ARRAY, parameters: EMPTY_ARRAY }, text, Future.withResolvers(), this.config.queryTimeout);
|
|
248
|
+
this._registerQuery(parseQuery);
|
|
249
|
+
this._parsing[text] = parseQuery.resolvers.future;
|
|
217
250
|
}
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
251
|
+
const parsing = this._parsing[text];
|
|
252
|
+
parsing
|
|
253
|
+
.tap(meta => {
|
|
254
|
+
const query = new StreamQuery(meta, text, args, controller, null, this.config.queryTimeout);
|
|
255
|
+
const err = this._registerQuery(query);
|
|
256
|
+
if (err) {
|
|
257
|
+
this._executingCounter--;
|
|
258
|
+
controller.error(err);
|
|
259
|
+
}
|
|
260
|
+
})
|
|
261
|
+
.tapErr(err => {
|
|
262
|
+
controller.error(err);
|
|
263
|
+
})
|
|
264
|
+
.recover();
|
|
222
265
|
}
|
|
223
266
|
/**
|
|
224
267
|
* Runs `txCallback` inside `BEGIN`/`COMMIT`, rolling back on error.
|
|
@@ -297,6 +340,7 @@ export class Connection {
|
|
|
297
340
|
this._parsed = {};
|
|
298
341
|
this._parsing = {};
|
|
299
342
|
this._sheduled = false;
|
|
343
|
+
this._executingCounter = 0;
|
|
300
344
|
while (this._queue.hasMore) {
|
|
301
345
|
this._queue.shift.error(ErrConnectionReconnecting);
|
|
302
346
|
}
|
|
@@ -324,37 +368,31 @@ export class Connection {
|
|
|
324
368
|
_handlePacket(type, length, reader) {
|
|
325
369
|
switch (type) {
|
|
326
370
|
case ResponseTypes.ParseComplete:
|
|
327
|
-
case ResponseTypes.NoData:
|
|
328
|
-
case ResponseTypes.CloseComplete: break;
|
|
329
371
|
case ResponseTypes.BindComplete:
|
|
372
|
+
case ResponseTypes.CloseComplete: break;
|
|
373
|
+
case ResponseTypes.ParameterDescription:
|
|
330
374
|
{
|
|
331
375
|
const query = this._currentQuery;
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
}
|
|
335
|
-
if (!query.columns) {
|
|
336
|
-
query.columns = this._parsed[query.text].columns;
|
|
337
|
-
}
|
|
376
|
+
const parameters = reader.readParameterDescription();
|
|
377
|
+
query.meta.parameters = parameters;
|
|
338
378
|
}
|
|
339
379
|
break;
|
|
340
|
-
case ResponseTypes.
|
|
380
|
+
case ResponseTypes.RowDescription:
|
|
341
381
|
{
|
|
342
382
|
const query = this._currentQuery;
|
|
343
|
-
const
|
|
344
|
-
|
|
345
|
-
statement: query.statement,
|
|
346
|
-
parameters: description,
|
|
347
|
-
columns: EMPTY_ARRAY
|
|
348
|
-
};
|
|
383
|
+
const columns = reader.readRowDescription();
|
|
384
|
+
query.meta.columns = columns;
|
|
349
385
|
delete this._parsing[query.text];
|
|
350
|
-
this._parsed[query.text] = meta;
|
|
386
|
+
this._parsed[query.text] = query.meta;
|
|
387
|
+
query.complete();
|
|
351
388
|
}
|
|
352
389
|
break;
|
|
353
|
-
case ResponseTypes.
|
|
390
|
+
case ResponseTypes.NoData:
|
|
354
391
|
{
|
|
355
392
|
const query = this._currentQuery;
|
|
356
|
-
|
|
357
|
-
this._parsed[query.text]
|
|
393
|
+
delete this._parsing[query.text];
|
|
394
|
+
this._parsed[query.text] = query.meta;
|
|
395
|
+
query.complete();
|
|
358
396
|
}
|
|
359
397
|
break;
|
|
360
398
|
case ResponseTypes.DataRow:
|
|
@@ -364,7 +402,7 @@ export class Connection {
|
|
|
364
402
|
reader.skipBytes(length);
|
|
365
403
|
break;
|
|
366
404
|
}
|
|
367
|
-
query.push(reader.readDataRow(query.columns, this.config.int8toBigint));
|
|
405
|
+
query.push(reader.readDataRow(query.meta.columns, this.config.int8toBigint));
|
|
368
406
|
}
|
|
369
407
|
break;
|
|
370
408
|
case ResponseTypes.ComandComplete:
|
|
@@ -372,6 +410,7 @@ export class Connection {
|
|
|
372
410
|
reader.skipBytes(length);
|
|
373
411
|
const query = this._currentQuery;
|
|
374
412
|
query.complete();
|
|
413
|
+
this._executingCounter--;
|
|
375
414
|
}
|
|
376
415
|
break;
|
|
377
416
|
case ResponseTypes.ErrorResponse:
|
|
@@ -387,13 +426,14 @@ export class Connection {
|
|
|
387
426
|
delete this._parsing[query.text];
|
|
388
427
|
}
|
|
389
428
|
query.error(error);
|
|
429
|
+
this._executingCounter--;
|
|
390
430
|
}
|
|
391
431
|
break;
|
|
392
432
|
case ResponseTypes.ReadyForQuery:
|
|
393
433
|
{
|
|
394
434
|
reader.skipBytes(length);
|
|
395
435
|
this._queue.next();
|
|
396
|
-
this._closing && this.
|
|
436
|
+
this._closing && !this._executingCounter && this._closing.resolve();
|
|
397
437
|
}
|
|
398
438
|
break;
|
|
399
439
|
case ResponseTypes.Notice:
|
|
@@ -439,7 +479,7 @@ export class Connection {
|
|
|
439
479
|
if (this._closing) {
|
|
440
480
|
return this._closing.future;
|
|
441
481
|
}
|
|
442
|
-
if (this.
|
|
482
|
+
if (!this._executingCounter) {
|
|
443
483
|
this._closed = true;
|
|
444
484
|
this._socket.destroy();
|
|
445
485
|
return Future.resolve();
|
package/dist/error.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DataTypeOid } from "./protocol/constants";
|
|
1
2
|
export declare class PostgresError extends Error {
|
|
2
3
|
message: string;
|
|
3
4
|
code: string;
|
|
@@ -30,4 +31,5 @@ export declare const ErrSSLDenied: PostgresError;
|
|
|
30
31
|
export declare const ErrDatabaseNotFound: PostgresError;
|
|
31
32
|
export declare const ErrUntrustedCertificate: PostgresError;
|
|
32
33
|
export declare const ErrCertificateFileNotFound: PostgresError;
|
|
34
|
+
export declare function createBindTypeError(index: number, expectedType: DataTypeOid, actualValue: unknown): PostgresError;
|
|
33
35
|
//# sourceMappingURL=error.d.ts.map
|
package/dist/error.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,qBAAa,aAAc,SAAQ,KAAK;IAEhB,OAAO,EAAE,MAAM;IACxB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,MAAM;IACd,QAAQ,EAAE,MAAM;IAChB,KAAK,EAAE,MAAM;IACb,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,MAAM;IAChB,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,MAAM;gBART,OAAO,EAAE,MAAM,EACxB,IAAI,GAAE,MAAqB,EAC3B,MAAM,GAAE,MAAW,EACnB,QAAQ,GAAE,MAAW,EACrB,KAAK,GAAE,MAAW,EAClB,IAAI,GAAE,MAAW,EACjB,QAAQ,GAAE,MAAW,EACrB,QAAQ,GAAE,MAAW,EACrB,UAAU,GAAE,MAAW;IAMlC,IAAI,YAAY,IAAI,OAAO,CAK1B;IAED,IAAI,WAAW,IAAI,OAAO,CAKzB;IAED,IAAI,uBAAuB,IAAI,OAAO,CAErC;IAED,IAAI,8BAA8B,IAAI,OAAO,CAE5C;IAED,IAAI,qBAAqB,IAAI,OAAO,CAEnC;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,mBAAmB,IAAI,OAAO,CAEjC;CACJ;AAGD,eAAO,MAAM,gBAAgB,eAAmF,CAAA;AAChH,eAAO,MAAM,mBAAmB,eAAqE,CAAA;AACrG,eAAO,MAAM,yBAAyB,eAAiD,CAAA;AAEvF,eAAO,MAAM,eAAe,eAA8C,CAAA;AAE1E,eAAO,MAAM,aAAa,eAAkE,CAAA;AAE5F,eAAO,MAAM,oBAAoB,eAA6E,CAAA;AAE9G,eAAO,MAAM,mBAAmB,eAA8E,CAAA;AAC9G,eAAO,MAAM,yBAAyB,eAA2F,CAAA;AACjI,eAAO,MAAM,YAAY,eAA4D,CAAA;AACrF,eAAO,MAAM,mBAAmB,eAAwD,CAAA;AACxF,eAAO,MAAM,uBAAuB,eAA4E,CAAA;AAChH,eAAO,MAAM,0BAA0B,eAAkF,CAAA"}
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAgB,MAAM,sBAAsB,CAAA;AAEhE,qBAAa,aAAc,SAAQ,KAAK;IAEhB,OAAO,EAAE,MAAM;IACxB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,MAAM;IACd,QAAQ,EAAE,MAAM;IAChB,KAAK,EAAE,MAAM;IACb,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,MAAM;IAChB,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,MAAM;gBART,OAAO,EAAE,MAAM,EACxB,IAAI,GAAE,MAAqB,EAC3B,MAAM,GAAE,MAAW,EACnB,QAAQ,GAAE,MAAW,EACrB,KAAK,GAAE,MAAW,EAClB,IAAI,GAAE,MAAW,EACjB,QAAQ,GAAE,MAAW,EACrB,QAAQ,GAAE,MAAW,EACrB,UAAU,GAAE,MAAW;IAMlC,IAAI,YAAY,IAAI,OAAO,CAK1B;IAED,IAAI,WAAW,IAAI,OAAO,CAKzB;IAED,IAAI,uBAAuB,IAAI,OAAO,CAErC;IAED,IAAI,8BAA8B,IAAI,OAAO,CAE5C;IAED,IAAI,qBAAqB,IAAI,OAAO,CAEnC;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,mBAAmB,IAAI,OAAO,CAEjC;CACJ;AAGD,eAAO,MAAM,gBAAgB,eAAmF,CAAA;AAChH,eAAO,MAAM,mBAAmB,eAAqE,CAAA;AACrG,eAAO,MAAM,yBAAyB,eAAiD,CAAA;AAEvF,eAAO,MAAM,eAAe,eAA8C,CAAA;AAE1E,eAAO,MAAM,aAAa,eAAkE,CAAA;AAE5F,eAAO,MAAM,oBAAoB,eAA6E,CAAA;AAE9G,eAAO,MAAM,mBAAmB,eAA8E,CAAA;AAC9G,eAAO,MAAM,yBAAyB,eAA2F,CAAA;AACjI,eAAO,MAAM,YAAY,eAA4D,CAAA;AACrF,eAAO,MAAM,mBAAmB,eAAwD,CAAA;AACxF,eAAO,MAAM,uBAAuB,eAA4E,CAAA;AAChH,eAAO,MAAM,0BAA0B,eAAkF,CAAA;AAEzH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,GAAG,aAAa,CAcjH"}
|
package/dist/error.js
CHANGED
|
@@ -51,3 +51,14 @@ export const ErrSSLDenied = new PostgresError("SSL is required but server denied
|
|
|
51
51
|
export const ErrDatabaseNotFound = new PostgresError('Database with that dsn not found');
|
|
52
52
|
export const ErrUntrustedCertificate = new PostgresError("Database SSL certificate is untrusted or self-signed");
|
|
53
53
|
export const ErrCertificateFileNotFound = new PostgresError("The SSL certificate file specified in caPath was not found");
|
|
54
|
+
export function createBindTypeError(index, expectedType, actualValue) {
|
|
55
|
+
const position = (index + 1).toString();
|
|
56
|
+
const actualType = actualValue === null ? 'null' : typeof actualValue;
|
|
57
|
+
const message = `Bind error: Parameter $${position} type mismatch. Expected ${expectedType}, received "${actualType}(${actualValue})".`;
|
|
58
|
+
return new PostgresError(message, '22000', // code
|
|
59
|
+
`The parameter at position $${position} failed client-side binary validation.`, // detail
|
|
60
|
+
'ERROR', // severity
|
|
61
|
+
'writeBind() inside driver', // where
|
|
62
|
+
`Ensure that the argument passed as $${position} matches the PostgreSQL schema requirements.` // hint
|
|
63
|
+
);
|
|
64
|
+
}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { PostgresError } from "../error";
|
|
2
|
+
import { StatementMeta } from "../types";
|
|
3
|
+
import { DataTypeOid, DescribeType, RequestType } from "./constants";
|
|
3
4
|
export declare class ConnectionRequestBuffer {
|
|
4
5
|
private buffer;
|
|
5
6
|
private offset;
|
|
6
7
|
private lastRequestLenByteOffset;
|
|
8
|
+
private _markedCaret;
|
|
7
9
|
private constructor();
|
|
8
10
|
static new(capacity: number): ConnectionRequestBuffer;
|
|
11
|
+
get isEmpty(): boolean;
|
|
12
|
+
get hasMore(): boolean;
|
|
13
|
+
mark(): this;
|
|
14
|
+
rollback(): this;
|
|
9
15
|
private ensureCapacity;
|
|
10
16
|
writeCString(string: string): this;
|
|
11
17
|
writeString(string: string): this;
|
|
@@ -37,6 +43,7 @@ export declare class ConnectionRequestBuffer {
|
|
|
37
43
|
writeSaslInitial(mechanism: string, clientFirstMessage: string): this;
|
|
38
44
|
writeSaslResponse(clientFinalMessage: string): this;
|
|
39
45
|
writeBinaryBool(value: boolean): this;
|
|
46
|
+
writeBinaryString(value: string): this;
|
|
40
47
|
writeBinaryInt2(value: number): this;
|
|
41
48
|
writeBinaryInt4(value: number): this;
|
|
42
49
|
writeBinaryInt8(value: number): this;
|
|
@@ -45,8 +52,84 @@ export declare class ConnectionRequestBuffer {
|
|
|
45
52
|
writeBinaryFloat8(value: number): this;
|
|
46
53
|
writeBinaryBytea(value: Uint8Array): this;
|
|
47
54
|
writeBinaryTimestamp(value: Date): this;
|
|
55
|
+
writeBinaryPoint(value: {
|
|
56
|
+
x: number;
|
|
57
|
+
y: number;
|
|
58
|
+
}): this;
|
|
59
|
+
writeBinaryNumeric(value: string): this;
|
|
60
|
+
writeBinaryDate(value: Date): this;
|
|
61
|
+
writeBinaryTime(value: string): this;
|
|
62
|
+
writeBinaryTimetz(value: string): this;
|
|
63
|
+
writeBinaryInterval(value: {
|
|
64
|
+
months: number;
|
|
65
|
+
days: number;
|
|
66
|
+
microseconds: number | bigint;
|
|
67
|
+
}): this;
|
|
68
|
+
writeBinaryJson(value: unknown): this;
|
|
69
|
+
writeBinaryJsonb(value: unknown): this;
|
|
70
|
+
writeBinaryUuid(value: string): this;
|
|
71
|
+
private static readonly PGSQL_AF_INET;
|
|
72
|
+
private static readonly PGSQL_AF_INET6;
|
|
73
|
+
private ipv4ToBytes;
|
|
74
|
+
private ipv6ToBytes;
|
|
75
|
+
writeBinaryInet(value: string, isCidr?: boolean): this;
|
|
76
|
+
writeBinaryCidr(value: string): this;
|
|
77
|
+
writeBinaryMacaddr(value: string): this;
|
|
78
|
+
writeBinaryOid(value: number): this;
|
|
79
|
+
writeBinaryXid(value: number): this;
|
|
80
|
+
writeBinaryCid(value: number): this;
|
|
81
|
+
writeBinaryRegproc(value: number): this;
|
|
82
|
+
writeBinaryLseg(value: {
|
|
83
|
+
a: {
|
|
84
|
+
x: number;
|
|
85
|
+
y: number;
|
|
86
|
+
};
|
|
87
|
+
b: {
|
|
88
|
+
x: number;
|
|
89
|
+
y: number;
|
|
90
|
+
};
|
|
91
|
+
}): this;
|
|
92
|
+
writeBinaryPath(value: {
|
|
93
|
+
closed: boolean;
|
|
94
|
+
points: {
|
|
95
|
+
x: number;
|
|
96
|
+
y: number;
|
|
97
|
+
}[];
|
|
98
|
+
}): this;
|
|
99
|
+
writeBinaryBox(value: {
|
|
100
|
+
high: {
|
|
101
|
+
x: number;
|
|
102
|
+
y: number;
|
|
103
|
+
};
|
|
104
|
+
low: {
|
|
105
|
+
x: number;
|
|
106
|
+
y: number;
|
|
107
|
+
};
|
|
108
|
+
}): this;
|
|
109
|
+
writeBinaryPolygon(value: {
|
|
110
|
+
points: {
|
|
111
|
+
x: number;
|
|
112
|
+
y: number;
|
|
113
|
+
}[];
|
|
114
|
+
}): this;
|
|
115
|
+
writeBinaryLine(value: {
|
|
116
|
+
a: number;
|
|
117
|
+
b: number;
|
|
118
|
+
c: number;
|
|
119
|
+
}): this;
|
|
120
|
+
private writeLengthPrefixed;
|
|
121
|
+
writeBinaryArray(arr: unknown[], elementOid: DataTypeOid, elementWriter: (val: any) => void): this;
|
|
122
|
+
writeBinaryBoolArray(value: (boolean | null | undefined)[]): this;
|
|
123
|
+
writeBinaryInt2Array(value: (number | null | undefined)[]): this;
|
|
124
|
+
writeBinaryInt4Array(value: (number | null | undefined)[]): this;
|
|
125
|
+
writeBinaryInt8Array(value: (number | bigint | null | undefined)[]): this;
|
|
126
|
+
writeBinaryTextArray(value: (string | null | undefined)[]): this;
|
|
127
|
+
writeBinaryVarcharArray(value: (string | null | undefined)[]): this;
|
|
128
|
+
writeBinaryJsonArray(value: (unknown | null | undefined)[]): this;
|
|
129
|
+
writeBinaryJsonbArray(value: (unknown | null | undefined)[]): this;
|
|
130
|
+
writeBinaryUuidArray(value: (string | null | undefined)[]): this;
|
|
131
|
+
writeBinaryNumericArray(value: (number | string | null | undefined)[]): this;
|
|
48
132
|
writeNull(): this;
|
|
49
|
-
|
|
50
|
-
writeBind(portName: string | "", statementName: string | "", params: unknown[], parameterTypes?: ParameterDescription): this;
|
|
133
|
+
writeBind(portName: string | "", meta: StatementMeta, params: unknown[]): PostgresError | null;
|
|
51
134
|
}
|
|
52
135
|
//# sourceMappingURL=connection-request-writer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-request-writer.d.ts","sourceRoot":"","sources":["../../src/protocol/connection-request-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"connection-request-writer.d.ts","sourceRoot":"","sources":["../../src/protocol/connection-request-writer.ts"],"names":[],"mappings":"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"}
|