@minnowdb/core 0.6.9 → 0.7.1
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/dist/block-format/block.js +254 -325
- package/dist/block-format/checksum.js +30 -52
- package/dist/block-format/codecs.js +112 -125
- package/dist/block-format/column.js +187 -205
- package/dist/block-format/index.js +5 -1
- package/dist/block-format/physical.js +371 -387
- package/dist/block-format/types.js +4 -1
- package/dist/block-format/unicode.js +30 -39
- package/dist/date-value.d.ts +5 -0
- package/dist/date-value.js +71 -41
- package/dist/engine/artifact-cache.js +106 -116
- package/dist/engine/batch.js +36 -44
- package/dist/engine/buffered-writer.js +156 -158
- package/dist/engine/byte-estimates.js +20 -22
- package/dist/engine/cache-limits.js +24 -25
- package/dist/engine/cancellation.js +5 -3
- package/dist/engine/catalog.js +64 -73
- package/dist/engine/client.js +715 -780
- package/dist/engine/database.js +15952 -18465
- package/dist/engine/defaults.js +104 -111
- package/dist/engine/errors.js +113 -128
- package/dist/engine/fts.js +233 -280
- package/dist/engine/group-index.js +287 -321
- package/dist/engine/index.js +23 -12
- package/dist/engine/join-index.js +177 -186
- package/dist/engine/keyed-live.js +168 -173
- package/dist/engine/live-api.js +0 -1
- package/dist/engine/live-equal.js +32 -37
- package/dist/engine/live.js +603 -647
- package/dist/engine/memory.js +109 -111
- package/dist/engine/optimizer.d.ts +19 -1
- package/dist/engine/optimizer.js +2642 -2515
- package/dist/engine/point-read.d.ts +4 -2
- package/dist/engine/point-read.js +121 -171
- package/dist/engine/query-api.js +12 -3
- package/dist/engine/query-cache.js +61 -69
- package/dist/engine/query.d.ts +45 -0
- package/dist/engine/query.js +8506 -9375
- package/dist/engine/result-wire.js +221 -252
- package/dist/engine/schema-wire.js +97 -112
- package/dist/engine/schema.js +1099 -1254
- package/dist/engine/sort-keys.js +315 -389
- package/dist/engine/sql-domains.d.ts +7 -1
- package/dist/engine/sql-domains.js +648 -734
- package/dist/engine/sql-driver.js +0 -1
- package/dist/engine/sql-functions.d.ts +11 -0
- package/dist/engine/sql-functions.js +1092 -0
- package/dist/engine/sql-json.js +199 -218
- package/dist/engine/sql-semantics.d.ts +25 -4
- package/dist/engine/sql-semantics.js +579 -513
- package/dist/engine/typed-live.js +271 -293
- package/dist/engine/vector.d.ts +7 -1
- package/dist/engine/vector.js +4513 -4580
- package/dist/engine/worker-host.d.ts +8 -63
- package/dist/engine/worker-host.js +28 -1130
- package/dist/engine/worker-indexeddb.d.ts +1 -0
- package/dist/engine/worker-indexeddb.js +3 -0
- package/dist/engine/worker-memory.d.ts +1 -0
- package/dist/engine/worker-memory.js +3 -0
- package/dist/engine/worker-opfs.d.ts +1 -0
- package/dist/engine/worker-opfs.js +3 -0
- package/dist/engine/worker-server.d.ts +93 -0
- package/dist/engine/worker-server.js +999 -0
- package/dist/engine/worker-store-indexeddb.d.ts +2 -0
- package/dist/engine/worker-store-indexeddb.js +11 -0
- package/dist/engine/worker-store-memory.d.ts +2 -0
- package/dist/engine/worker-store-memory.js +6 -0
- package/dist/engine/worker-store-opfs.d.ts +2 -0
- package/dist/engine/worker-store-opfs.js +9 -0
- package/dist/engine/worker.js +0 -12
- package/dist/engine/write-block-planner.js +93 -100
- package/dist/plan/index.js +15 -16
- package/dist/plan/model.d.ts +9 -1
- package/dist/plan/model.js +20 -27
- package/dist/storage/index.js +0 -12
- package/dist/storage/indexeddb.js +11776 -13171
- package/dist/storage/memory.js +1198 -1241
- package/dist/storage/opfs/files.js +238 -295
- package/dist/storage/opfs/index.js +9 -3
- package/dist/storage/opfs/leader.js +4386 -4856
- package/dist/storage/opfs/rpc.js +223 -259
- package/dist/storage/opfs/snapshot-ledger.js +219 -260
- package/dist/storage/opfs/store.js +884 -1003
- package/dist/storage/persistence.js +59 -74
- package/dist/storage/snapshot-stream.js +788 -826
- package/dist/storage/snapshot.js +36 -37
- package/dist/storage/toolkit/extents.js +444 -520
- package/dist/storage/toolkit/index.js +28 -29
- package/dist/storage/toolkit/record-core.js +5792 -6377
- package/dist/storage/toolkit/sync-file.js +34 -42
- package/dist/storage/toolkit/wal.js +92 -127
- package/dist/storage/toolkit/wire.js +232 -256
- package/dist/storage/types.js +2952 -3228
- package/dist/testing/block-store-conformance.js +1556 -1629
- package/dist/testing/index.js +310 -291
- package/dist/testing/opfs-shim.js +280 -312
- package/dist/testing/simulator.js +496 -534
- package/dist/testing/sqllogictest.js +425 -365
- package/dist/transactions/index.js +1464 -1712
- package/dist/worker-protocol/index.js +70 -69
- package/package.json +20 -2
- package/postgres-feature-profile.json +15 -5
- package/sql-feature-matrix.json +252 -2
|
@@ -9,10 +9,11 @@ export interface PointReadShape {
|
|
|
9
9
|
/** Conjunctive equalities, in predicate order; may repeat a column. */
|
|
10
10
|
equalities: PointReadEquality[];
|
|
11
11
|
/** Plain column projections, in select order. */
|
|
12
|
+
/** Projected columns, or "*" for a bare wildcard the catalog expands at execution. */
|
|
12
13
|
select: Array<{
|
|
13
14
|
column: string;
|
|
14
15
|
alias: string;
|
|
15
|
-
}
|
|
16
|
+
}> | "*";
|
|
16
17
|
}
|
|
17
18
|
/** The statement-shaped half of the analysis, computed once per cached plan. */
|
|
18
19
|
interface PointReadTemplate {
|
|
@@ -24,10 +25,11 @@ interface PointReadTemplate {
|
|
|
24
25
|
column: string;
|
|
25
26
|
parameter: number;
|
|
26
27
|
}>;
|
|
28
|
+
/** Projected columns, or "*" for a bare wildcard the catalog expands at execution. */
|
|
27
29
|
select: Array<{
|
|
28
30
|
column: string;
|
|
29
31
|
alias: string;
|
|
30
|
-
}
|
|
32
|
+
}> | "*";
|
|
31
33
|
}
|
|
32
34
|
/**
|
|
33
35
|
* Test-only escape hatch and counters. Not exported from any public entry point: in-repo
|
|
@@ -1,190 +1,140 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shape analysis for the keyed point-read fast path: a single-table conjunction of
|
|
3
|
-
* column-equals-literal predicates that covers the table's unique key, projecting bare
|
|
4
|
-
* columns — plain or logical-domain typed, since domain scalars externalize through the
|
|
5
|
-
* same result boundary. Such a statement addresses at most one row, so execution can skip parameter
|
|
6
|
-
* binding, plan cloning, streamed-view construction, and the vector pipeline entirely and
|
|
7
|
-
* answer from cached decoded blocks. Anything this module cannot prove eligible falls back to
|
|
8
|
-
* the ordinary executor, which stays the authority on errors and semantics.
|
|
9
|
-
*/
|
|
10
1
|
import { dateMilliseconds } from "../date-value.js";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
*/
|
|
16
|
-
export const pointReadTestHooks = {
|
|
17
|
-
disabled: false,
|
|
18
|
-
attempted: 0,
|
|
19
|
-
served: 0,
|
|
2
|
+
const pointReadTestHooks = {
|
|
3
|
+
disabled: false,
|
|
4
|
+
attempted: 0,
|
|
5
|
+
served: 0
|
|
20
6
|
};
|
|
21
7
|
const DUAL_TABLE = "(dual)";
|
|
22
|
-
/** A base-table column reference: bare, or qualified by the base source's alias. */
|
|
23
8
|
function baseColumnReference(expression, alias) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return column.includes(".") ? undefined : column;
|
|
9
|
+
if (expression.kind !== "column")
|
|
10
|
+
return void 0;
|
|
11
|
+
const reference = expression.reference;
|
|
12
|
+
const dot = reference.indexOf(".");
|
|
13
|
+
if (dot < 0)
|
|
14
|
+
return reference;
|
|
15
|
+
if (reference.slice(0, dot) !== alias)
|
|
16
|
+
return void 0;
|
|
17
|
+
const column = reference.slice(dot + 1);
|
|
18
|
+
return column.includes(".") ? void 0 : column;
|
|
35
19
|
}
|
|
36
|
-
/** A usable equality operand: a plain non-null literal of a storage type, verified exactly. */
|
|
37
20
|
function equalityValue(value) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (value instanceof Date && Number.isNaN(dateMilliseconds(value)))
|
|
48
|
-
return undefined;
|
|
49
|
-
return value;
|
|
21
|
+
if (value === null)
|
|
22
|
+
return void 0;
|
|
23
|
+
if (typeof value === "number" && !Number.isFinite(value))
|
|
24
|
+
return void 0;
|
|
25
|
+
if (typeof value === "string" && value.startsWith("\0"))
|
|
26
|
+
return void 0;
|
|
27
|
+
if (value instanceof Date && Number.isNaN(dateMilliseconds(value)))
|
|
28
|
+
return void 0;
|
|
29
|
+
return value;
|
|
50
30
|
}
|
|
51
31
|
function templateEquality(expression) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const value = equalityValue(expression.value);
|
|
61
|
-
return value === undefined ? undefined : { value };
|
|
32
|
+
if (expression.kind === "parameter")
|
|
33
|
+
return { parameter: expression.index };
|
|
34
|
+
if (expression.kind !== "literal")
|
|
35
|
+
return void 0;
|
|
36
|
+
if (expression.internalSqlValue === true || expression.sqlDomain !== void 0)
|
|
37
|
+
return void 0;
|
|
38
|
+
const value = equalityValue(expression.value);
|
|
39
|
+
return value === void 0 ? void 0 : { value };
|
|
62
40
|
}
|
|
63
|
-
/**
|
|
64
|
-
* Recognizes the eligible statement shape. Purely syntactic: catalog checks (column existence,
|
|
65
|
-
* types, key coverage, view expansion, physical history) belong to the caller, which falls
|
|
66
|
-
* back to the ordinary executor whenever they cannot be proven.
|
|
67
|
-
*/
|
|
68
41
|
function pointReadTemplate(plan) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
plan.groupBy.length > 0 ||
|
|
79
|
-
plan.having.length > 0 ||
|
|
80
|
-
plan.orderBy.length > 0 ||
|
|
81
|
-
plan.select.length === 0 ||
|
|
82
|
-
plan.predicates.length === 0 ||
|
|
83
|
-
plan.limit !== undefined ||
|
|
84
|
-
plan.offset !== undefined ||
|
|
85
|
-
plan.limitParameter !== undefined ||
|
|
86
|
-
plan.offsetParameter !== undefined ||
|
|
87
|
-
(plan.limitValidationParameters?.length ?? 0) > 0 ||
|
|
88
|
-
(plan.offsetValidationParameters?.length ?? 0) > 0 ||
|
|
89
|
-
plan.limitWithTies === true ||
|
|
90
|
-
plan.distinctWildcard === true ||
|
|
91
|
-
plan.usesStatementDatetime === true ||
|
|
92
|
-
plan.usesSequenceCalls === true ||
|
|
93
|
-
plan.usesVolatileFunctions === true) {
|
|
94
|
-
return undefined;
|
|
95
|
-
}
|
|
96
|
-
const select = [];
|
|
42
|
+
const base = plan.base;
|
|
43
|
+
if (base.table === DUAL_TABLE || base.derived !== void 0 || base.union !== void 0 || base.recursive !== void 0 || base.windowed !== void 0 || base.lateral === true || base.columnAliases !== void 0 || plan.joins.length > 0 || plan.groupBy.length > 0 || plan.having.length > 0 || plan.orderBy.length > 0 || plan.select.length === 0 || plan.predicates.length === 0 || plan.limit !== void 0 || plan.offset !== void 0 || plan.limitParameter !== void 0 || plan.offsetParameter !== void 0 || (plan.limitValidationParameters?.length ?? 0) > 0 || (plan.offsetValidationParameters?.length ?? 0) > 0 || plan.limitWithTies === true || plan.distinctWildcard === true || plan.usesStatementDatetime === true || plan.usesSequenceCalls === true || plan.usesVolatileFunctions === true) {
|
|
44
|
+
return void 0;
|
|
45
|
+
}
|
|
46
|
+
let select = [];
|
|
47
|
+
const first = plan.select[0];
|
|
48
|
+
if (plan.select.length === 1 && first?.expression.kind === "wildcard" && (first.expression.table === void 0 || first.expression.table === base.alias)) {
|
|
49
|
+
select = "*";
|
|
50
|
+
} else {
|
|
97
51
|
for (const item of plan.select) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
const equalities = [];
|
|
104
|
-
for (const predicate of plan.predicates) {
|
|
105
|
-
if (predicate.operator !== "=" || predicate.escape !== undefined)
|
|
106
|
-
return undefined;
|
|
107
|
-
const leftColumn = baseColumnReference(predicate.left, base.alias);
|
|
108
|
-
const rightColumn = baseColumnReference(predicate.right, base.alias);
|
|
109
|
-
const operand = leftColumn !== undefined && rightColumn === undefined
|
|
110
|
-
? templateEquality(predicate.right)
|
|
111
|
-
: rightColumn !== undefined && leftColumn === undefined
|
|
112
|
-
? templateEquality(predicate.left)
|
|
113
|
-
: undefined;
|
|
114
|
-
const column = leftColumn ?? rightColumn;
|
|
115
|
-
if (operand === undefined || column === undefined)
|
|
116
|
-
return undefined;
|
|
117
|
-
equalities.push({ column, ...operand });
|
|
52
|
+
const column = baseColumnReference(item.expression, base.alias);
|
|
53
|
+
if (column === void 0)
|
|
54
|
+
return void 0;
|
|
55
|
+
select.push({ column, alias: item.alias });
|
|
118
56
|
}
|
|
119
|
-
|
|
57
|
+
}
|
|
58
|
+
const equalities = [];
|
|
59
|
+
for (const predicate of plan.predicates) {
|
|
60
|
+
if (predicate.operator !== "=" || predicate.escape !== void 0)
|
|
61
|
+
return void 0;
|
|
62
|
+
const leftColumn = baseColumnReference(predicate.left, base.alias);
|
|
63
|
+
const rightColumn = baseColumnReference(predicate.right, base.alias);
|
|
64
|
+
const operand = leftColumn !== void 0 && rightColumn === void 0 ? templateEquality(predicate.right) : rightColumn !== void 0 && leftColumn === void 0 ? templateEquality(predicate.left) : void 0;
|
|
65
|
+
const column = leftColumn ?? rightColumn;
|
|
66
|
+
if (operand === void 0 || column === void 0)
|
|
67
|
+
return void 0;
|
|
68
|
+
equalities.push({ column, ...operand });
|
|
69
|
+
}
|
|
70
|
+
return { table: base.table, equalities, select };
|
|
120
71
|
}
|
|
121
|
-
const templates = new WeakMap();
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return template;
|
|
72
|
+
const templates = /* @__PURE__ */ new WeakMap();
|
|
73
|
+
function cachedPointReadTemplate(plan) {
|
|
74
|
+
const cached = templates.get(plan);
|
|
75
|
+
if (cached !== void 0)
|
|
76
|
+
return cached;
|
|
77
|
+
const template = pointReadTemplate(plan) ?? null;
|
|
78
|
+
templates.set(plan, template);
|
|
79
|
+
return template;
|
|
130
80
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const equalities = [];
|
|
138
|
-
for (const entry of template.equalities) {
|
|
139
|
-
if ("value" in entry) {
|
|
140
|
-
equalities.push(entry);
|
|
141
|
-
continue;
|
|
142
|
-
}
|
|
143
|
-
const raw = params[entry.parameter];
|
|
144
|
-
if (raw === undefined)
|
|
145
|
-
return undefined;
|
|
146
|
-
const value = equalityValue(raw);
|
|
147
|
-
if (value === undefined)
|
|
148
|
-
return undefined;
|
|
149
|
-
equalities.push({ column: entry.column, value });
|
|
81
|
+
function resolvePointReadShape(template, params) {
|
|
82
|
+
const equalities = [];
|
|
83
|
+
for (const entry of template.equalities) {
|
|
84
|
+
if ("value" in entry) {
|
|
85
|
+
equalities.push(entry);
|
|
86
|
+
continue;
|
|
150
87
|
}
|
|
151
|
-
|
|
88
|
+
const raw = params[entry.parameter];
|
|
89
|
+
if (raw === void 0)
|
|
90
|
+
return void 0;
|
|
91
|
+
const value = equalityValue(raw);
|
|
92
|
+
if (value === void 0)
|
|
93
|
+
return void 0;
|
|
94
|
+
equalities.push({ column: entry.column, value });
|
|
95
|
+
}
|
|
96
|
+
return { table: template.table, equalities, select: template.select };
|
|
152
97
|
}
|
|
153
|
-
const ascendingRuns = new WeakMap();
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
break;
|
|
164
|
-
}
|
|
98
|
+
const ascendingRuns = /* @__PURE__ */ new WeakMap();
|
|
99
|
+
function valuesAreAscending(values) {
|
|
100
|
+
const cached = ascendingRuns.get(values);
|
|
101
|
+
if (cached !== void 0)
|
|
102
|
+
return cached;
|
|
103
|
+
let ascending = true;
|
|
104
|
+
for (let index = 1; index < values.length; index += 1) {
|
|
105
|
+
if ((values[index] ?? 0) < (values[index - 1] ?? 0)) {
|
|
106
|
+
ascending = false;
|
|
107
|
+
break;
|
|
165
108
|
}
|
|
166
|
-
|
|
167
|
-
|
|
109
|
+
}
|
|
110
|
+
ascendingRuns.set(values, ascending);
|
|
111
|
+
return ascending;
|
|
168
112
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
return { begin, end: low };
|
|
113
|
+
function equalRunRange(values, target) {
|
|
114
|
+
let low = 0;
|
|
115
|
+
let high = values.length;
|
|
116
|
+
while (low < high) {
|
|
117
|
+
const middle = low + high >>> 1;
|
|
118
|
+
if ((values[middle] ?? 0) < target)
|
|
119
|
+
low = middle + 1;
|
|
120
|
+
else
|
|
121
|
+
high = middle;
|
|
122
|
+
}
|
|
123
|
+
const begin = low;
|
|
124
|
+
high = values.length;
|
|
125
|
+
while (low < high) {
|
|
126
|
+
const middle = low + high >>> 1;
|
|
127
|
+
if ((values[middle] ?? 0) <= target)
|
|
128
|
+
low = middle + 1;
|
|
129
|
+
else
|
|
130
|
+
high = middle;
|
|
131
|
+
}
|
|
132
|
+
return { begin, end: low };
|
|
190
133
|
}
|
|
134
|
+
export {
|
|
135
|
+
cachedPointReadTemplate,
|
|
136
|
+
equalRunRange,
|
|
137
|
+
pointReadTestHooks,
|
|
138
|
+
resolvePointReadShape,
|
|
139
|
+
valuesAreAscending
|
|
140
|
+
};
|
package/dist/engine/query-api.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export {
|
|
1
|
+
import { bindPlanParameters, bindStatementParameters, compileQuery, compileStatement, executeQuery, referencedColumns } from "./query.js";
|
|
2
|
+
import { optimizePlan, renderPlan } from "./optimizer.js";
|
|
3
|
+
export {
|
|
4
|
+
bindPlanParameters,
|
|
5
|
+
bindStatementParameters,
|
|
6
|
+
compileQuery,
|
|
7
|
+
compileStatement,
|
|
8
|
+
executeQuery,
|
|
9
|
+
optimizePlan,
|
|
10
|
+
referencedColumns,
|
|
11
|
+
renderPlan
|
|
12
|
+
};
|
|
@@ -2,78 +2,70 @@ import { copyDate, dateMilliseconds } from "../date-value.js";
|
|
|
2
2
|
import { estimateValuesBytes } from "./byte-estimates.js";
|
|
3
3
|
import { copyQueryResultExternalization } from "./query.js";
|
|
4
4
|
import { defineSqlResultProperty } from "./sql-semantics.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export function queryResultMemoKey(sql, params) {
|
|
9
|
-
return JSON.stringify([sql, params.map(encodeParameter)]);
|
|
5
|
+
const RESULT_MEMO_MAX_BYTES = 4 * 1024 * 1024;
|
|
6
|
+
function queryResultMemoKey(sql, params) {
|
|
7
|
+
return JSON.stringify([sql, params.map(encodeParameter)]);
|
|
10
8
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (!Number.isFinite(value))
|
|
26
|
-
return { $number: String(value) };
|
|
27
|
-
}
|
|
28
|
-
return value;
|
|
29
|
-
});
|
|
9
|
+
function planMemoKey(plan) {
|
|
10
|
+
return JSON.stringify(plan, (_key, value) => {
|
|
11
|
+
if (value instanceof Date)
|
|
12
|
+
return { $date: dateMilliseconds(value) };
|
|
13
|
+
if (typeof value === "bigint")
|
|
14
|
+
return { $bigint: value.toString() };
|
|
15
|
+
if (typeof value === "number") {
|
|
16
|
+
if (Object.is(value, -0))
|
|
17
|
+
return { $number: "-0" };
|
|
18
|
+
if (!Number.isFinite(value))
|
|
19
|
+
return { $number: String(value) };
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
});
|
|
30
23
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (value instanceof Date)
|
|
48
|
-
defineSqlResultProperty(copy, name, copyDate(value));
|
|
49
|
-
}
|
|
50
|
-
return copy;
|
|
51
|
-
}),
|
|
52
|
-
};
|
|
53
|
-
return copyQueryResultExternalization(result, copy);
|
|
24
|
+
function copyQueryResult(result) {
|
|
25
|
+
const columns = result.columns;
|
|
26
|
+
const copy = {
|
|
27
|
+
columns: [...columns],
|
|
28
|
+
columnDomains: structuredClone(result.columnDomains),
|
|
29
|
+
rows: result.rows.map((row) => {
|
|
30
|
+
const copy2 = { ...row };
|
|
31
|
+
for (const name of columns) {
|
|
32
|
+
const value = copy2[name];
|
|
33
|
+
if (value instanceof Date)
|
|
34
|
+
defineSqlResultProperty(copy2, name, copyDate(value));
|
|
35
|
+
}
|
|
36
|
+
return copy2;
|
|
37
|
+
})
|
|
38
|
+
};
|
|
39
|
+
return copyQueryResultExternalization(result, copy);
|
|
54
40
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return bytes;
|
|
41
|
+
function queryResultRetainedBytes(result) {
|
|
42
|
+
let bytes = 64;
|
|
43
|
+
for (const column of result.columns)
|
|
44
|
+
bytes += 16 + column.length * 2;
|
|
45
|
+
for (const row of result.rows)
|
|
46
|
+
bytes += estimateValuesBytes(Object.values(row));
|
|
47
|
+
return bytes;
|
|
63
48
|
}
|
|
64
49
|
function encodeParameter(value) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
50
|
+
if (value === null)
|
|
51
|
+
return [0];
|
|
52
|
+
if (typeof value === "boolean")
|
|
53
|
+
return [1, value];
|
|
54
|
+
if (typeof value === "number") {
|
|
55
|
+
if (Object.is(value, -0))
|
|
56
|
+
return [2, "-0"];
|
|
57
|
+
return [2, String(value)];
|
|
58
|
+
}
|
|
59
|
+
if (typeof value === "string")
|
|
60
|
+
return [3, value];
|
|
61
|
+
if (value instanceof Date)
|
|
62
|
+
return [4, dateMilliseconds(value)];
|
|
63
|
+
throw new TypeError("Query parameter has an unsupported value");
|
|
79
64
|
}
|
|
65
|
+
export {
|
|
66
|
+
RESULT_MEMO_MAX_BYTES,
|
|
67
|
+
copyQueryResult,
|
|
68
|
+
planMemoKey,
|
|
69
|
+
queryResultMemoKey,
|
|
70
|
+
queryResultRetainedBytes
|
|
71
|
+
};
|
package/dist/engine/query.d.ts
CHANGED
|
@@ -31,6 +31,12 @@ export interface QueryExecutionOptions {
|
|
|
31
31
|
export declare const scalarFunctionNames: ReadonlySet<string>;
|
|
32
32
|
/** Functions whose answer can change without any catalog or input-row change. */
|
|
33
33
|
export declare const volatileScalarFunctionNames: ReadonlySet<string>;
|
|
34
|
+
/**
|
|
35
|
+
* The niladic datetime functions (F051-06/07/08). Their value is the statement's own clock
|
|
36
|
+
* reading, so they are resolved once per execution rather than evaluated per row: every row of
|
|
37
|
+
* one statement sees one instant, both executors agree, and constant folding leaves them alone.
|
|
38
|
+
*/
|
|
39
|
+
export declare const statementDatetimeNames: ReadonlySet<string>;
|
|
34
40
|
export declare function isScalarFunctionName(name: AggregateName | ScalarFunctionName): name is ScalarFunctionName;
|
|
35
41
|
/**
|
|
36
42
|
* Evaluates one scalar function over already-evaluated argument values. Every executor calls
|
|
@@ -40,6 +46,14 @@ export declare function isScalarFunctionName(name: AggregateName | ScalarFunctio
|
|
|
40
46
|
* SUBSTR count characters, not UTF-16 units, matching SQLite and PostgreSQL.
|
|
41
47
|
*/
|
|
42
48
|
export declare function scalarFunctionValue(name: Exclude<ScalarFunctionName, "COALESCE">, values: readonly unknown[]): unknown;
|
|
49
|
+
export type ScalarFunctionEvaluator = (values: readonly unknown[]) => unknown;
|
|
50
|
+
/**
|
|
51
|
+
* The evaluator for one function name, resolved once. A call site that keeps the evaluator
|
|
52
|
+
* skips the name dispatch on every row; the registry functions and the hottest built-ins get
|
|
53
|
+
* a closure of their own, everything else a closure over the general dispatch.
|
|
54
|
+
*/
|
|
55
|
+
export declare function scalarFunctionEvaluator(name: Exclude<ScalarFunctionName, "COALESCE">): ScalarFunctionEvaluator;
|
|
56
|
+
export declare function dateTruncValue(unit: unknown, value: unknown): Date | null;
|
|
43
57
|
/** The output column type of one window: rankings and most aggregates count, MIN/MAX carry. */
|
|
44
58
|
export declare function windowOutputType(window: WindowSpec, innerSchema: readonly SqlColumnSchema[]): SqlColumnType;
|
|
45
59
|
/** Logical domain carried or produced by a window result, when its physical type is not enough. */
|
|
@@ -56,6 +70,14 @@ interface CompileQueryOptions {
|
|
|
56
70
|
/** Set false to skip deterministic plan rewrites, for example to snapshot the raw plan. */
|
|
57
71
|
readonly optimize?: boolean;
|
|
58
72
|
}
|
|
73
|
+
/** One RETURNING item beyond a plain column: its statement text, output name, and the column it names when it is one. */
|
|
74
|
+
export interface ReturningItem {
|
|
75
|
+
sql: string;
|
|
76
|
+
alias: string;
|
|
77
|
+
expression: Expression;
|
|
78
|
+
/** The target column the item names, when it is a bare column reference. */
|
|
79
|
+
column?: string;
|
|
80
|
+
}
|
|
59
81
|
export declare function compileQuery(sql: string, options?: CompileQueryOptions): CompiledQuery;
|
|
60
82
|
/**
|
|
61
83
|
* One WHEN clause of a MERGE (F312). Branches are tried in order for each source row, and the
|
|
@@ -135,6 +157,11 @@ export type CompiledStatement = {
|
|
|
135
157
|
column: string;
|
|
136
158
|
/** The full PostgreSQL conflict target; `column` remains the scalar fast-path name. */
|
|
137
159
|
columns?: string[];
|
|
160
|
+
/**
|
|
161
|
+
* `ON CONFLICT DO NOTHING` with no target: the statement names no columns, and the
|
|
162
|
+
* table's unique key is resolved at execution, where the catalog is known.
|
|
163
|
+
*/
|
|
164
|
+
anyTarget?: true;
|
|
138
165
|
action: "nothing" | "replace" | "update";
|
|
139
166
|
/** Expressions evaluated against the stored target row and the proposed EXCLUDED row. */
|
|
140
167
|
assignments?: Array<{
|
|
@@ -145,10 +172,14 @@ export type CompiledStatement = {
|
|
|
145
172
|
where?: Expression;
|
|
146
173
|
};
|
|
147
174
|
returning?: string[] | "*";
|
|
175
|
+
/** RETURNING items that are not plain columns, evaluated over the affected rows. */
|
|
176
|
+
returningItems?: ReturningItem[];
|
|
148
177
|
parameterCount?: number;
|
|
149
178
|
} | {
|
|
150
179
|
kind: "update";
|
|
151
180
|
table: string;
|
|
181
|
+
/** `UPDATE t AS u`: the name the assignments, predicates, and RETURNING may qualify by. */
|
|
182
|
+
alias?: string;
|
|
152
183
|
assignments: Array<{
|
|
153
184
|
column: string;
|
|
154
185
|
expression: Expression;
|
|
@@ -159,16 +190,21 @@ export type CompiledStatement = {
|
|
|
159
190
|
right: Expression;
|
|
160
191
|
}>;
|
|
161
192
|
returning?: string[] | "*";
|
|
193
|
+
/** RETURNING items that are not plain columns, evaluated over the affected rows. */
|
|
194
|
+
returningItems?: ReturningItem[];
|
|
162
195
|
parameterCount?: number;
|
|
163
196
|
} | {
|
|
164
197
|
kind: "delete";
|
|
165
198
|
table: string;
|
|
199
|
+
alias?: string;
|
|
166
200
|
predicates: Array<{
|
|
167
201
|
left: Expression;
|
|
168
202
|
operator: PredicateOperator;
|
|
169
203
|
right: Expression;
|
|
170
204
|
}>;
|
|
171
205
|
returning?: string[] | "*";
|
|
206
|
+
/** RETURNING items that are not plain columns, evaluated over the affected rows. */
|
|
207
|
+
returningItems?: ReturningItem[];
|
|
172
208
|
parameterCount?: number;
|
|
173
209
|
} | {
|
|
174
210
|
kind: "create-table";
|
|
@@ -535,6 +571,8 @@ export declare function orderOutputName(expression: Expression, select: readonly
|
|
|
535
571
|
interface ListMembership {
|
|
536
572
|
set: ReadonlySet<unknown>;
|
|
537
573
|
hasNull: boolean;
|
|
574
|
+
/** Whether any member is text, which a typed left value may read in its own type. */
|
|
575
|
+
hasText: boolean;
|
|
538
576
|
}
|
|
539
577
|
/**
|
|
540
578
|
* IN lists produced by subquery materialization can hold many thousands of literals, and
|
|
@@ -668,6 +706,13 @@ export declare function projectResultColumns(result: QueryResult, aliases: reado
|
|
|
668
706
|
export declare function derivedTableSource(derived: CompiledQuery, alias: string, nextSequence: () => number): TableSource;
|
|
669
707
|
/** The parser's LIMIT range contract, shared with the typed builder. */
|
|
670
708
|
export declare function validateLimit(limit: number): number;
|
|
709
|
+
/**
|
|
710
|
+
* Reads datetime text the way the TIMESTAMP literal does — a zoneless `2026-01-02 03:04:05` is
|
|
711
|
+
* UTC, never the host's zone — and falls back to the JavaScript parser for other spellings.
|
|
712
|
+
* `new Date("2026-01-02 03:04:05")` alone would read the same text in local time, so a CAST
|
|
713
|
+
* would answer differently on two machines.
|
|
714
|
+
*/
|
|
715
|
+
export declare function datetimeText(text: string): Date;
|
|
671
716
|
/** The parser's OFFSET range contract, shared with the typed builder. */
|
|
672
717
|
export declare function validateOffset(offset: number): number;
|
|
673
718
|
/**
|