postgrejs 3.1.3 → 3.3.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +42 -1
  2. package/README.md +25 -9
  3. package/connection/cursor.d.ts +2 -1
  4. package/connection/cursor.js +6 -6
  5. package/connection/intl-connection.js +10 -14
  6. package/connection/prepared-statement.js +2 -1
  7. package/data-types/bool-type.js +0 -1
  8. package/data-types/box-type.js +0 -1
  9. package/data-types/bytea-type.js +5 -3
  10. package/data-types/char-type.js +2 -2
  11. package/data-types/circle-type.js +0 -1
  12. package/data-types/date-type.js +1 -2
  13. package/data-types/float4-type.js +2 -4
  14. package/data-types/float8-type.js +2 -5
  15. package/data-types/int2-type.js +0 -1
  16. package/data-types/int2-vector-type.js +3 -2
  17. package/data-types/int4-type.js +0 -1
  18. package/data-types/int8-type.js +0 -1
  19. package/data-types/json-type.js +2 -2
  20. package/data-types/jsonb-type.js +6 -5
  21. package/data-types/lseg-type.js +0 -1
  22. package/data-types/numeric-type.js +2 -4
  23. package/data-types/oid-type.js +0 -1
  24. package/data-types/oid-vector-type.js +3 -2
  25. package/data-types/point-type.js +0 -1
  26. package/data-types/time-type.js +1 -2
  27. package/data-types/timestamp-type.js +13 -3
  28. package/data-types/timestamptz-type.js +27 -10
  29. package/data-types/uuid-type.js +1 -2
  30. package/data-types/varchar-type.js +2 -2
  31. package/index.d.ts +1 -0
  32. package/index.js +1 -0
  33. package/interfaces/command-result.d.ts +3 -2
  34. package/interfaces/data-type.d.ts +0 -1
  35. package/interfaces/query-options.d.ts +12 -0
  36. package/interfaces/script-execute-options.d.ts +12 -0
  37. package/package.json +14 -2
  38. package/protocol/backend.js +6 -6
  39. package/protocol/buffer-reader.d.ts +7 -12
  40. package/protocol/buffer-reader.js +11 -58
  41. package/protocol/frontend.js +86 -96
  42. package/protocol/pg-socket.d.ts +6 -33
  43. package/protocol/pg-socket.js +19 -74
  44. package/protocol/pgoutput.js +2 -2
  45. package/protocol/smart-buffer.d.ts +11 -29
  46. package/protocol/smart-buffer.js +19 -162
  47. package/types.d.ts +13 -1
  48. package/util/bigint-methods.d.ts +0 -1
  49. package/util/bigint-methods.js +0 -22
  50. package/util/decode-binaryarray.d.ts +1 -1
  51. package/util/decode-binaryarray.js +7 -7
  52. package/util/encode-binaryarray.js +6 -6
  53. package/util/fast-parsefloat.d.ts +15 -0
  54. package/util/fast-parsefloat.js +141 -0
  55. package/util/get-parsers.js +4 -8
  56. package/util/parse-datetime.js +7 -0
  57. package/util/parse-pg-timestamp.d.ts +31 -0
  58. package/util/parse-pg-timestamp.js +199 -0
  59. package/util/parse-row.js +120 -0
  60. package/util/row-decoder.d.ts +49 -0
  61. package/util/row-decoder.js +63 -0
@@ -39,31 +39,31 @@ export class Frontend {
39
39
  this._io = new SmartBuffer(options?.buffer);
40
40
  }
41
41
  getSSLRequestMessage() {
42
- return this._io
43
- .start()
44
- .writeUInt32BE(8) // Length of message contents in bytes, including self.
45
- .writeUInt16BE(1234)
46
- .writeUInt16BE(5679)
47
- .flush();
42
+ const io = this._io.start();
43
+ io.writeUInt32BE(8); // Length of message contents in bytes, including self.
44
+ io.writeUInt16BE(1234);
45
+ io.writeUInt16BE(5679);
46
+ return io.flush();
48
47
  }
49
48
  getStartupMessage(args, minorVersion = Protocol.VERSION_MINOR) {
50
- const io = this._io
51
- .start()
52
- .writeInt32BE(0) // Preserve length
53
- .writeInt16BE(Protocol.VERSION_MAJOR)
54
- .writeInt16BE(minorVersion);
49
+ const io = this._io.start();
50
+ io.writeInt32BE(0); // Preserve length
51
+ io.writeInt16BE(Protocol.VERSION_MAJOR);
52
+ io.writeInt16BE(minorVersion);
55
53
  const entries = Object.entries(args);
56
54
  const l = entries.length;
57
55
  let k;
58
56
  let v;
59
57
  for (let i = 0; i < l; i++) {
60
58
  [k, v] = entries[i];
61
- if (k !== 'client_encoding')
62
- io.writeCString(k, 'utf8').writeCString(v, 'utf8');
59
+ if (k !== 'client_encoding') {
60
+ io.writeCString(k, 'utf8');
61
+ io.writeCString(v, 'utf8');
62
+ }
63
63
  }
64
- io.writeCString('client_encoding', 'utf8')
65
- .writeCString('UTF8', 'utf8')
66
- .writeUInt8(0);
64
+ io.writeCString('client_encoding', 'utf8');
65
+ io.writeCString('UTF8', 'utf8');
66
+ io.writeUInt8(0);
67
67
  return setLengthAndFlush(io, 0);
68
68
  }
69
69
  /**
@@ -73,51 +73,46 @@ export class Frontend {
73
73
  * down the normal one.
74
74
  */
75
75
  getCancelRequestMessage(processID, secretKey) {
76
- return this._io
77
- .start()
78
- .writeUInt32BE(12 + secretKey.length) // Length of message contents in bytes, including self.
79
- .writeUInt16BE(1234)
80
- .writeUInt16BE(5678)
81
- .writeUInt32BE(processID)
82
- .writeBuffer(secretKey)
83
- .flush();
76
+ const io = this._io.start();
77
+ io.writeUInt32BE(12 + secretKey.length); // Length of message contents in bytes, including self.
78
+ io.writeUInt16BE(1234);
79
+ io.writeUInt16BE(5678);
80
+ io.writeUInt32BE(processID);
81
+ io.writeBytes(secretKey);
82
+ return io.flush();
84
83
  }
85
84
  getPasswordMessage(password) {
86
- const io = this._io
87
- .start()
88
- .writeInt8(Protocol.FrontendMessageCode.PasswordMessage)
89
- .writeInt32BE(0) // Preserve header
90
- .writeCString(password, 'utf8');
85
+ const io = this._io.start();
86
+ io.writeInt8(Protocol.FrontendMessageCode.PasswordMessage);
87
+ io.writeInt32BE(0); // Preserve header
88
+ io.writeCString(password, 'utf8');
91
89
  return setLengthAndFlush(io, 1);
92
90
  }
93
91
  getSASLMessage(sasl) {
94
- const io = this._io
95
- .start()
96
- .writeInt8(Protocol.FrontendMessageCode.PasswordMessage)
97
- .writeInt32BE(0) // Preserve header
98
- .writeCString(sasl.mechanism, 'utf8')
99
- .writeLString(sasl.clientFirstMessage);
92
+ const io = this._io.start();
93
+ io.writeInt8(Protocol.FrontendMessageCode.PasswordMessage);
94
+ io.writeInt32BE(0); // Preserve header
95
+ io.writeCString(sasl.mechanism, 'utf8');
96
+ io.writeLString(sasl.clientFirstMessage);
100
97
  return setLengthAndFlush(io, 1);
101
98
  }
102
99
  getSASLFinalMessage(session) {
103
- const io = this._io
104
- .start()
105
- .writeInt8(Protocol.FrontendMessageCode.PasswordMessage)
106
- .writeInt32BE(0) // Preserve header
107
- .writeString(session.clientFinalMessage);
100
+ const io = this._io.start();
101
+ io.writeInt8(Protocol.FrontendMessageCode.PasswordMessage);
102
+ io.writeInt32BE(0); // Preserve header
103
+ io.writeString(session.clientFinalMessage);
108
104
  return setLengthAndFlush(io, 1);
109
105
  }
110
106
  getParseMessage(args) {
111
107
  if (args.statement && args.statement.length > 63)
112
108
  throw new Error('Query name length must be lower than 63');
113
109
  const { paramTypes } = args;
114
- const io = this._io
115
- .start()
116
- .writeInt8(Protocol.FrontendMessageCode.Parse)
117
- .writeInt32BE(0) // Preserve header
118
- .writeCString(args.statement || '', 'utf8')
119
- .writeCString(args.sql, 'utf8')
120
- .writeUInt16BE(paramTypes?.length || 0);
110
+ const io = this._io.start();
111
+ io.writeInt8(Protocol.FrontendMessageCode.Parse);
112
+ io.writeInt32BE(0); // Preserve header
113
+ io.writeCString(args.statement || '', 'utf8');
114
+ io.writeCString(args.sql, 'utf8');
115
+ io.writeUInt16BE(paramTypes?.length || 0);
121
116
  if (paramTypes) {
122
117
  let i;
123
118
  const l = paramTypes.length;
@@ -132,19 +127,18 @@ export class Frontend {
132
127
  throw new Error('Portal name length must be lower than 63');
133
128
  if (args.statement && args.statement.length > 63)
134
129
  throw new Error('Query name length must be lower than 63');
135
- const io = this._io
136
- .start()
137
- .writeInt8(Protocol.FrontendMessageCode.Bind)
138
- .writeInt32BE(0) // Preserve header
139
- .writeCString(args.portal || '', 'utf8')
140
- .writeCString(args.statement || '', 'utf8');
130
+ const io = this._io.start();
131
+ io.writeInt8(Protocol.FrontendMessageCode.Bind);
132
+ io.writeInt32BE(0); // Preserve header
133
+ io.writeCString(args.portal || '', 'utf8');
134
+ io.writeCString(args.statement || '', 'utf8');
141
135
  const { params, paramTypes, queryOptions } = args;
142
136
  const columnFormat = queryOptions.columnFormat != null
143
137
  ? queryOptions.columnFormat
144
138
  : DEFAULT_COLUMN_FORMAT;
145
139
  if (params && params.length) {
146
140
  io.writeInt16BE(params.length);
147
- const formatOffset = io.offset;
141
+ const formatOffset = io.position;
148
142
  const l = params.length;
149
143
  let i;
150
144
  for (i = 0; i < l; i++) {
@@ -172,7 +166,7 @@ export class Frontend {
172
166
  io.buffer.writeInt16BE(Protocol.DataFormat.binary, formatOffset + i * 2);
173
167
  // Preserve data length
174
168
  io.writeInt32BE(0);
175
- const dataOffset = io.offset;
169
+ const dataOffset = io.position;
176
170
  if (dt.elementsOID) {
177
171
  // If data type is array
178
172
  v = Array.isArray(v) ? v : [v];
@@ -181,7 +175,7 @@ export class Frontend {
181
175
  else {
182
176
  dt.encodeBinary(io, v, queryOptions);
183
177
  }
184
- io.buffer.writeInt32BE(io.length - dataOffset, dataOffset - 4); // Update length
178
+ io.buffer.writeInt32BE(io.size - dataOffset, dataOffset - 4); // Update length
185
179
  }
186
180
  else if (typeof dt.encodeText === 'function') {
187
181
  v = dt.elementsOID
@@ -195,9 +189,9 @@ export class Frontend {
195
189
  io.buffer.writeInt16BE(Protocol.DataFormat.binary, formatOffset + i * 2);
196
190
  // Preserve data length
197
191
  io.writeInt32BE(0);
198
- const dataOffset = io.offset;
199
- io.writeBuffer(v);
200
- io.buffer.writeInt32BE(io.length - dataOffset, dataOffset - 4); // Update length
192
+ const dataOffset = io.position;
193
+ io.writeBytes(v);
194
+ io.buffer.writeInt32BE(io.size - dataOffset, dataOffset - 4); // Update length
201
195
  }
202
196
  else {
203
197
  io.writeLString('' + v, 'utf8');
@@ -230,12 +224,11 @@ export class Frontend {
230
224
  ? 'Portal'
231
225
  : 'Statement name length must be lower than 63');
232
226
  }
233
- const io = this._io
234
- .start()
235
- .writeInt8(Protocol.FrontendMessageCode.Describe)
236
- .writeInt32BE(0) // Preserve header
237
- .writeUInt8(args.type.charCodeAt(0))
238
- .writeCString(args.name || '', 'utf8');
227
+ const io = this._io.start();
228
+ io.writeInt8(Protocol.FrontendMessageCode.Describe);
229
+ io.writeInt32BE(0); // Preserve header
230
+ io.writeUInt8(args.type.charCodeAt(0));
231
+ io.writeCString(args.name || '', 'utf8');
239
232
  return setLengthAndFlush(io, 1);
240
233
  }
241
234
  getExecuteMessage(args) {
@@ -243,12 +236,11 @@ export class Frontend {
243
236
  (args.fetchCount < 0 || args.fetchCount > 4294967295)) {
244
237
  throw new Error('fetchCount can be between 0 and 4294967295');
245
238
  }
246
- const io = this._io
247
- .start()
248
- .writeInt8(Protocol.FrontendMessageCode.Execute)
249
- .writeInt32BE(0) // Preserve header
250
- .writeCString(args.portal || '', 'utf8')
251
- .writeUInt32BE(args.fetchCount || 0);
239
+ const io = this._io.start();
240
+ io.writeInt8(Protocol.FrontendMessageCode.Execute);
241
+ io.writeInt32BE(0); // Preserve header
242
+ io.writeCString(args.portal || '', 'utf8');
243
+ io.writeUInt32BE(args.fetchCount || 0);
252
244
  return setLengthAndFlush(io, 1);
253
245
  }
254
246
  getCloseMessage(args) {
@@ -257,20 +249,18 @@ export class Frontend {
257
249
  ? 'Portal'
258
250
  : 'Statement name length must be lower than 63');
259
251
  }
260
- const io = this._io
261
- .start()
262
- .writeInt8(Protocol.FrontendMessageCode.Close)
263
- .writeInt32BE(0) // Preserve header
264
- .writeUInt8(args.type.charCodeAt(0))
265
- .writeCString(args.name || '', 'utf8');
252
+ const io = this._io.start();
253
+ io.writeInt8(Protocol.FrontendMessageCode.Close);
254
+ io.writeInt32BE(0); // Preserve header
255
+ io.writeUInt8(args.type.charCodeAt(0));
256
+ io.writeCString(args.name || '', 'utf8');
266
257
  return setLengthAndFlush(io, 1);
267
258
  }
268
259
  getQueryMessage(sql) {
269
- const io = this._io
270
- .start()
271
- .writeInt8(Protocol.FrontendMessageCode.Query)
272
- .writeInt32BE(0) // Preserve header
273
- .writeCString(sql || '', 'utf8');
260
+ const io = this._io.start();
261
+ io.writeInt8(Protocol.FrontendMessageCode.Query);
262
+ io.writeInt32BE(0); // Preserve header
263
+ io.writeCString(sql || '', 'utf8');
274
264
  return setLengthAndFlush(io, 1);
275
265
  }
276
266
  getFunctionCallMessage(args) {
@@ -279,12 +269,11 @@ export class Frontend {
279
269
  const fl = formats.length;
280
270
  const l = values.length;
281
271
  let i;
282
- const io = this._io
283
- .start()
284
- .writeInt8(Protocol.FrontendMessageCode.FunctionCall)
285
- .writeInt32BE(0) // Preserve header
286
- .writeInt32BE(functionId)
287
- .writeInt16BE(fl);
272
+ const io = this._io.start();
273
+ io.writeInt8(Protocol.FrontendMessageCode.FunctionCall);
274
+ io.writeInt32BE(0); // Preserve header
275
+ io.writeInt32BE(functionId);
276
+ io.writeInt16BE(fl);
288
277
  for (i = 0; i < fl; i++)
289
278
  io.writeInt16BE(formats[i]);
290
279
  io.writeInt16BE(l);
@@ -293,8 +282,10 @@ export class Frontend {
293
282
  v = values[i];
294
283
  if (v == null)
295
284
  io.writeInt32BE(-1);
296
- else
297
- io.writeInt32BE(v.length).writeBuffer(v);
285
+ else {
286
+ io.writeInt32BE(v.length);
287
+ io.writeBytes(v);
288
+ }
298
289
  }
299
290
  io.writeInt16BE(resultFormat ?? DataFormat.text);
300
291
  return setLengthAndFlush(io, 1);
@@ -315,11 +306,10 @@ export class Frontend {
315
306
  return StaticCopyDoneBuffer;
316
307
  }
317
308
  getCopyFailMessage(message) {
318
- const io = this._io
319
- .start()
320
- .writeInt8(Protocol.FrontendMessageCode.CopyFail)
321
- .writeInt32BE(0) // Preserve header
322
- .writeCString(message || '', 'utf8');
309
+ const io = this._io.start();
310
+ io.writeInt8(Protocol.FrontendMessageCode.CopyFail);
311
+ io.writeInt32BE(0); // Preserve header
312
+ io.writeCString(message || '', 'utf8');
323
313
  return setLengthAndFlush(io, 1);
324
314
  }
325
315
  getFlushMessage() {
@@ -333,6 +323,6 @@ export class Frontend {
333
323
  }
334
324
  }
335
325
  function setLengthAndFlush(io, lengthOffset) {
336
- io.buffer.writeUInt32BE(io.length - lengthOffset, lengthOffset);
326
+ io.buffer.writeUInt32BE(io.size - lengthOffset, lengthOffset);
337
327
  return io.flush();
338
328
  }
@@ -22,8 +22,6 @@ export declare class PgSocket extends SafeEventEmitter {
22
22
  private _secretKey?;
23
23
  private _protocolNegotiation?;
24
24
  private _captureQueue;
25
- private _pendingWrites;
26
- private _flushScheduled;
27
25
  private _hosts;
28
26
  private _hostIndex;
29
27
  private _sessionAttrsChecked;
@@ -235,39 +233,14 @@ export declare class PgSocket extends SafeEventEmitter {
235
233
  protected _handleNegotiateProtocolVersion(msg: Protocol.NegotiateProtocolVersionMessage): void;
236
234
  protected _handleBackendKeyData(msg: Protocol.BackendKeyDataMessage): void;
237
235
  protected _handleCommandComplete(msg: any): Protocol.CommandCompleteMessage;
238
- /**
239
- * Queues `data` for the socket instead of writing it straight through:
240
- * everything handed to _send() during the same synchronous burst (e.g.
241
- * many concurrent query() calls fired via Promise.all over one
242
- * connection) is flushed together on the next tick, corked, so Node
243
- * turns the whole batch into a single underlying writev rather than one
244
- * socket write per call. Measured against postgres.js, which coalesces
245
- * the same way at the application level (its connection.js write()/
246
- * nextWrite() pair, flushing on a 1KB threshold or setImmediate): 50
247
- * concurrent prepared executes cost it 3 socket writes where this cost
248
- * us 50, and that write path was the single largest non-idle item in a
249
- * CPU profile of the scenario.
250
- *
251
- * nextTick rather than setImmediate, deliberately: it still batches a
252
- * whole synchronous burst, but a lone query doesn't have to wait for the
253
- * event loop's check phase before its bytes go out - which would trade
254
- * away the sequential/single-query scenarios to win the concurrent ones.
255
- *
256
- * Returns whether the socket could accept the data at all; the write
257
- * itself is reported through `cb` (and a socket that dies before the
258
- * flush rejects every pending capture via _failPendingCaptures()).
259
- */
260
236
  protected _send(data: Buffer | Buffer[], cb?: Callback): boolean;
261
237
  /**
262
- * Writes COPY bytes straight through instead of queueing them for the
263
- * next tick like _send() does. Two reasons: during a copy the capture
264
- * queue holds exactly one entry (the Query that opened it), so _send()'s
265
- * "batch only when more than one request is in flight" test would never
266
- * fire and every chunk would be written on its own anyway; and the
267
- * caller needs write()'s own return value to know when to stop, which a
268
- * deferred write cannot give it.
238
+ * Same write as _send(), but reporting backpressure instead of
239
+ * writability: a COPY IN producer needs write()'s own return value to
240
+ * know when to stop pushing, whereas _send()'s callers only need to know
241
+ * whether the socket could take the bytes at all. Kept separate rather
242
+ * than folded into _send() precisely so those two meanings of `false`
243
+ * cannot be confused at a call site.
269
244
  */
270
245
  protected _sendCopy(data: Buffer | Buffer[], cb?: Callback): boolean;
271
- /** Arrow property, not a method: used as a bare process.nextTick callback. */
272
- private _flushPendingWrites;
273
246
  }
@@ -26,8 +26,6 @@ export class PgSocket extends SafeEventEmitter {
26
26
  _secretKey;
27
27
  _protocolNegotiation;
28
28
  _captureQueue = new DoublyLinked();
29
- _pendingWrites = [];
30
- _flushScheduled = false;
31
29
  _hosts = [];
32
30
  _hostIndex = 0;
33
31
  _sessionAttrsChecked = false;
@@ -421,9 +419,6 @@ export class PgSocket extends SafeEventEmitter {
421
419
  this._processID = undefined;
422
420
  this._secretKey = undefined;
423
421
  this._saslSession = undefined;
424
- // Anything still queued belonged to the connection being reset - it
425
- // must never reach a freshly connected socket.
426
- this._pendingWrites = [];
427
422
  }
428
423
  _handleConnect() {
429
424
  const socket = this._socket;
@@ -740,65 +735,38 @@ export class PgSocket extends SafeEventEmitter {
740
735
  result.rowCount = parseInt(m[2], 10);
741
736
  return result;
742
737
  }
743
- /**
744
- * Queues `data` for the socket instead of writing it straight through:
745
- * everything handed to _send() during the same synchronous burst (e.g.
746
- * many concurrent query() calls fired via Promise.all over one
747
- * connection) is flushed together on the next tick, corked, so Node
748
- * turns the whole batch into a single underlying writev rather than one
749
- * socket write per call. Measured against postgres.js, which coalesces
750
- * the same way at the application level (its connection.js write()/
751
- * nextWrite() pair, flushing on a 1KB threshold or setImmediate): 50
752
- * concurrent prepared executes cost it 3 socket writes where this cost
753
- * us 50, and that write path was the single largest non-idle item in a
754
- * CPU profile of the scenario.
755
- *
756
- * nextTick rather than setImmediate, deliberately: it still batches a
757
- * whole synchronous burst, but a lone query doesn't have to wait for the
758
- * event loop's check phase before its bytes go out - which would trade
759
- * away the sequential/single-query scenarios to win the concurrent ones.
760
- *
761
- * Returns whether the socket could accept the data at all; the write
762
- * itself is reported through `cb` (and a socket that dies before the
763
- * flush rejects every pending capture via _failPendingCaptures()).
764
- */
765
738
  _send(data, cb) {
766
- if (!this._socket || !this._socket.writable)
739
+ const socket = this._socket;
740
+ if (!socket || !socket.writable)
767
741
  return false;
768
- if (Array.isArray(data)) {
742
+ if (!Array.isArray(data)) {
743
+ socket.write(data, cb);
744
+ return true;
745
+ }
746
+ socket.cork();
747
+ try {
769
748
  const l = data.length;
770
- for (let i = 0; i < l; i++)
771
- this._pendingWrites.push({
772
- data: data[i],
773
- cb: i === l - 1 ? cb : undefined,
774
- });
749
+ let i;
750
+ for (i = 0; i < l; i++)
751
+ socket.write(data[i], i === l - 1 ? cb : undefined);
775
752
  }
776
- else
777
- this._pendingWrites.push({ data, cb });
778
- if (this._captureQueue.length > 1) {
779
- if (!this._flushScheduled) {
780
- this._flushScheduled = true;
781
- process.nextTick(this._flushPendingWrites);
782
- }
753
+ finally {
754
+ socket.uncork();
783
755
  }
784
- else
785
- this._flushPendingWrites();
786
756
  return true;
787
757
  }
788
758
  /**
789
- * Writes COPY bytes straight through instead of queueing them for the
790
- * next tick like _send() does. Two reasons: during a copy the capture
791
- * queue holds exactly one entry (the Query that opened it), so _send()'s
792
- * "batch only when more than one request is in flight" test would never
793
- * fire and every chunk would be written on its own anyway; and the
794
- * caller needs write()'s own return value to know when to stop, which a
795
- * deferred write cannot give it.
759
+ * Same write as _send(), but reporting backpressure instead of
760
+ * writability: a COPY IN producer needs write()'s own return value to
761
+ * know when to stop pushing, whereas _send()'s callers only need to know
762
+ * whether the socket could take the bytes at all. Kept separate rather
763
+ * than folded into _send() precisely so those two meanings of `false`
764
+ * cannot be confused at a call site.
796
765
  */
797
766
  _sendCopy(data, cb) {
798
767
  const socket = this._socket;
799
768
  if (!socket || !socket.writable)
800
769
  return false;
801
- this._flushPendingWrites();
802
770
  if (!Array.isArray(data))
803
771
  return socket.write(data, cb);
804
772
  socket.cork();
@@ -814,27 +782,4 @@ export class PgSocket extends SafeEventEmitter {
814
782
  socket.uncork();
815
783
  }
816
784
  }
817
- /** Arrow property, not a method: used as a bare process.nextTick callback. */
818
- _flushPendingWrites = () => {
819
- this._flushScheduled = false;
820
- const pending = this._pendingWrites;
821
- if (!pending.length)
822
- return;
823
- this._pendingWrites = [];
824
- const socket = this._socket;
825
- if (!socket || !socket.writable)
826
- return;
827
- socket.cork();
828
- try {
829
- const l = pending.length;
830
- let i;
831
- for (i = 0; i < l; i++) {
832
- const { data, cb } = pending[i];
833
- socket.write(data, cb);
834
- }
835
- }
836
- finally {
837
- socket.uncork();
838
- }
839
- };
840
785
  }
@@ -106,7 +106,7 @@ export class PgOutputDecoder {
106
106
  const lsn = readLsn(io);
107
107
  const prefix = io.readCString();
108
108
  const length = io.readUInt32BE();
109
- return { kind: 'message', prefix, lsn, content: io.readBuffer(length) };
109
+ return { kind: 'message', prefix, lsn, content: io.readBytes(length) };
110
110
  }
111
111
  default:
112
112
  return { kind: 'unknown', code };
@@ -134,7 +134,7 @@ export class PgOutputDecoder {
134
134
  }
135
135
  else {
136
136
  const length = io.readUInt32BE();
137
- out[column.name] = io.readBuffer(length).toString('utf8');
137
+ out[column.name] = io.readBytes(length).toString('utf8');
138
138
  }
139
139
  }
140
140
  return out;
@@ -1,37 +1,19 @@
1
- import { BufferReader } from './buffer-reader.js';
1
+ import { FlexyBuffer } from 'flexy-buffer';
2
2
  export interface SmartBufferConfig {
3
3
  pageSize?: number;
4
4
  maxLength?: number;
5
- houseKeepInterval?: number;
5
+ houseKeepMs?: number;
6
6
  }
7
- export declare class SmartBuffer extends BufferReader {
7
+ /**
8
+ * Adds the PostgreSQL wire format's two string encodings on top of
9
+ * flexy-buffer's `FlexyBuffer`: a NUL-terminated C string, and a
10
+ * length-prefixed string where a `null`/`undefined` value is written as a
11
+ * length of -1 with no bytes following.
12
+ */
13
+ export declare class SmartBuffer extends FlexyBuffer {
8
14
  static DEFAULT_PAGE_SIZE: number;
9
15
  static DEFAULT_MAX_SIZE: number;
10
- private readonly _houseKeepInterval;
11
- private _houseKeepTimer?;
12
- private _stMaxPages;
13
- private _length;
14
- readonly pageSize: number;
15
- readonly maxSize: number;
16
16
  constructor(cfg?: SmartBufferConfig);
17
- get capacity(): number;
18
- get length(): number;
19
- start(): this;
20
- flush(): Buffer;
21
- growSize(len: number): this;
22
- writeCString(str: string, encoding?: BufferEncoding): this;
23
- writeLString(str?: string, encoding?: BufferEncoding): this;
24
- writeString(str: string, encoding?: BufferEncoding): this;
25
- writeInt8(n: number): this;
26
- writeUInt8(n: number): this;
27
- writeUInt16BE(n: number): this;
28
- writeUInt32BE(n: number): this;
29
- writeInt16BE(n: number): this;
30
- writeInt32BE(n: number): this;
31
- writeBigInt64BE(n: bigint | number): this;
32
- writeFloatBE(n: number): this;
33
- writeDoubleBE(n: number): this;
34
- writeBuffer(buffer: Buffer): this;
35
- private ensureSize;
36
- private _houseKeep;
17
+ writeCString(str: string, encoding?: BufferEncoding): number;
18
+ writeLString(str?: string, encoding?: BufferEncoding): number;
37
19
  }