joist-orm 2.3.0-next.4 → 2.3.0-next.40
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/build/codegen.d.ts +1 -1
- package/build/codegen.js +1 -0
- package/build/codegen.js.map +1 -1
- package/build/drivers/PostgresDriver.d.ts +25 -1
- package/build/drivers/PostgresDriver.js +56 -1
- package/build/drivers/PostgresDriver.js.map +1 -1
- package/build/drivers/WireRowData.d.ts +107 -0
- package/build/drivers/WireRowData.js +430 -0
- package/build/drivers/WireRowData.js.map +1 -0
- package/build/drivers/binaryParsers.d.ts +76 -0
- package/build/drivers/binaryParsers.js +482 -0
- package/build/drivers/binaryParsers.js.map +1 -0
- package/build/drivers/patchPgProtocol.d.ts +43 -0
- package/build/drivers/patchPgProtocol.js +274 -0
- package/build/drivers/patchPgProtocol.js.map +1 -0
- package/build/graphql-codegen-export.d.ts +0 -1
- package/build/graphql-export.d.ts +0 -1
- package/build/index.d.ts +1 -2
- package/build/index.js.map +1 -1
- package/build/knex-export.d.ts +0 -1
- package/build/pg-export.d.ts +1 -1
- package/build/pg-export.js +12 -1
- package/build/pg-export.js.map +1 -1
- package/build/pg-migrate.d.ts +1 -1
- package/build/pg-migrate.js +1 -0
- package/build/pg-migrate.js.map +1 -1
- package/build/seed.d.ts +0 -1
- package/build/seed.js.map +1 -1
- package/build/tests-export.d.ts +0 -1
- package/package.json +13 -19
- package/build/codegen.d.ts.map +0 -1
- package/build/drivers/PostgresDriver.d.ts.map +0 -1
- package/build/graphql-codegen-export.d.ts.map +0 -1
- package/build/graphql-export.d.ts.map +0 -1
- package/build/index.d.ts.map +0 -1
- package/build/knex-export.d.ts.map +0 -1
- package/build/pg-export.d.ts.map +0 -1
- package/build/pg-migrate.d.ts.map +0 -1
- package/build/seed.d.ts.map +0 -1
- package/build/tests-export.d.ts.map +0 -1
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setBinaryTypeParser = setBinaryTypeParser;
|
|
4
|
+
exports.getBinaryTypeParser = getBinaryTypeParser;
|
|
5
|
+
exports.registerDatabaseBinaryParsers = registerDatabaseBinaryParsers;
|
|
6
|
+
exports.setSessionTimeZone = setSessionTimeZone;
|
|
7
|
+
exports.binaryTextParser = binaryTextParser;
|
|
8
|
+
exports.binaryArrayParser = binaryArrayParser;
|
|
9
|
+
exports.binaryDateToDate = binaryDateToDate;
|
|
10
|
+
exports.binaryTimestampToDate = binaryTimestampToDate;
|
|
11
|
+
exports.binaryTimestamptzToDate = binaryTimestamptzToDate;
|
|
12
|
+
exports.registerTemporalBinaryParsers = registerTemporalBinaryParsers;
|
|
13
|
+
const joist_core_1 = require("joist-core");
|
|
14
|
+
/**
|
|
15
|
+
* Joist's registry of PostgreSQL *binary-format* cell parsers, used by `WireRowData` for lazy
|
|
16
|
+
* `em.find`/`em.load` results (which request binary output; see `executeRowDataQuery`).
|
|
17
|
+
*
|
|
18
|
+
* This registry is deliberately **separate from `pg.types`**: `pg.types.setTypeParser` and
|
|
19
|
+
* pool/client `TypeOverrides` continue to govern classic *text* results (knex, `pool.query`,
|
|
20
|
+
* non-lazy drivers), while binary cells decode wire-bytes -> values directly — ints via
|
|
21
|
+
* `readInt32BE`, timestamps via µs arithmetic, Temporal values constructed without ever
|
|
22
|
+
* materializing a string. There is no fallback from one registry to the other:
|
|
23
|
+
*
|
|
24
|
+
* - Built-in parsers cover the standard scalar/array types below; `setupLatestPgTypes`
|
|
25
|
+
* registers the date/time parsers appropriate to Date-vs-Temporal mode.
|
|
26
|
+
* - Custom/extension types (native enums, citext, domains, hstore, ...) must be registered
|
|
27
|
+
* explicitly with {@link setBinaryTypeParser} — text-like types can use
|
|
28
|
+
* {@link binaryTextParser}, arrays of registered elements can use {@link binaryArrayParser}.
|
|
29
|
+
* - A query selecting a column whose oid has no registered parser **fails** with a descriptive
|
|
30
|
+
* error (see `WireRowData.setRowDescription`), rather than guessing at a lossy decoding.
|
|
31
|
+
*
|
|
32
|
+
* Values produced here should match what the classic text path produces for the same column
|
|
33
|
+
* (i.e. `numeric` stays a string, `int8` stays a string, Date-mode timestamps become `Date`s),
|
|
34
|
+
* so entities hydrate identically in either mode; Temporal-mode parsers construct
|
|
35
|
+
* `Temporal.PlainDate`/`ZonedDateTime`/etc. directly, and the temporal mappers pass
|
|
36
|
+
* already-constructed instances through.
|
|
37
|
+
*/
|
|
38
|
+
function setBinaryTypeParser(oid, parse) {
|
|
39
|
+
parsers.set(oid, parse);
|
|
40
|
+
}
|
|
41
|
+
/** Returns the registered binary parser for `oid`, i.e. for tests to save/restore. */
|
|
42
|
+
function getBinaryTypeParser(oid) {
|
|
43
|
+
return parsers.get(oid);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Auto-registers binary parsers for the database's text-like dynamic-oid types — native enums
|
|
47
|
+
* and citext, plus their array types — so apps get those for free.
|
|
48
|
+
*
|
|
49
|
+
* `PostgresDriver` calls this lazily before its first lazy query; apps can also call it
|
|
50
|
+
* directly (i.e. at boot) if they want the registrations eagerly. Explicit
|
|
51
|
+
* `setBinaryTypeParser` registrations are never overwritten.
|
|
52
|
+
*/
|
|
53
|
+
async function registerDatabaseBinaryParsers(pool) {
|
|
54
|
+
// Also capture the session's TimeZone, which zones temporal-mode timestamptz loads to match
|
|
55
|
+
// what classic text parsing would have produced (pg renders timestamps in the session zone)
|
|
56
|
+
const [{ rows: settings }, { rows }] = await Promise.all([
|
|
57
|
+
pool.query(`select current_setting('TimeZone') as tz`),
|
|
58
|
+
pool.query(`select t.oid, t.typarray
|
|
59
|
+
from pg_type t
|
|
60
|
+
where t.typtype = 'e'
|
|
61
|
+
or t.typname = 'citext'
|
|
62
|
+
or (t.typtype = 'd' and (select b.typcategory from pg_type b where b.oid = t.typbasetype) = 'S')`),
|
|
63
|
+
]);
|
|
64
|
+
setSessionTimeZone(settings[0].tz);
|
|
65
|
+
for (const row of rows) {
|
|
66
|
+
const oid = Number(row.oid);
|
|
67
|
+
if (getBinaryTypeParser(oid) === undefined)
|
|
68
|
+
setBinaryTypeParser(oid, binaryTextParser);
|
|
69
|
+
const arrayOid = Number(row.typarray);
|
|
70
|
+
if (arrayOid !== 0 && getBinaryTypeParser(arrayOid) === undefined) {
|
|
71
|
+
setBinaryTypeParser(arrayOid, binaryArrayParser);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Sets the session `TimeZone` used to zone temporal-mode `timestamptz` loads; normally captured
|
|
77
|
+
* automatically by {@link registerDatabaseBinaryParsers}. One zone per process — pools with
|
|
78
|
+
* differing session TimeZones are not supported by the binary path.
|
|
79
|
+
*/
|
|
80
|
+
function setSessionTimeZone(timeZone) {
|
|
81
|
+
sessionTimeZone = timeZone === "Etc/UTC" ? "UTC" : timeZone;
|
|
82
|
+
}
|
|
83
|
+
let sessionTimeZone = "UTC";
|
|
84
|
+
/** Decodes a cell's bytes as utf8 text, i.e. for text-like custom types (enums, citext, domains). */
|
|
85
|
+
function binaryTextParser(chunk, start, length) {
|
|
86
|
+
return chunk.toString("utf8", start, start + length);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Decodes a binary array cell into a JS array of element values.
|
|
90
|
+
*
|
|
91
|
+
* The element oid is embedded in the wire format, and each element decodes through this
|
|
92
|
+
* registry — so arrays of any registered type (including custom-registered oids and the
|
|
93
|
+
* mode-appropriate temporal types) work without separate element wiring. Registered for the
|
|
94
|
+
* standard `_type` oids below; register it for custom array oids as needed.
|
|
95
|
+
*/
|
|
96
|
+
function binaryArrayParser(chunk, start, length) {
|
|
97
|
+
const nDims = chunk.readInt32BE(start);
|
|
98
|
+
if (nDims === 0)
|
|
99
|
+
return [];
|
|
100
|
+
const elemOid = chunk.readInt32BE(start + 8);
|
|
101
|
+
const parse = parsers.get(elemOid) ??
|
|
102
|
+
fail(`joist-orm: no binary type parser registered for array element oid ${elemOid}; see setBinaryTypeParser`);
|
|
103
|
+
const dims = [];
|
|
104
|
+
for (let d = 0; d < nDims; d++)
|
|
105
|
+
dims.push(chunk.readInt32BE(start + 12 + d * 8));
|
|
106
|
+
let pos = start + 12 + nDims * 8;
|
|
107
|
+
function readDim(dim) {
|
|
108
|
+
const values = [];
|
|
109
|
+
for (let i = 0; i < dims[dim]; i++) {
|
|
110
|
+
if (dim < nDims - 1) {
|
|
111
|
+
values.push(readDim(dim + 1));
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
const len = chunk.readInt32BE(pos);
|
|
115
|
+
pos += 4;
|
|
116
|
+
if (len === -1) {
|
|
117
|
+
values.push(null);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
values.push(parse(chunk, pos, len));
|
|
121
|
+
pos += len;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return values;
|
|
126
|
+
}
|
|
127
|
+
return readDim(0);
|
|
128
|
+
}
|
|
129
|
+
/** Decodes binary `date` cells to `Date`s, matching postgres-date's text semantics; Date mode. */
|
|
130
|
+
function binaryDateToDate(chunk, start) {
|
|
131
|
+
const days = chunk.readInt32BE(start);
|
|
132
|
+
if (days === INFINITY_DAYS)
|
|
133
|
+
return Infinity;
|
|
134
|
+
if (days === NEG_INFINITY_DAYS)
|
|
135
|
+
return -Infinity;
|
|
136
|
+
const [year, month, day] = civilFromDays(days + PG_EPOCH_DAYS);
|
|
137
|
+
const date = new Date(year, month - 1, day);
|
|
138
|
+
// Mirror postgres-date's fixup for years 0-99 being interpreted as 1900-1999
|
|
139
|
+
if (year < 100)
|
|
140
|
+
date.setFullYear(year);
|
|
141
|
+
return date;
|
|
142
|
+
}
|
|
143
|
+
/** Decodes binary `timestamp` (without zone) cells to local-time `Date`s; Date mode. */
|
|
144
|
+
function binaryTimestampToDate(chunk, start) {
|
|
145
|
+
const pgMicros = chunk.readBigInt64BE(start);
|
|
146
|
+
if (pgMicros === INFINITY_US)
|
|
147
|
+
return Infinity;
|
|
148
|
+
if (pgMicros === NEG_INFINITY_US)
|
|
149
|
+
return -Infinity;
|
|
150
|
+
const { days, us } = splitPgMicros(pgMicros);
|
|
151
|
+
const [year, month, day] = civilFromDays(days);
|
|
152
|
+
const seconds = Math.floor(us / 1_000_000);
|
|
153
|
+
const date = new Date(year, month - 1, day, Math.floor(seconds / 3600), Math.floor((seconds / 60) % 60), seconds % 60, Math.floor((us % 1_000_000) / 1000));
|
|
154
|
+
if (year < 100)
|
|
155
|
+
date.setFullYear(year);
|
|
156
|
+
return date;
|
|
157
|
+
}
|
|
158
|
+
/** Decodes binary `timestamptz` cells to `Date`s (µs floor to ms, like the text parse); Date mode. */
|
|
159
|
+
function binaryTimestamptzToDate(chunk, start) {
|
|
160
|
+
const pgMicros = chunk.readBigInt64BE(start);
|
|
161
|
+
if (pgMicros === INFINITY_US)
|
|
162
|
+
return Infinity;
|
|
163
|
+
if (pgMicros === NEG_INFINITY_US)
|
|
164
|
+
return -Infinity;
|
|
165
|
+
const epochMicros = pgMicros + PG_EPOCH_US;
|
|
166
|
+
let ms = epochMicros / 1000n;
|
|
167
|
+
if (epochMicros % 1000n < 0n)
|
|
168
|
+
ms -= 1n;
|
|
169
|
+
return new Date(Number(ms));
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Registers the Temporal-mode binary parsers: date/time/timestamp/timestamptz cells construct
|
|
173
|
+
* `Temporal` values *directly* from the wire µs/days — no intermediate strings, no
|
|
174
|
+
* `temporalMappers.fromDb` parsing (the mappers pass already-constructed instances through).
|
|
175
|
+
*
|
|
176
|
+
* `timestamptz` matches the text path's zoning exactly: classic parsing zones the value by the
|
|
177
|
+
* offset the session's `TimeZone` rendered (normalizing `+00` to `UTC`), so we compute the
|
|
178
|
+
* session zone's offset at each instant (see `setSessionTimeZone`; the configured
|
|
179
|
+
* `temporal.timeZone` only governs `now`-conversions, not loads).
|
|
180
|
+
*/
|
|
181
|
+
function registerTemporalBinaryParsers() {
|
|
182
|
+
const { Temporal: t } = (0, joist_core_1.requireTemporal)();
|
|
183
|
+
setBinaryTypeParser(oids.DATE, (chunk, start) => {
|
|
184
|
+
const days = chunk.readInt32BE(start);
|
|
185
|
+
if (days === INFINITY_DAYS || days === NEG_INFINITY_DAYS)
|
|
186
|
+
failTemporalInfinity("date");
|
|
187
|
+
const [year, month, day] = civilFromDays(days + PG_EPOCH_DAYS);
|
|
188
|
+
return new t.PlainDate(year, month, day);
|
|
189
|
+
});
|
|
190
|
+
setBinaryTypeParser(1083 /* time */, (chunk, start) => {
|
|
191
|
+
const us = Number(chunk.readBigInt64BE(start));
|
|
192
|
+
const seconds = Math.floor(us / 1_000_000);
|
|
193
|
+
return new t.PlainTime(Math.floor(seconds / 3600), Math.floor((seconds / 60) % 60), seconds % 60, Math.floor((us % 1_000_000) / 1000), us % 1000);
|
|
194
|
+
});
|
|
195
|
+
setBinaryTypeParser(oids.TIMESTAMP, (chunk, start) => {
|
|
196
|
+
const pgMicros = chunk.readBigInt64BE(start);
|
|
197
|
+
if (pgMicros === INFINITY_US || pgMicros === NEG_INFINITY_US)
|
|
198
|
+
failTemporalInfinity("timestamp");
|
|
199
|
+
const { days, us } = splitPgMicros(pgMicros);
|
|
200
|
+
const [year, month, day] = civilFromDays(days);
|
|
201
|
+
const seconds = Math.floor(us / 1_000_000);
|
|
202
|
+
return new t.PlainDateTime(year, month, day, Math.floor(seconds / 3600), Math.floor((seconds / 60) % 60), seconds % 60, Math.floor((us % 1_000_000) / 1000), us % 1000);
|
|
203
|
+
});
|
|
204
|
+
setBinaryTypeParser(oids.TIMESTAMPTZ, (chunk, start) => {
|
|
205
|
+
const pgMicros = chunk.readBigInt64BE(start);
|
|
206
|
+
if (pgMicros === INFINITY_US || pgMicros === NEG_INFINITY_US)
|
|
207
|
+
failTemporalInfinity("timestamptz");
|
|
208
|
+
const instant = t.Instant.fromEpochNanoseconds((pgMicros + PG_EPOCH_US) * 1000n);
|
|
209
|
+
if (sessionTimeZone === "UTC")
|
|
210
|
+
return instant.toZonedDateTimeISO("UTC");
|
|
211
|
+
// Zone by the session zone's offset at this instant, i.e. what pg's text rendering carries
|
|
212
|
+
const zoned = instant.toZonedDateTimeISO(sessionTimeZone);
|
|
213
|
+
const { offset } = zoned;
|
|
214
|
+
return offset === "+00:00" ? zoned.withTimeZone("UTC") : zoned.withTimeZone(offset);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
// Microseconds between the Postgres epoch (2000-01-01) and the Unix epoch (1970-01-01)
|
|
218
|
+
const PG_EPOCH_US = 946684800000000n;
|
|
219
|
+
const PG_EPOCH_DAYS = 10_957;
|
|
220
|
+
const US_PER_DAY = 86400000000n;
|
|
221
|
+
// The wire sentinels for `infinity` / `-infinity` timestamps and dates
|
|
222
|
+
const INFINITY_US = 0x7fffffffffffffffn;
|
|
223
|
+
const NEG_INFINITY_US = -0x8000000000000000n;
|
|
224
|
+
const INFINITY_DAYS = 0x7fffffff;
|
|
225
|
+
const NEG_INFINITY_DAYS = -0x80000000;
|
|
226
|
+
// pg's builtin oids, inlined to avoid importing pg here (these are protocol constants)
|
|
227
|
+
const oids = {
|
|
228
|
+
BOOL: 16,
|
|
229
|
+
BYTEA: 17,
|
|
230
|
+
INT8: 20,
|
|
231
|
+
INT2: 21,
|
|
232
|
+
INT4: 23,
|
|
233
|
+
TEXT: 25,
|
|
234
|
+
OID: 26,
|
|
235
|
+
JSON: 114,
|
|
236
|
+
FLOAT4: 700,
|
|
237
|
+
FLOAT8: 701,
|
|
238
|
+
BPCHAR: 1042,
|
|
239
|
+
VARCHAR: 1043,
|
|
240
|
+
DATE: 1082,
|
|
241
|
+
TIMESTAMP: 1114,
|
|
242
|
+
TIMESTAMPTZ: 1184,
|
|
243
|
+
NUMERIC: 1700,
|
|
244
|
+
UUID: 2950,
|
|
245
|
+
JSONB: 3802,
|
|
246
|
+
};
|
|
247
|
+
const parsers = new Map();
|
|
248
|
+
// The standard scalar builtins; values match what the classic text path produces for the same
|
|
249
|
+
// column, i.e. int8/numeric stay strings, bytea stays a Buffer (byte-exact, where classic pg's
|
|
250
|
+
// binary handling is utf8-lossy)
|
|
251
|
+
setBinaryTypeParser(oids.BOOL, (chunk, start) => chunk[start] !== 0);
|
|
252
|
+
setBinaryTypeParser(oids.INT2, (chunk, start) => chunk.readInt16BE(start));
|
|
253
|
+
setBinaryTypeParser(oids.INT4, (chunk, start) => chunk.readInt32BE(start));
|
|
254
|
+
setBinaryTypeParser(oids.OID, (chunk, start) => chunk.readUInt32BE(start));
|
|
255
|
+
setBinaryTypeParser(oids.INT8, (chunk, start) => chunk.readBigInt64BE(start).toString());
|
|
256
|
+
setBinaryTypeParser(oids.FLOAT4, (chunk, start) => readFloat4(chunk, start));
|
|
257
|
+
setBinaryTypeParser(oids.FLOAT8, (chunk, start) => chunk.readDoubleBE(start));
|
|
258
|
+
setBinaryTypeParser(oids.TEXT, binaryTextParser);
|
|
259
|
+
setBinaryTypeParser(oids.VARCHAR, binaryTextParser);
|
|
260
|
+
setBinaryTypeParser(oids.BPCHAR, binaryTextParser);
|
|
261
|
+
setBinaryTypeParser(19 /* name */, binaryTextParser);
|
|
262
|
+
setBinaryTypeParser(oids.UUID, (chunk, start) => renderUuid(chunk, start));
|
|
263
|
+
setBinaryTypeParser(oids.BYTEA, copyBytes);
|
|
264
|
+
setBinaryTypeParser(oids.JSON, (chunk, start, length) => JSON.parse(chunk.toString("utf8", start, start + length)));
|
|
265
|
+
// jsonb payloads have a 1-byte version prefix before the JSON text
|
|
266
|
+
setBinaryTypeParser(oids.JSONB, (chunk, start, length) => JSON.parse(chunk.toString("utf8", start + 1, start + length)));
|
|
267
|
+
setBinaryTypeParser(oids.NUMERIC, renderNumeric);
|
|
268
|
+
setBinaryTypeParser(3614 /* tsvector */, renderTsVector);
|
|
269
|
+
setBinaryTypeParser(3910 /* tstzrange */, (chunk, start) => renderRange(chunk, start, (c, s) => {
|
|
270
|
+
// pg quotes finite bounds (they contain spaces) but renders infinity bounds bare
|
|
271
|
+
const text = renderTimestamp(c.readBigInt64BE(s), "+00");
|
|
272
|
+
return text === "infinity" || text === "-infinity" ? text : `"${text}"`;
|
|
273
|
+
}));
|
|
274
|
+
// Rendered like pg's text output, which is also what the classic text path yields (no parser)
|
|
275
|
+
setBinaryTypeParser(1083 /* time */, (chunk, start) => renderTimeOfDay(Number(chunk.readBigInt64BE(start))));
|
|
276
|
+
// The standard `_type` array oids; elements decode through the registry (see binaryArrayParser)
|
|
277
|
+
for (const arrayOid of [
|
|
278
|
+
1000, // bool[]
|
|
279
|
+
1001, // bytea[]
|
|
280
|
+
1005, // int2[]
|
|
281
|
+
1007, // int4[]
|
|
282
|
+
1009, // text[]
|
|
283
|
+
1014, // bpchar[]
|
|
284
|
+
1015, // varchar[]
|
|
285
|
+
1016, // int8[]
|
|
286
|
+
1021, // float4[]
|
|
287
|
+
1022, // float8[]
|
|
288
|
+
1182, // date[]
|
|
289
|
+
1183, // time[]
|
|
290
|
+
1115, // timestamp[]
|
|
291
|
+
1185, // timestamptz[]
|
|
292
|
+
1231, // numeric[]
|
|
293
|
+
2951, // uuid[]
|
|
294
|
+
199, // json[]
|
|
295
|
+
3807, // jsonb[]
|
|
296
|
+
3643, // tsvector[]
|
|
297
|
+
3911, // tstzrange[]
|
|
298
|
+
]) {
|
|
299
|
+
setBinaryTypeParser(arrayOid, binaryArrayParser);
|
|
300
|
+
}
|
|
301
|
+
// Default the date/time oids to Date-mode semantics; `setupLatestPgTypes` re-registers the
|
|
302
|
+
// Temporal-mode parsers when the app runs with `temporal` configured
|
|
303
|
+
setBinaryTypeParser(oids.DATE, binaryDateToDate);
|
|
304
|
+
setBinaryTypeParser(oids.TIMESTAMP, binaryTimestampToDate);
|
|
305
|
+
setBinaryTypeParser(oids.TIMESTAMPTZ, binaryTimestamptzToDate);
|
|
306
|
+
/** Splits pg timestamp µs into days-since-1970 and µs-within-day, flooring correctly pre-epoch. */
|
|
307
|
+
function splitPgMicros(pgMicros) {
|
|
308
|
+
const epochMicros = pgMicros + PG_EPOCH_US;
|
|
309
|
+
let days = epochMicros / US_PER_DAY;
|
|
310
|
+
let micros = epochMicros % US_PER_DAY;
|
|
311
|
+
if (micros < 0n) {
|
|
312
|
+
days -= 1n;
|
|
313
|
+
micros += US_PER_DAY;
|
|
314
|
+
}
|
|
315
|
+
return { days: Number(days), us: Number(micros) };
|
|
316
|
+
}
|
|
317
|
+
/** Fails on the ±infinity wire sentinels, which have no Temporal representation. */
|
|
318
|
+
function failTemporalInfinity(type) {
|
|
319
|
+
return fail(`joist-orm: cannot represent an 'infinity' ${type} as a Temporal value`);
|
|
320
|
+
}
|
|
321
|
+
/** Reads a float4 as its shortest round-trip decimal, matching pg's shortest text output. */
|
|
322
|
+
function readFloat4(chunk, start) {
|
|
323
|
+
const value = chunk.readFloatBE(start);
|
|
324
|
+
if (!Number.isFinite(value))
|
|
325
|
+
return value;
|
|
326
|
+
// ±0 as-is: toPrecision would drop -0's sign, and === cannot tell the zeros apart
|
|
327
|
+
if (value === 0)
|
|
328
|
+
return value;
|
|
329
|
+
// The raw float32 -> float64 widening (i.e. 0.1f -> 0.10000000149...) diverges from the text
|
|
330
|
+
// path, which parses pg's shortest repr; find the shortest decimal that round-trips instead
|
|
331
|
+
// (binary32 needs at most 9 significant decimal digits)
|
|
332
|
+
for (let precision = 1; precision <= 9; precision++) {
|
|
333
|
+
const shortest = Number(value.toPrecision(precision));
|
|
334
|
+
if (Math.fround(shortest) === value)
|
|
335
|
+
return shortest;
|
|
336
|
+
}
|
|
337
|
+
return value;
|
|
338
|
+
}
|
|
339
|
+
/** Copies the exact cell bytes, i.e. for bytea values. */
|
|
340
|
+
function copyBytes(chunk, start, length) {
|
|
341
|
+
const cell = Buffer.allocUnsafe(length);
|
|
342
|
+
chunk.copy(cell, 0, start, start + length);
|
|
343
|
+
return cell;
|
|
344
|
+
}
|
|
345
|
+
/** Renders a binary uuid (16 bytes) as the canonical dashed-hex string. */
|
|
346
|
+
function renderUuid(chunk, start) {
|
|
347
|
+
const hex = chunk.toString("hex", start, start + 16);
|
|
348
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
349
|
+
}
|
|
350
|
+
/** Renders a binary numeric (base-10000 digit groups) to pg's text form, i.e. `-12.340`. */
|
|
351
|
+
function renderNumeric(chunk, start) {
|
|
352
|
+
const nDigits = chunk.readInt16BE(start);
|
|
353
|
+
const weight = chunk.readInt16BE(start + 2);
|
|
354
|
+
const sign = chunk.readUInt16BE(start + 4);
|
|
355
|
+
const dscale = chunk.readUInt16BE(start + 6);
|
|
356
|
+
if (sign === 0xc000)
|
|
357
|
+
return "NaN";
|
|
358
|
+
if (sign === 0xd000)
|
|
359
|
+
return "Infinity";
|
|
360
|
+
if (sign === 0xf000)
|
|
361
|
+
return "-Infinity";
|
|
362
|
+
// Integer part: digit groups from `weight` down to 0 (missing groups are zero)
|
|
363
|
+
let integer = "";
|
|
364
|
+
for (let w = weight, i = 0; w >= 0; w--, i++) {
|
|
365
|
+
const group = i < nDigits ? chunk.readUInt16BE(start + 8 + i * 2) : 0;
|
|
366
|
+
integer += integer === "" ? String(group) : String(group).padStart(4, "0");
|
|
367
|
+
}
|
|
368
|
+
if (integer === "")
|
|
369
|
+
integer = "0";
|
|
370
|
+
if (dscale === 0)
|
|
371
|
+
return sign === 0x4000 ? `-${integer}` : integer;
|
|
372
|
+
// Fraction part: the group at weight -k is digits[weight + k]; pad/trim to exactly `dscale` digits
|
|
373
|
+
let fraction = "";
|
|
374
|
+
for (let k = 1; fraction.length < dscale; k++) {
|
|
375
|
+
const i = weight + k;
|
|
376
|
+
const group = i >= 0 && i < nDigits ? chunk.readUInt16BE(start + 8 + i * 2) : 0;
|
|
377
|
+
fraction += String(group).padStart(4, "0");
|
|
378
|
+
}
|
|
379
|
+
fraction = fraction.slice(0, dscale);
|
|
380
|
+
return `${sign === 0x4000 ? "-" : ""}${integer}.${fraction}`;
|
|
381
|
+
}
|
|
382
|
+
/** Renders a binary tsvector (lexeme cstrings + position/weight words) to pg's text form, i.e. `'new':2A`. */
|
|
383
|
+
function renderTsVector(chunk, start) {
|
|
384
|
+
const count = chunk.readInt32BE(start);
|
|
385
|
+
let pos = start + 4;
|
|
386
|
+
const lexemes = [];
|
|
387
|
+
for (let i = 0; i < count; i++) {
|
|
388
|
+
const end = chunk.indexOf(0, pos);
|
|
389
|
+
// pg's output doubles both backslashes and quotes inside lexemes
|
|
390
|
+
const word = chunk.toString("utf8", pos, end).replace(/\\/g, "\\\\").replace(/'/g, "''");
|
|
391
|
+
pos = end + 1;
|
|
392
|
+
const nPositions = chunk.readUInt16BE(pos);
|
|
393
|
+
pos += 2;
|
|
394
|
+
const positions = [];
|
|
395
|
+
for (let p = 0; p < nPositions; p++) {
|
|
396
|
+
// Each word entry packs the weight in the top 2 bits (3=A, 2=B, 1=C, 0=D/default)
|
|
397
|
+
const entry = chunk.readUInt16BE(pos);
|
|
398
|
+
pos += 2;
|
|
399
|
+
positions.push(`${entry & 0x3fff}${weightSuffixes[entry >> 14]}`);
|
|
400
|
+
}
|
|
401
|
+
lexemes.push(positions.length > 0 ? `'${word}':${positions.join(",")}` : `'${word}'`);
|
|
402
|
+
}
|
|
403
|
+
return lexemes.join(" ");
|
|
404
|
+
}
|
|
405
|
+
const weightSuffixes = ["", "C", "B", "A"];
|
|
406
|
+
/** Renders a binary range (flags byte + length-prefixed bounds) to pg's text form, i.e. `["a","b")`. */
|
|
407
|
+
function renderRange(chunk, start, bound) {
|
|
408
|
+
const flags = chunk[start];
|
|
409
|
+
if (flags & 0x01)
|
|
410
|
+
return "empty";
|
|
411
|
+
let pos = start + 1;
|
|
412
|
+
let lower = "";
|
|
413
|
+
let upper = "";
|
|
414
|
+
if (!(flags & 0x08)) {
|
|
415
|
+
const len = chunk.readInt32BE(pos);
|
|
416
|
+
lower = bound(chunk, pos + 4);
|
|
417
|
+
pos += 4 + len;
|
|
418
|
+
}
|
|
419
|
+
if (!(flags & 0x10)) {
|
|
420
|
+
upper = bound(chunk, pos + 4);
|
|
421
|
+
}
|
|
422
|
+
return `${flags & 0x02 ? "[" : "("}${lower},${upper}${flags & 0x04 ? "]" : ")"}`;
|
|
423
|
+
}
|
|
424
|
+
/** Renders days-since-1970 as pg's date text, i.e. `2020-01-02` or `0001-01-01 BC`. */
|
|
425
|
+
function renderDate(epochDays) {
|
|
426
|
+
const { text, bc } = renderDatePart(epochDays);
|
|
427
|
+
return bc ? `${text} BC` : text;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Renders the `YYYY-MM-DD` part, converting astronomical years to pg's BC numbering
|
|
431
|
+
* (astronomical year 0 = `0001 BC`); timestamps append the ` BC` marker after the time/zone.
|
|
432
|
+
*/
|
|
433
|
+
function renderDatePart(epochDays) {
|
|
434
|
+
const [year, month, day] = civilFromDays(epochDays);
|
|
435
|
+
const bc = year <= 0;
|
|
436
|
+
const displayYear = bc ? 1 - year : year;
|
|
437
|
+
return {
|
|
438
|
+
text: `${String(displayYear).padStart(4, "0")}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`,
|
|
439
|
+
bc,
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
/** Renders a binary timestamp (µs since 2000-01-01) to pg's text form, i.e. `2020-01-02 03:04:05.678+00`. */
|
|
443
|
+
function renderTimestamp(pgMicros, suffix) {
|
|
444
|
+
if (pgMicros === INFINITY_US)
|
|
445
|
+
return "infinity";
|
|
446
|
+
if (pgMicros === NEG_INFINITY_US)
|
|
447
|
+
return "-infinity";
|
|
448
|
+
const { days, us } = splitPgMicros(pgMicros);
|
|
449
|
+
const { text: date, bc } = renderDatePart(days);
|
|
450
|
+
return `${date} ${renderTimeOfDay(us)}${suffix}${bc ? " BC" : ""}`;
|
|
451
|
+
}
|
|
452
|
+
/** Renders µs-since-midnight to pg's time text, i.e. `03:04:05.678` with trailing zeros trimmed. */
|
|
453
|
+
function renderTimeOfDay(us) {
|
|
454
|
+
const seconds = Math.floor(us / 1_000_000);
|
|
455
|
+
const hh = String(Math.floor(seconds / 3600)).padStart(2, "0");
|
|
456
|
+
const mm = String(Math.floor((seconds / 60) % 60)).padStart(2, "0");
|
|
457
|
+
const ss = String(seconds % 60).padStart(2, "0");
|
|
458
|
+
// pg renders up to 6 fractional digits with trailing zeros trimmed, and no "." when zero
|
|
459
|
+
let fraction = "";
|
|
460
|
+
const usPart = us % 1_000_000;
|
|
461
|
+
if (usPart > 0)
|
|
462
|
+
fraction = `.${String(usPart).padStart(6, "0")}`.replace(/0+$/, "");
|
|
463
|
+
return `${hh}:${mm}:${ss}${fraction}`;
|
|
464
|
+
}
|
|
465
|
+
/** Converts days-since-1970 to a civil [year, month, day], i.e. Howard Hinnant's algorithm. */
|
|
466
|
+
function civilFromDays(epochDays) {
|
|
467
|
+
const z = epochDays + 719_468;
|
|
468
|
+
const era = Math.floor(z / 146_097);
|
|
469
|
+
const doe = z - era * 146_097;
|
|
470
|
+
const yoe = Math.floor((doe - Math.floor(doe / 1460) + Math.floor(doe / 36524) - Math.floor(doe / 146096)) / 365);
|
|
471
|
+
const y = yoe + era * 400;
|
|
472
|
+
const doy = doe - (365 * yoe + Math.floor(yoe / 4) - Math.floor(yoe / 100));
|
|
473
|
+
const mp = Math.floor((5 * doy + 2) / 153);
|
|
474
|
+
const d = doy - Math.floor((153 * mp + 2) / 5) + 1;
|
|
475
|
+
const m = mp < 10 ? mp + 3 : mp - 9;
|
|
476
|
+
return [m <= 2 ? y + 1 : y, m, d];
|
|
477
|
+
}
|
|
478
|
+
/** Throws an `Error` with `message`. */
|
|
479
|
+
function fail(message) {
|
|
480
|
+
throw new Error(message);
|
|
481
|
+
}
|
|
482
|
+
//# sourceMappingURL=binaryParsers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binaryParsers.js","sourceRoot":"","sources":["../../src/drivers/binaryParsers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Patches pg-protocol at runtime so that DataRow messages are lazy *and* their bytes are
|
|
3
|
+
* immutable, i.e. so `WireRowData` can retain raw row payloads by reference — no per-cell
|
|
4
|
+
* strings, no per-row copies, no arena.
|
|
5
|
+
*
|
|
6
|
+
* We patch at runtime (instead of shipping a patched pg-protocol) so that installing joist-orm
|
|
7
|
+
* requires no package-manager patch steps; see JS-ROW-STORE-DESIGN.md "Distribution". Two
|
|
8
|
+
* prototype methods are replaced, porting brianc/node-postgres#3719 (which may or may not ever
|
|
9
|
+
* land upstream — this patch is how we run its design in production regardless):
|
|
10
|
+
*
|
|
11
|
+
* - `handlePacket` (stable across pg-protocol 1.10-1.15) returns a {@link LazyDataRowMessage}
|
|
12
|
+
* for DataRow packets and delegates every other message type to the original.
|
|
13
|
+
* - `parse` replaces the recycled-scratch buffer management: each socket chunk is parsed *in
|
|
14
|
+
* place*, and only the one message per chunk that straddles a read boundary is reassembled
|
|
15
|
+
* into a buffer of its own, which is handed to that message and never touched again. Every
|
|
16
|
+
* message therefore stays valid for as long as it is held (holding one pins the ~64 KiB chunk
|
|
17
|
+
* it came from) — versus stock pg-protocol, which copies whole chunks into a scratch buffer
|
|
18
|
+
* and compacts it in place over the bytes earlier messages point into.
|
|
19
|
+
*
|
|
20
|
+
* The patch verifies itself by round-tripping synthetic DataRows through a fresh `Parser` —
|
|
21
|
+
* including a message that straddles chunks, retained across later reads that would clobber it
|
|
22
|
+
* under the stock buffer management. On any mismatch (i.e. a future pg-protocol internals
|
|
23
|
+
* rewrite), it un-patches and reports failure so the driver can fall back to classic rows.
|
|
24
|
+
*
|
|
25
|
+
* The lazy message's memoized `fields` getter decodes identically to the original for classic
|
|
26
|
+
* consumers, i.e. pg's own `Result.parseRow(msg.fields)`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function ensureLazyDataRows(): boolean;
|
|
29
|
+
/** A drop-in `DataRowMessage` that defers cell decoding; lazy consumers read `bytes`/`offset`. */
|
|
30
|
+
export declare class LazyDataRowMessage {
|
|
31
|
+
#private;
|
|
32
|
+
readonly length: number;
|
|
33
|
+
/** The row's payload bytes; immutable under our `parse` patch, so safe to retain. */
|
|
34
|
+
readonly bytes: Buffer;
|
|
35
|
+
readonly offset: number;
|
|
36
|
+
readonly name = "dataRow";
|
|
37
|
+
readonly fieldCount: number;
|
|
38
|
+
constructor(length: number,
|
|
39
|
+
/** The row's payload bytes; immutable under our `parse` patch, so safe to retain. */
|
|
40
|
+
bytes: Buffer, offset: number);
|
|
41
|
+
/** Lazily materializes the per-cell strings for classic consumers, i.e. pg's `Result.parseRow`. */
|
|
42
|
+
get fields(): (string | null)[];
|
|
43
|
+
}
|