@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
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { INT4Length } from "./constants";
|
|
2
2
|
import { PostgresError } from "../error";
|
|
3
|
-
|
|
3
|
+
import { handlers } from "./types";
|
|
4
4
|
const POSTGRES_EPOCH_MS = 946684800000;
|
|
5
5
|
export class ConnectionResponseBuffer {
|
|
6
6
|
constructor(buffer) {
|
|
@@ -10,6 +10,25 @@ export class ConnectionResponseBuffer {
|
|
|
10
10
|
static from(buffer) {
|
|
11
11
|
return new ConnectionResponseBuffer(buffer);
|
|
12
12
|
}
|
|
13
|
+
hasMore() {
|
|
14
|
+
return this.caret < this.buffer.length;
|
|
15
|
+
}
|
|
16
|
+
skipBytes(byteCount) {
|
|
17
|
+
this.caret += byteCount;
|
|
18
|
+
}
|
|
19
|
+
hasFullPacket() {
|
|
20
|
+
const availableBytes = this.buffer.length - this.caret;
|
|
21
|
+
if (availableBytes < 5)
|
|
22
|
+
return false;
|
|
23
|
+
const packetLength = this.buffer.readInt32BE(this.caret + 1);
|
|
24
|
+
if (availableBytes < 1 + packetLength)
|
|
25
|
+
return false;
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
getResidualBuffer() {
|
|
29
|
+
return this.buffer.subarray(this.caret);
|
|
30
|
+
}
|
|
31
|
+
// ------ primitives ------
|
|
13
32
|
readChar() {
|
|
14
33
|
const char = String.fromCharCode(this.buffer[this.caret]);
|
|
15
34
|
this.caret += 1;
|
|
@@ -36,109 +55,16 @@ export class ConnectionResponseBuffer {
|
|
|
36
55
|
this.caret += length;
|
|
37
56
|
return text;
|
|
38
57
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
readBinaryDate() {
|
|
43
|
-
const daysSince2000 = this.readInt32();
|
|
44
|
-
const ms = POSTGRES_EPOCH_MS + (daysSince2000 * 86400000);
|
|
45
|
-
return new Date(ms);
|
|
46
|
-
}
|
|
47
|
-
readByte() {
|
|
48
|
-
return this.buffer[this.caret++];
|
|
49
|
-
}
|
|
50
|
-
readBinaryTimestamp() {
|
|
51
|
-
const microSecondsSince2000 = this.readInt64();
|
|
52
|
-
const msSince2000 = Number(microSecondsSince2000 / 1000);
|
|
53
|
-
return new Date(POSTGRES_EPOCH_MS + msSince2000);
|
|
54
|
-
}
|
|
55
|
-
readBinaryTime() {
|
|
56
|
-
const microSecondsSinceMidnight = this.readInt64();
|
|
57
|
-
const totalMs = Number(microSecondsSinceMidnight / 1000);
|
|
58
|
-
const seconds = Math.floor(totalMs / 1000);
|
|
59
|
-
const ms = totalMs % 1000;
|
|
60
|
-
const minutes = Math.floor(seconds / 60);
|
|
61
|
-
const hours = Math.floor(minutes / 60);
|
|
62
|
-
return `${String(hours).padStart(2, '0')}:${String(minutes % 60).padStart(2, '0')}:${String(seconds % 60).padStart(2, '0')}.${String(ms).padStart(3, '0')}`;
|
|
63
|
-
}
|
|
64
|
-
skipBytes(byteCount) {
|
|
65
|
-
this.caret += byteCount;
|
|
66
|
-
}
|
|
67
|
-
hasFullPacket() {
|
|
68
|
-
const availableBytes = this.buffer.length - this.caret;
|
|
69
|
-
if (availableBytes < 5)
|
|
70
|
-
return false;
|
|
71
|
-
const packetLength = this.buffer.readInt32BE(this.caret + 1);
|
|
72
|
-
if (availableBytes < 1 + packetLength)
|
|
73
|
-
return false;
|
|
74
|
-
return true;
|
|
75
|
-
}
|
|
76
|
-
getResidualBuffer() {
|
|
77
|
-
return this.buffer.subarray(this.caret);
|
|
78
|
-
}
|
|
79
|
-
readBool() {
|
|
80
|
-
const value = this.buffer[this.caret] !== 0;
|
|
81
|
-
this.caret++;
|
|
58
|
+
readUInt16() {
|
|
59
|
+
const value = this.buffer.readUInt16BE(this.caret);
|
|
60
|
+
this.caret += 2;
|
|
82
61
|
return value;
|
|
83
62
|
}
|
|
84
|
-
|
|
85
|
-
const value = this.buffer.
|
|
86
|
-
this.caret +=
|
|
63
|
+
readUInt32() {
|
|
64
|
+
const value = this.buffer.readUInt32BE(this.caret);
|
|
65
|
+
this.caret += 4;
|
|
87
66
|
return value;
|
|
88
67
|
}
|
|
89
|
-
readInt64() {
|
|
90
|
-
const hi = this.buffer.readInt32BE(this.caret);
|
|
91
|
-
const lo = this.buffer.readUInt32BE(this.caret + 4);
|
|
92
|
-
this.caret += 8;
|
|
93
|
-
return (hi * 4294967296) + lo;
|
|
94
|
-
}
|
|
95
|
-
readNumeric() {
|
|
96
|
-
const ndigits = this.readInt16();
|
|
97
|
-
const weight = this.readInt16();
|
|
98
|
-
const sign = this.readInt16();
|
|
99
|
-
const dscale = this.readInt16();
|
|
100
|
-
if (sign === 0xC000 || sign === -16384)
|
|
101
|
-
return 'NaN';
|
|
102
|
-
const digits = new Array(ndigits);
|
|
103
|
-
for (let i = 0; i < ndigits; i++) {
|
|
104
|
-
digits[i] = this.readInt16();
|
|
105
|
-
}
|
|
106
|
-
const highExp = Math.max(weight, 0);
|
|
107
|
-
const lowExp = Math.min(weight - ndigits + 1, -1);
|
|
108
|
-
let intPart = '';
|
|
109
|
-
for (let exp = highExp; exp >= 0; exp--) {
|
|
110
|
-
const idx = weight - exp;
|
|
111
|
-
const digit = (idx >= 0 && idx < ndigits) ? digits[idx] : 0;
|
|
112
|
-
intPart += exp === highExp ? String(digit) : String(digit).padStart(4, '0');
|
|
113
|
-
}
|
|
114
|
-
if (intPart === '')
|
|
115
|
-
intPart = '0';
|
|
116
|
-
let fracPart = '';
|
|
117
|
-
for (let exp = -1; exp >= lowExp; exp--) {
|
|
118
|
-
const idx = weight - exp;
|
|
119
|
-
const digit = (idx >= 0 && idx < ndigits) ? digits[idx] : 0;
|
|
120
|
-
fracPart += String(digit).padStart(4, '0');
|
|
121
|
-
}
|
|
122
|
-
if (dscale > 0) {
|
|
123
|
-
fracPart = fracPart.padEnd(dscale, '0').slice(0, dscale);
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
fracPart = '';
|
|
127
|
-
}
|
|
128
|
-
const negative = sign === 0x4000 || sign === 16384;
|
|
129
|
-
const result = fracPart ? `${intPart}.${fracPart}` : intPart;
|
|
130
|
-
return negative ? `-${result}` : result;
|
|
131
|
-
}
|
|
132
|
-
readBinaryTimetz() {
|
|
133
|
-
const time = this.readBinaryTime();
|
|
134
|
-
const zoneOffsetSeconds = this.readInt32();
|
|
135
|
-
const offsetMinutesTotal = -zoneOffsetSeconds / 60;
|
|
136
|
-
const sign = offsetMinutesTotal >= 0 ? '+' : '-';
|
|
137
|
-
const abs = Math.abs(offsetMinutesTotal);
|
|
138
|
-
const offH = Math.floor(abs / 60);
|
|
139
|
-
const offM = abs % 60;
|
|
140
|
-
return `${time}${sign}${String(offH).padStart(2, '0')}:${String(offM).padStart(2, '0')}`;
|
|
141
|
-
}
|
|
142
68
|
readFloat32() {
|
|
143
69
|
const value = this.buffer.readFloatBE(this.caret);
|
|
144
70
|
this.caret += 4;
|
|
@@ -149,13 +75,8 @@ export class ConnectionResponseBuffer {
|
|
|
149
75
|
this.caret += 8;
|
|
150
76
|
return value;
|
|
151
77
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return buf.toString('hex', 0, 4) + '-' +
|
|
155
|
-
buf.toString('hex', 4, 6) + '-' +
|
|
156
|
-
buf.toString('hex', 6, 8) + '-' +
|
|
157
|
-
buf.toString('hex', 8, 10) + '-' +
|
|
158
|
-
buf.toString('hex', 10, 16);
|
|
78
|
+
readByte() {
|
|
79
|
+
return this.buffer[this.caret++];
|
|
159
80
|
}
|
|
160
81
|
readBytes(length) {
|
|
161
82
|
const result = Buffer.allocUnsafe(length);
|
|
@@ -163,15 +84,23 @@ export class ConnectionResponseBuffer {
|
|
|
163
84
|
this.caret += length;
|
|
164
85
|
return result;
|
|
165
86
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
hash ^= this.buffer[i];
|
|
171
|
-
hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
|
|
172
|
-
}
|
|
173
|
-
return hash >>> 0;
|
|
87
|
+
readBool() {
|
|
88
|
+
const value = this.buffer[this.caret] !== 0;
|
|
89
|
+
this.caret++;
|
|
90
|
+
return value;
|
|
174
91
|
}
|
|
92
|
+
readBigInt64() {
|
|
93
|
+
const value = this.buffer.readBigInt64BE(this.caret);
|
|
94
|
+
this.caret += 8;
|
|
95
|
+
return value;
|
|
96
|
+
}
|
|
97
|
+
readInt64() {
|
|
98
|
+
const hi = this.buffer.readInt32BE(this.caret);
|
|
99
|
+
const lo = this.buffer.readUInt32BE(this.caret + 4);
|
|
100
|
+
this.caret += 8;
|
|
101
|
+
return (hi * 4294967296) + lo;
|
|
102
|
+
}
|
|
103
|
+
// ------ commands ------
|
|
175
104
|
readType() {
|
|
176
105
|
return { type: this.readByte(), length: this.readInt32() - INT4Length };
|
|
177
106
|
}
|
|
@@ -272,136 +201,6 @@ export class ConnectionResponseBuffer {
|
|
|
272
201
|
}
|
|
273
202
|
return columns;
|
|
274
203
|
}
|
|
275
|
-
readDataRow(descriptions, int8toBigint) {
|
|
276
|
-
const fieldsCount = this.readInt16();
|
|
277
|
-
const row = {};
|
|
278
|
-
for (let i = 0; i < fieldsCount; i++) {
|
|
279
|
-
const fieldLength = this.readInt32();
|
|
280
|
-
const desc = descriptions[i];
|
|
281
|
-
const key = desc.name;
|
|
282
|
-
if (fieldLength === -1) {
|
|
283
|
-
row[key] = null;
|
|
284
|
-
continue;
|
|
285
|
-
}
|
|
286
|
-
const oid = desc.typeOID;
|
|
287
|
-
switch (oid) {
|
|
288
|
-
case DataTypeOids.Text:
|
|
289
|
-
case DataTypeOids.Varchar:
|
|
290
|
-
case DataTypeOids.Char:
|
|
291
|
-
case DataTypeOids.Bpchar:
|
|
292
|
-
{
|
|
293
|
-
if (fieldLength <= 32) {
|
|
294
|
-
let cacheForColumn = columnValueCache.get(i);
|
|
295
|
-
if (!cacheForColumn) {
|
|
296
|
-
cacheForColumn = new Map();
|
|
297
|
-
columnValueCache.set(i, cacheForColumn);
|
|
298
|
-
}
|
|
299
|
-
const byteHash = this.getBufferHash(fieldLength);
|
|
300
|
-
let cachedString = cacheForColumn.get(byteHash);
|
|
301
|
-
if (cachedString === undefined) {
|
|
302
|
-
cachedString = this.readRawString(fieldLength);
|
|
303
|
-
if (cacheForColumn.size > 512) {
|
|
304
|
-
cacheForColumn.clear();
|
|
305
|
-
}
|
|
306
|
-
cacheForColumn.set(byteHash, cachedString);
|
|
307
|
-
}
|
|
308
|
-
else {
|
|
309
|
-
this.skipBytes(fieldLength);
|
|
310
|
-
}
|
|
311
|
-
row[key] = cachedString;
|
|
312
|
-
}
|
|
313
|
-
else {
|
|
314
|
-
row[key] = this.readRawString(fieldLength);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
break;
|
|
318
|
-
case DataTypeOids.Int2:
|
|
319
|
-
{
|
|
320
|
-
row[key] = this.readInt16();
|
|
321
|
-
}
|
|
322
|
-
break;
|
|
323
|
-
case DataTypeOids.Int4:
|
|
324
|
-
{
|
|
325
|
-
row[key] = this.readInt32();
|
|
326
|
-
}
|
|
327
|
-
break;
|
|
328
|
-
case DataTypeOids.Int8:
|
|
329
|
-
{
|
|
330
|
-
row[key] = int8toBigint ? this.readBigInt64() : this.readInt64();
|
|
331
|
-
}
|
|
332
|
-
break;
|
|
333
|
-
case DataTypeOids.Float4:
|
|
334
|
-
{
|
|
335
|
-
row[key] = this.readFloat32();
|
|
336
|
-
}
|
|
337
|
-
break;
|
|
338
|
-
case DataTypeOids.Float8:
|
|
339
|
-
{
|
|
340
|
-
row[key] = this.readFloat64();
|
|
341
|
-
}
|
|
342
|
-
break;
|
|
343
|
-
case DataTypeOids.Bool:
|
|
344
|
-
{
|
|
345
|
-
row[key] = this.readBool();
|
|
346
|
-
}
|
|
347
|
-
break;
|
|
348
|
-
case DataTypeOids.Bytea:
|
|
349
|
-
{
|
|
350
|
-
row[key] = this.readBytes(fieldLength);
|
|
351
|
-
}
|
|
352
|
-
break;
|
|
353
|
-
case DataTypeOids.Jsonb:
|
|
354
|
-
{
|
|
355
|
-
this.skipBytes(1);
|
|
356
|
-
row[key] = JSON.parse(this.readRawString(fieldLength - 1));
|
|
357
|
-
}
|
|
358
|
-
break;
|
|
359
|
-
case DataTypeOids.Json:
|
|
360
|
-
{
|
|
361
|
-
row[key] = JSON.parse(this.readRawString(fieldLength));
|
|
362
|
-
}
|
|
363
|
-
break;
|
|
364
|
-
case DataTypeOids.Date:
|
|
365
|
-
{
|
|
366
|
-
row[key] = this.readBinaryDate();
|
|
367
|
-
}
|
|
368
|
-
break;
|
|
369
|
-
case DataTypeOids.Timestamp:
|
|
370
|
-
case DataTypeOids.Timestamptz:
|
|
371
|
-
{
|
|
372
|
-
row[key] = this.readBinaryTimestamp();
|
|
373
|
-
}
|
|
374
|
-
break;
|
|
375
|
-
case DataTypeOids.Uuid:
|
|
376
|
-
{
|
|
377
|
-
row[key] = this.readUuid();
|
|
378
|
-
}
|
|
379
|
-
break;
|
|
380
|
-
case DataTypeOids.Time:
|
|
381
|
-
{
|
|
382
|
-
row[key] = this.readBinaryTime();
|
|
383
|
-
}
|
|
384
|
-
break;
|
|
385
|
-
case DataTypeOids.Timetz:
|
|
386
|
-
{
|
|
387
|
-
row[key] = this.readBinaryTimetz();
|
|
388
|
-
}
|
|
389
|
-
break;
|
|
390
|
-
case DataTypeOids.Numeric:
|
|
391
|
-
{
|
|
392
|
-
row[key] = this.readNumeric();
|
|
393
|
-
}
|
|
394
|
-
break;
|
|
395
|
-
default:
|
|
396
|
-
{
|
|
397
|
-
this.skipBytes(fieldLength);
|
|
398
|
-
row[key] = null;
|
|
399
|
-
}
|
|
400
|
-
break;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
return row;
|
|
404
|
-
}
|
|
405
204
|
readNotificationResponse() {
|
|
406
205
|
this.readInt32();
|
|
407
206
|
const name = this.readCString();
|
|
@@ -419,4 +218,223 @@ export class ConnectionResponseBuffer {
|
|
|
419
218
|
}
|
|
420
219
|
return description;
|
|
421
220
|
}
|
|
221
|
+
// ------ binary types parsers ------
|
|
222
|
+
readBinaryDate() {
|
|
223
|
+
const daysSince2000 = this.readInt32();
|
|
224
|
+
const ms = POSTGRES_EPOCH_MS + (daysSince2000 * 86400000);
|
|
225
|
+
return new Date(ms);
|
|
226
|
+
}
|
|
227
|
+
readBinaryTimestamp() {
|
|
228
|
+
const microSecondsSince2000 = this.readInt64();
|
|
229
|
+
const msSince2000 = Number(microSecondsSince2000 / 1000);
|
|
230
|
+
return new Date(POSTGRES_EPOCH_MS + msSince2000);
|
|
231
|
+
}
|
|
232
|
+
readBinaryTime() {
|
|
233
|
+
const microSecondsSinceMidnight = this.readInt64();
|
|
234
|
+
const totalMs = Number(microSecondsSinceMidnight / 1000);
|
|
235
|
+
const seconds = Math.floor(totalMs / 1000);
|
|
236
|
+
const ms = totalMs % 1000;
|
|
237
|
+
const minutes = Math.floor(seconds / 60);
|
|
238
|
+
const hours = Math.floor(minutes / 60);
|
|
239
|
+
return `${String(hours).padStart(2, '0')}:${String(minutes % 60).padStart(2, '0')}:${String(seconds % 60).padStart(2, '0')}.${String(ms).padStart(3, '0')}`;
|
|
240
|
+
}
|
|
241
|
+
readBinaryTimetz() {
|
|
242
|
+
const time = this.readBinaryTime();
|
|
243
|
+
const zoneOffsetSeconds = this.readInt32();
|
|
244
|
+
const offsetMinutesTotal = -zoneOffsetSeconds / 60;
|
|
245
|
+
const sign = offsetMinutesTotal >= 0 ? '+' : '-';
|
|
246
|
+
const abs = Math.abs(offsetMinutesTotal);
|
|
247
|
+
const offH = Math.floor(abs / 60);
|
|
248
|
+
const offM = abs % 60;
|
|
249
|
+
return `${time}${sign}${String(offH).padStart(2, '0')}:${String(offM).padStart(2, '0')}`;
|
|
250
|
+
}
|
|
251
|
+
readBinaryNumeric() {
|
|
252
|
+
const ndigits = this.readInt16();
|
|
253
|
+
const weight = this.readInt16();
|
|
254
|
+
const sign = this.readInt16();
|
|
255
|
+
const dscale = this.readInt16();
|
|
256
|
+
if (sign === 0xC000 || sign === -16384)
|
|
257
|
+
return 'NaN';
|
|
258
|
+
const digits = new Array(ndigits);
|
|
259
|
+
for (let i = 0; i < ndigits; i++) {
|
|
260
|
+
digits[i] = this.readInt16();
|
|
261
|
+
}
|
|
262
|
+
const highExp = Math.max(weight, 0);
|
|
263
|
+
const lowExp = Math.min(weight - ndigits + 1, -1);
|
|
264
|
+
let intPart = '';
|
|
265
|
+
for (let exp = highExp; exp >= 0; exp--) {
|
|
266
|
+
const idx = weight - exp;
|
|
267
|
+
const digit = (idx >= 0 && idx < ndigits) ? digits[idx] : 0;
|
|
268
|
+
intPart += exp === highExp ? String(digit) : String(digit).padStart(4, '0');
|
|
269
|
+
}
|
|
270
|
+
if (intPart === '')
|
|
271
|
+
intPart = '0';
|
|
272
|
+
let fracPart = '';
|
|
273
|
+
for (let exp = -1; exp >= lowExp; exp--) {
|
|
274
|
+
const idx = weight - exp;
|
|
275
|
+
const digit = (idx >= 0 && idx < ndigits) ? digits[idx] : 0;
|
|
276
|
+
fracPart += String(digit).padStart(4, '0');
|
|
277
|
+
}
|
|
278
|
+
if (dscale > 0) {
|
|
279
|
+
fracPart = fracPart.padEnd(dscale, '0').slice(0, dscale);
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
fracPart = '';
|
|
283
|
+
}
|
|
284
|
+
const negative = sign === 0x4000 || sign === 16384;
|
|
285
|
+
const result = fracPart ? `${intPart}.${fracPart}` : intPart;
|
|
286
|
+
return negative ? `-${result}` : result;
|
|
287
|
+
}
|
|
288
|
+
readBinaryInterval() {
|
|
289
|
+
const microseconds = this.readBigInt64();
|
|
290
|
+
const days = this.readInt32();
|
|
291
|
+
const months = this.readInt32();
|
|
292
|
+
return { months, days, microseconds };
|
|
293
|
+
}
|
|
294
|
+
readBinaryJson(fieldLength) {
|
|
295
|
+
return JSON.parse(this.readRawString(fieldLength));
|
|
296
|
+
}
|
|
297
|
+
readBinaryJsonb(fieldLength) {
|
|
298
|
+
this.skipBytes(1);
|
|
299
|
+
return JSON.parse(this.readRawString(fieldLength - 1));
|
|
300
|
+
}
|
|
301
|
+
readBinaryMacaddr() {
|
|
302
|
+
const bytes = this.readBytes(6);
|
|
303
|
+
return Array.from(bytes)
|
|
304
|
+
.map(b => b.toString(16).padStart(2, '0'))
|
|
305
|
+
.join(':');
|
|
306
|
+
}
|
|
307
|
+
readBinaryOid() {
|
|
308
|
+
return this.readUInt32();
|
|
309
|
+
}
|
|
310
|
+
readBinaryXid() {
|
|
311
|
+
return this.readUInt32();
|
|
312
|
+
}
|
|
313
|
+
readBinaryCid() {
|
|
314
|
+
return this.readUInt32();
|
|
315
|
+
}
|
|
316
|
+
readBinaryRegproc() {
|
|
317
|
+
return this.readUInt32();
|
|
318
|
+
}
|
|
319
|
+
readBinaryLseg() {
|
|
320
|
+
return {
|
|
321
|
+
a: this.readBinaryPoint(),
|
|
322
|
+
b: this.readBinaryPoint(),
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
readBinaryPath() {
|
|
326
|
+
const closed = this.readByte() !== 0;
|
|
327
|
+
const npoints = this.readInt32();
|
|
328
|
+
const points = new Array(npoints);
|
|
329
|
+
for (let i = 0; i < npoints; i++) {
|
|
330
|
+
points[i] = this.readBinaryPoint();
|
|
331
|
+
}
|
|
332
|
+
return { closed, points };
|
|
333
|
+
}
|
|
334
|
+
readBinaryBox() {
|
|
335
|
+
return {
|
|
336
|
+
high: this.readBinaryPoint(),
|
|
337
|
+
low: this.readBinaryPoint(),
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
readBinaryPolygon() {
|
|
341
|
+
const npoints = this.readInt32();
|
|
342
|
+
const points = new Array(npoints);
|
|
343
|
+
for (let i = 0; i < npoints; i++) {
|
|
344
|
+
points[i] = this.readBinaryPoint();
|
|
345
|
+
}
|
|
346
|
+
return { points };
|
|
347
|
+
}
|
|
348
|
+
readBinaryLine() {
|
|
349
|
+
return {
|
|
350
|
+
a: this.readFloat64(),
|
|
351
|
+
b: this.readFloat64(),
|
|
352
|
+
c: this.readFloat64(),
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
readBinaryUuid() {
|
|
356
|
+
const buf = this.readBytes(16);
|
|
357
|
+
return buf.toString('hex', 0, 4) + '-' +
|
|
358
|
+
buf.toString('hex', 4, 6) + '-' +
|
|
359
|
+
buf.toString('hex', 6, 8) + '-' +
|
|
360
|
+
buf.toString('hex', 8, 10) + '-' +
|
|
361
|
+
buf.toString('hex', 10, 16);
|
|
362
|
+
}
|
|
363
|
+
readBinaryArray(fieldLength, elementParser) {
|
|
364
|
+
if (fieldLength === 0)
|
|
365
|
+
return [];
|
|
366
|
+
const ndims = this.readInt32();
|
|
367
|
+
const hasNull = this.readInt32();
|
|
368
|
+
const elementOid = this.readInt32();
|
|
369
|
+
if (ndims === 0)
|
|
370
|
+
return [];
|
|
371
|
+
if (ndims > 1) {
|
|
372
|
+
for (let d = 1; d < ndims; d++) {
|
|
373
|
+
this.readInt32();
|
|
374
|
+
this.readInt32();
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
const dimLength = this.readInt32();
|
|
378
|
+
const lbound = this.readInt32();
|
|
379
|
+
const result = new Array(dimLength);
|
|
380
|
+
for (let i = 0; i < dimLength; i++) {
|
|
381
|
+
const itemLength = this.readInt32();
|
|
382
|
+
if (itemLength === -1) {
|
|
383
|
+
result[i] = null;
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
result[i] = elementParser(itemLength);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
return result;
|
|
390
|
+
}
|
|
391
|
+
readBinaryInet(fieldLength) {
|
|
392
|
+
const family = this.readByte();
|
|
393
|
+
const bits = this.readByte();
|
|
394
|
+
const isCidr = this.readByte();
|
|
395
|
+
const nb = this.readByte();
|
|
396
|
+
if (nb === 4) {
|
|
397
|
+
const b1 = this.readByte();
|
|
398
|
+
const b2 = this.readByte();
|
|
399
|
+
const b3 = this.readByte();
|
|
400
|
+
const b4 = this.readByte();
|
|
401
|
+
return `${b1}.${b2}.${b3}.${b4}`;
|
|
402
|
+
}
|
|
403
|
+
else if (nb === 16) {
|
|
404
|
+
const parts = [];
|
|
405
|
+
for (let i = 0; i < 8; i++) {
|
|
406
|
+
parts.push(this.readUInt16().toString(16));
|
|
407
|
+
}
|
|
408
|
+
return parts.join(':');
|
|
409
|
+
}
|
|
410
|
+
this.skipBytes(fieldLength - 4);
|
|
411
|
+
return '';
|
|
412
|
+
}
|
|
413
|
+
readBinaryPoint() {
|
|
414
|
+
return {
|
|
415
|
+
x: this.readFloat64(),
|
|
416
|
+
y: this.readFloat64()
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
readDataRow(descriptions, int8toBigint) {
|
|
420
|
+
const fieldsCount = this.readInt16();
|
|
421
|
+
const row = {};
|
|
422
|
+
for (let i = 0; i < fieldsCount; i++) {
|
|
423
|
+
const fieldLength = this.readInt32();
|
|
424
|
+
const desc = descriptions[i];
|
|
425
|
+
const key = desc.name;
|
|
426
|
+
if (fieldLength === -1) {
|
|
427
|
+
row[key] = null;
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
const handler = handlers[desc.typeOID];
|
|
431
|
+
if (!handler) {
|
|
432
|
+
this.skipBytes(fieldLength);
|
|
433
|
+
row[key] = undefined;
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
row[key] = handler.read(this, fieldLength, int8toBigint);
|
|
437
|
+
}
|
|
438
|
+
return row;
|
|
439
|
+
}
|
|
422
440
|
}
|
|
@@ -29,16 +29,16 @@ export const ResponseTypes = {
|
|
|
29
29
|
SSLDenied: 78 // "N"
|
|
30
30
|
};
|
|
31
31
|
export const DataTypeOids = {
|
|
32
|
-
Bool: 16,
|
|
32
|
+
Bool: 16, // parameter
|
|
33
33
|
Bytea: 17,
|
|
34
|
-
Char: 18,
|
|
34
|
+
Char: 18, // parameter
|
|
35
35
|
Name: 19,
|
|
36
|
-
Text: 25,
|
|
37
|
-
Varchar: 1043,
|
|
38
|
-
Bpchar: 1042,
|
|
39
|
-
Int2: 21,
|
|
40
|
-
Int4: 23,
|
|
41
|
-
Int8: 20,
|
|
36
|
+
Text: 25, // parameter
|
|
37
|
+
Varchar: 1043, // parameter
|
|
38
|
+
Bpchar: 1042, // parameter
|
|
39
|
+
Int2: 21, // parameter
|
|
40
|
+
Int4: 23, // parameter
|
|
41
|
+
Int8: 20, // parameter
|
|
42
42
|
Float4: 700,
|
|
43
43
|
Float8: 701,
|
|
44
44
|
Numeric: 1700,
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ConnectionRequestBuffer } from "./connection-request-writer";
|
|
2
|
+
import { ConnectionResponseBuffer } from "./connection-response-reader";
|
|
3
|
+
import { DataTypeOid } from "./constants";
|
|
4
|
+
type BindValidator = (value: unknown) => boolean;
|
|
5
|
+
type BindWriter = (request: ConnectionRequestBuffer, value: any) => void;
|
|
6
|
+
type FieldReader = (response: ConnectionResponseBuffer, fieldLength: number, int8toBigint: boolean) => unknown;
|
|
7
|
+
interface BindHandler {
|
|
8
|
+
validate: BindValidator;
|
|
9
|
+
write: BindWriter;
|
|
10
|
+
read: FieldReader;
|
|
11
|
+
}
|
|
12
|
+
export declare const handlers: Partial<Record<DataTypeOid, BindHandler>>;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/protocol/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAA;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAA;AACvE,OAAO,EAAE,WAAW,EAAgB,MAAM,aAAa,CAAA;AAEvD,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAA;AAChD,KAAK,UAAU,GAAG,CAAC,OAAO,EAAE,uBAAuB,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAA;AACxE,KAAK,WAAW,GAAG,CACf,QAAQ,EAAE,wBAAwB,EAClC,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,OAAO,KACpB,OAAO,CAAA;AAEZ,UAAU,WAAW;IACjB,QAAQ,EAAE,aAAa,CAAA;IACvB,KAAK,EAAE,UAAU,CAAA;IACjB,IAAI,EAAE,WAAW,CAAA;CACpB;AASD,eAAO,MAAM,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,CAsY9D,CAAA"}
|