@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 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, and the binary protocol skips text (de)serialization where it can. None of this requires you to change how you write queries.
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
- ### Every query is its own commit boundary
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
- Fire off several queries in the same batch and one of them fails — the others aren't affected. Each query gets its own Sync, which means its own implicit transaction: an error in query B doesn't undo query A, even if A already returned and B is still in flight on the same pipelined write.
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
- This isolation is per-statement, not free-standing atomicity across statements if you need several queries to succeed or fail together, that's what `begin()` and `savepoint()` are for. Outside a transaction, every query stands on its own.
71
-
72
-
73
- ### Errors you can pattern-match on
71
+ // a: fulfilledthe balance update is committed
72
+ // b: rejected — the duplicate key error only affects this query
73
+ ```
74
74
 
75
- Every call returns a `Future<T[], PostgresError>` from [fluent-future](https://www.npmjs.com/package/fluent-future) instead of a bare `Promise`. `await` still works exactly like you'd expect — but you also get typed errors and a way to handle them without a `try/catch` pyramid:
75
+ Errors can be matched and recovered directly on the `Future`:
76
76
 
77
77
  ```typescript
78
- const users = await pool.query<User>`SELECT * FROM users WHERE id = ${1}`
79
- .recoverIf(err => err.code === '42P01', []) // undefined_table → []
80
- .recoverIf(err => err.code === '23505', []) // unique_violation → []
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
 
@@ -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
  /**
@@ -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;IAE3C,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,CAAuC;IAEvD,OAAO,CAAC,mBAAmB,CAAyD;IACpF,OAAO,CAAC,YAAY,CAAI;IAExB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,cAAc;IAYtB,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;IA4CrB;;;;;OAKG;IACH,OAAO,CAAC,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IAazD,OAAO,CAAC,eAAe;IA2CvB;;;;;;OAMG;IACH,MAAM,CAAC,CAAC,SAAS,GAAG,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE;IA2BvE,OAAO,CAAC,cAAc;IA8CtB;;;;;;;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;IA6BzB,OAAO,CAAC,qBAAqB;IAW7B,OAAO,KAAK,aAAa,GAExB;IAGD,OAAO,CAAC,aAAa;IAgIrB,kDAAkD;IAClD,IAAI,QAAQ,YAEX;IAGD,mDAAmD;IACnD,IAAI,QAAQ,YAEX;IAGD;;OAEG;IACH,KAAK;CAwBR"}
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"}
@@ -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
- this._queue.push(query);
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.statement, text, args, parsed.columns, this.config.queryTimeout, resolvers);
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
- if (parsing) {
123
- const query = new CollectQuery(parsing, text, args, null, this.config.queryTimeout, resolvers);
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.statement, text, args, this.config.queryTimeout, resolvers);
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
- if (parsing) {
163
- const query = new ExecuteQuery(parsing, text, args, this.config.queryTimeout, resolvers);
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.statement, text, args, controller, parsed.columns, this.config.queryTimeout);
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
- const parsing = this._parsing[text];
213
- if (parsing) {
214
- const query = new StreamQuery(parsing, text, args, controller, null, this.config.queryTimeout);
215
- this._registerQuery(query);
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 query = new StreamQuery(this._nextStatement(), text, args, controller, null, this.config.queryTimeout);
219
- this._parsing[text] = query.statement;
220
- this._parseQuery(query);
221
- this._registerQuery(query);
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
- if (query instanceof ExecuteQuery) {
333
- break;
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.ParameterDescription:
380
+ case ResponseTypes.RowDescription:
341
381
  {
342
382
  const query = this._currentQuery;
343
- const description = reader.readParameterDescription();
344
- const meta = {
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.RowDescription:
390
+ case ResponseTypes.NoData:
354
391
  {
355
392
  const query = this._currentQuery;
356
- const columns = reader.readRowDescription();
357
- this._parsed[query.text].columns = columns;
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._queue.isFree && this._closing.resolve();
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._queue.isFree) {
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
@@ -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 { ParameterDescription } from "../types";
2
- import { DescribeType, RequestType } from "./constants";
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
- private canWriteBinary;
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,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAE/C,OAAO,EAA6B,YAAY,EAAE,WAAW,EAAgB,MAAM,aAAa,CAAA;AAMhG,qBAAa,uBAAuB;IAE5B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,wBAAwB;IAHpC,OAAO;IAOP,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM;IAK3B,OAAO,CAAC,cAAc;IAoBtB,YAAY,CAAC,MAAM,EAAE,MAAM;IAY3B,WAAW,CAAC,MAAM,EAAE,MAAM;IAS1B,UAAU,CAAC,MAAM,EAAE,MAAM;IAUzB,UAAU,CAAC,MAAM,EAAE,MAAM;IAUzB,SAAS,CAAC,IAAI,EAAE,MAAM;IAStB,SAAS,CAAC,IAAI,EAAE,MAAM;IAQtB,aAAa,CAAC,KAAK,EAAE,MAAM;IAS3B,WAAW,CAAC,KAAK,EAAE,MAAM;IASzB,WAAW,CAAC,KAAK,EAAE,MAAM;IASzB,UAAU,CAAC,KAAK,EAAE,UAAU;IAa5B,UAAU,CAAC,MAAM,EAAE,MAAM;IAQzB,YAAY,CAAC,MAAM,EAAE,MAAM;IAQ3B,YAAY,CAAC,MAAM,EAAE,MAAM;IAQ3B,YAAY,CAAC,WAAW,EAAE,WAAW;IAQrC,YAAY;IAMZ,UAAU;IAYV,QAAQ;IAKR,KAAK;IAKL,UAAU,CAAC,IAAI,EAAE,MAAM;IASvB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM;IAW1C,aAAa,CACT,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,MAAM,GAAG,EAAE;IAWrB,UAAU,CAAC,IAAI,EAAE,MAAM;IAUvB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAY3C,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,EAAE;IAUlC,SAAS;IAOT,eAAe;IASf,aAAa,CAAC,QAAQ,EAAE,MAAM;IAS9B,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM;IAW9D,iBAAiB,CAAC,kBAAkB,EAAE,MAAM;IAS5C,eAAe,CAAC,KAAK,EAAE,OAAO;IAO9B,eAAe,CAAC,KAAK,EAAE,MAAM;IAO7B,eAAe,CAAC,KAAK,EAAE,MAAM;IAQ7B,eAAe,CAAC,KAAK,EAAE,MAAM;IAO7B,kBAAkB,CAAC,KAAK,EAAE,MAAM;IAOhC,iBAAiB,CAAC,KAAK,EAAE,MAAM;IAO/B,iBAAiB,CAAC,KAAK,EAAE,MAAM;IAO/B,gBAAgB,CAAC,KAAK,EAAE,UAAU;IAOlC,oBAAoB,CAAC,KAAK,EAAE,IAAI;IAWhC,SAAS;IAMT,OAAO,CAAC,cAAc;IAkEtB,SAAS,CACL,QAAQ,EAAE,MAAM,GAAG,EAAE,EACrB,aAAa,EAAE,MAAM,GAAG,EAAE,EAC1B,MAAM,EAAE,OAAO,EAAE,EACjB,cAAc,CAAC,EAAE,oBAAoB;CAoF5C"}
1
+ {"version":3,"file":"connection-request-writer.d.ts","sourceRoot":"","sources":["../../src/protocol/connection-request-writer.ts"],"names":[],"mappings":"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"}