@rocicorp/zero 0.16.2025022601 → 0.17.2025022800
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/out/{chunk-7E4L5D3N.js → chunk-5BT5TJFM.js} +517 -3962
- package/out/chunk-5BT5TJFM.js.map +7 -0
- package/out/chunk-P3NUVEQJ.js +3578 -0
- package/out/chunk-P3NUVEQJ.js.map +7 -0
- package/out/pg.js +593 -0
- package/out/pg.js.map +7 -0
- package/out/react.js +1 -4
- package/out/react.js.map +2 -2
- package/out/shared/src/types.js +2 -0
- package/out/shared/src/types.js.map +1 -0
- package/out/solid.js +3 -2
- package/out/solid.js.map +1 -1
- package/out/z2s/src/compiler.d.ts +26 -0
- package/out/z2s/src/compiler.d.ts.map +1 -0
- package/out/z2s/src/compiler.js +155 -0
- package/out/z2s/src/compiler.js.map +1 -0
- package/out/z2s/src/sql.d.ts +12 -0
- package/out/z2s/src/sql.d.ts.map +1 -0
- package/out/z2s/src/sql.js +18 -0
- package/out/z2s/src/sql.js.map +1 -0
- package/out/zero/src/pg.d.ts +2 -0
- package/out/zero/src/pg.d.ts.map +1 -0
- package/out/zero/src/pg.js +3 -0
- package/out/zero/src/pg.js.map +1 -0
- package/out/zero-cache/src/auth/load-permissions.d.ts +2 -2
- package/out/zero-cache/src/auth/load-permissions.d.ts.map +1 -1
- package/out/zero-cache/src/auth/load-permissions.js +6 -7
- package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
- package/out/zero-cache/src/auth/read-authorizer.d.ts.map +1 -1
- package/out/zero-cache/src/auth/read-authorizer.js +1 -1
- package/out/zero-cache/src/auth/read-authorizer.js.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.d.ts +1 -1
- package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.js +4 -2
- package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +1 -1
- package/out/zero-cache/src/config/zero-config.js +4 -4
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/scripts/deploy-permissions.js +5 -4
- package/out/zero-cache/src/scripts/deploy-permissions.js.map +1 -1
- package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +3 -2
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/main.d.ts.map +1 -1
- package/out/zero-cache/src/server/main.js +2 -1
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/multi/config.d.ts +1 -1
- package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/server/syncer.js +4 -3
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.d.ts +2 -2
- package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.js +10 -10
- package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/sync-schema.d.ts +1 -1
- package/out/zero-cache/src/services/change-source/custom/sync-schema.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/sync-schema.js +2 -2
- package/out/zero-cache/src/services/change-source/custom/sync-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.js +14 -12
- package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +2 -2
- package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js +13 -9
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +11 -9
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts +2 -2
- package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/init.js +10 -10
- package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts +1 -3
- package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/published.js +1 -3
- package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +10 -12
- package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js +55 -51
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/validation.d.ts +1 -0
- package/out/zero-cache/src/services/change-source/pg/schema/validation.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/validation.js +1 -0
- package/out/zero-cache/src/services/change-source/pg/schema/validation.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/sync-schema.d.ts +1 -1
- package/out/zero-cache/src/services/change-source/pg/sync-schema.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/sync-schema.js +2 -2
- package/out/zero-cache/src/services/change-source/pg/sync-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.js +1 -3
- package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts +2 -2
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +18 -14
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +1 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.js +5 -6
- package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.js +3 -3
- package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js +4 -3
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +3 -3
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +12 -4
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js +2 -2
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/cvr.d.ts +3 -3
- package/out/zero-cache/src/services/view-syncer/schema/cvr.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/cvr.js +39 -39
- package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/init.d.ts +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/init.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/init.js +5 -5
- package/out/zero-cache/src/services/view-syncer/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +4 -3
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +25 -23
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +12 -8
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-client/src/client/custom.d.ts +1 -1
- package/out/zero-client/src/client/custom.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.d.ts +1 -1
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/mod.d.ts +1 -0
- package/out/zero-client/src/mod.d.ts.map +1 -1
- package/out/zero-pg/src/custom.d.ts +42 -0
- package/out/zero-pg/src/custom.d.ts.map +1 -0
- package/out/zero-pg/src/custom.js +99 -0
- package/out/zero-pg/src/custom.js.map +1 -0
- package/out/zero-pg/src/db.d.ts +27 -0
- package/out/zero-pg/src/db.d.ts.map +1 -0
- package/out/zero-pg/src/db.js +2 -0
- package/out/zero-pg/src/db.js.map +1 -0
- package/out/zero-pg/src/logging.d.ts +3 -0
- package/out/zero-pg/src/logging.d.ts.map +1 -0
- package/out/zero-pg/src/logging.js +5 -0
- package/out/zero-pg/src/logging.js.map +1 -0
- package/out/zero-pg/src/mod.d.ts +5 -0
- package/out/zero-pg/src/mod.d.ts.map +1 -0
- package/out/zero-pg/src/mod.js +2 -0
- package/out/zero-pg/src/mod.js.map +1 -0
- package/out/zero-pg/src/query.d.ts +22 -0
- package/out/zero-pg/src/query.d.ts.map +1 -0
- package/out/zero-pg/src/query.js +54 -0
- package/out/zero-pg/src/query.js.map +1 -0
- package/out/zero-pg/src/web.d.ts +16 -0
- package/out/zero-pg/src/web.d.ts.map +1 -0
- package/out/zero-pg/src/web.js +115 -0
- package/out/zero-pg/src/web.js.map +1 -0
- package/out/zero-react/src/use-zero.d.ts +5 -4
- package/out/zero-react/src/use-zero.d.ts.map +1 -1
- package/out/zero.js +2 -1
- package/out/zql/src/ivm/exists.d.ts.map +1 -1
- package/out/zql/src/ivm/exists.js +43 -23
- package/out/zql/src/ivm/exists.js.map +1 -1
- package/out/zql/src/mutate/custom.js +10 -0
- package/out/zql/src/mutate/custom.js.map +1 -0
- package/out/zql/src/query/query-impl.d.ts +2 -2
- package/out/zql/src/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.js +1 -1
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query.d.ts +1 -1
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zql/src/query/static-query.d.ts +1 -1
- package/out/zql/src/query/static-query.d.ts.map +1 -1
- package/out/zql/src/query/static-query.js +3 -3
- package/out/zql/src/query/static-query.js.map +1 -1
- package/package.json +5 -1
- package/out/chunk-7E4L5D3N.js.map +0 -7
|
@@ -0,0 +1,3578 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hasOwn
|
|
3
|
+
} from "./chunk-HARIWJ2J.js";
|
|
4
|
+
import {
|
|
5
|
+
applyChange,
|
|
6
|
+
assert,
|
|
7
|
+
assertObject,
|
|
8
|
+
assertString,
|
|
9
|
+
compareValues,
|
|
10
|
+
drainStreams,
|
|
11
|
+
must,
|
|
12
|
+
normalizeUndefined,
|
|
13
|
+
throwInvalidType,
|
|
14
|
+
unreachable,
|
|
15
|
+
valuesEqual
|
|
16
|
+
} from "./chunk-Q6D7EOS6.js";
|
|
17
|
+
import {
|
|
18
|
+
__export,
|
|
19
|
+
__reExport
|
|
20
|
+
} from "./chunk-424PT5DM.js";
|
|
21
|
+
|
|
22
|
+
// ../shared/src/valita.ts
|
|
23
|
+
var valita_exports = {};
|
|
24
|
+
__export(valita_exports, {
|
|
25
|
+
assert: () => assert2,
|
|
26
|
+
deepPartial: () => deepPartial,
|
|
27
|
+
instanceOfAbstractType: () => instanceOfAbstractType,
|
|
28
|
+
is: () => is,
|
|
29
|
+
parse: () => parse,
|
|
30
|
+
readonly: () => readonly,
|
|
31
|
+
readonlyArray: () => readonlyArray,
|
|
32
|
+
readonlyObject: () => readonlyObject,
|
|
33
|
+
readonlyRecord: () => readonlyRecord,
|
|
34
|
+
test: () => test,
|
|
35
|
+
testOptional: () => testOptional
|
|
36
|
+
});
|
|
37
|
+
__reExport(valita_exports, valita_star);
|
|
38
|
+
import * as v from "@badrap/valita";
|
|
39
|
+
import * as valita_star from "@badrap/valita";
|
|
40
|
+
function toDisplay(value) {
|
|
41
|
+
switch (typeof value) {
|
|
42
|
+
case "string":
|
|
43
|
+
case "number":
|
|
44
|
+
case "boolean":
|
|
45
|
+
return JSON.stringify(value);
|
|
46
|
+
case "undefined":
|
|
47
|
+
return "undefined";
|
|
48
|
+
case "bigint":
|
|
49
|
+
return value.toString() + "n";
|
|
50
|
+
default:
|
|
51
|
+
if (value === null) {
|
|
52
|
+
return "null";
|
|
53
|
+
}
|
|
54
|
+
if (Array.isArray(value)) {
|
|
55
|
+
return "array";
|
|
56
|
+
}
|
|
57
|
+
return typeof value;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function toDisplayAtPath(v2, path2) {
|
|
61
|
+
if (!path2?.length) {
|
|
62
|
+
return toDisplay(v2);
|
|
63
|
+
}
|
|
64
|
+
let cur = v2;
|
|
65
|
+
for (const p of path2) {
|
|
66
|
+
cur = cur[p];
|
|
67
|
+
}
|
|
68
|
+
return toDisplay(cur);
|
|
69
|
+
}
|
|
70
|
+
function displayList(word, expected, toDisplay2 = (x) => String(x)) {
|
|
71
|
+
if (expected.length === 1) {
|
|
72
|
+
return toDisplay2(expected[0]);
|
|
73
|
+
}
|
|
74
|
+
const suffix = `${toDisplay2(
|
|
75
|
+
expected[expected.length - 2]
|
|
76
|
+
)} ${word} ${toDisplay2(expected[expected.length - 1])}`;
|
|
77
|
+
if (expected.length === 2) {
|
|
78
|
+
return suffix;
|
|
79
|
+
}
|
|
80
|
+
return `${expected.slice(0, -2).map(toDisplay2).join(", ")}, ${suffix}`;
|
|
81
|
+
}
|
|
82
|
+
function getMessage(err2, v2, schema, mode) {
|
|
83
|
+
const firstIssue = err2.issues[0];
|
|
84
|
+
const { path: path2 } = firstIssue;
|
|
85
|
+
const atPath = path2?.length ? ` at ${path2.join(".")}` : "";
|
|
86
|
+
switch (firstIssue.code) {
|
|
87
|
+
case "invalid_type":
|
|
88
|
+
return `Expected ${displayList(
|
|
89
|
+
"or",
|
|
90
|
+
firstIssue.expected
|
|
91
|
+
)}${atPath}. Got ${toDisplayAtPath(v2, path2)}`;
|
|
92
|
+
case "missing_value": {
|
|
93
|
+
const atPath2 = path2 && path2.length > 1 ? ` at ${path2.slice(0, -1).join(".")}` : "";
|
|
94
|
+
if (firstIssue.path?.length) {
|
|
95
|
+
return `Missing property ${firstIssue.path.at(-1)}${atPath2}`;
|
|
96
|
+
}
|
|
97
|
+
return `TODO Unknown missing property${atPath2}`;
|
|
98
|
+
}
|
|
99
|
+
case "invalid_literal":
|
|
100
|
+
return `Expected literal value ${displayList(
|
|
101
|
+
"or",
|
|
102
|
+
firstIssue.expected,
|
|
103
|
+
toDisplay
|
|
104
|
+
)}${atPath} Got ${toDisplayAtPath(v2, path2)}`;
|
|
105
|
+
case "invalid_length": {
|
|
106
|
+
return `Expected array with length ${firstIssue.minLength === firstIssue.maxLength ? firstIssue.minLength : `between ${firstIssue.minLength} and ${firstIssue.maxLength}`}${atPath}. Got array with length ${v2.length}`;
|
|
107
|
+
}
|
|
108
|
+
case "unrecognized_keys":
|
|
109
|
+
if (firstIssue.keys.length === 1) {
|
|
110
|
+
return `Unexpected property ${firstIssue.keys[0]}${atPath}`;
|
|
111
|
+
}
|
|
112
|
+
return `Unexpected properties ${displayList(
|
|
113
|
+
"and",
|
|
114
|
+
firstIssue.keys
|
|
115
|
+
)}${atPath}`;
|
|
116
|
+
case "invalid_union":
|
|
117
|
+
return schema.name === "union" ? getDeepestUnionParseError(v2, schema, mode ?? "strict") : `Invalid union value${atPath}`;
|
|
118
|
+
case "custom_error": {
|
|
119
|
+
const { error } = firstIssue;
|
|
120
|
+
const message = !error ? "unknown" : typeof error === "string" ? error : error.message ?? "unknown";
|
|
121
|
+
return `${message}${atPath}. Got ${toDisplayAtPath(v2, path2)}`;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function getDeepestUnionParseError(value, schema, mode) {
|
|
126
|
+
const failures = [];
|
|
127
|
+
for (const type of schema.options) {
|
|
128
|
+
const r = type.try(value, { mode });
|
|
129
|
+
if (!r.ok) {
|
|
130
|
+
failures.push({ type, err: r });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (failures.length) {
|
|
134
|
+
failures.sort(pathCmp);
|
|
135
|
+
if (failures.length === 1 || pathCmp(failures[0], failures[1]) < 0) {
|
|
136
|
+
return getMessage(failures[0].err, value, failures[0].type, mode);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
const str = JSON.stringify(value);
|
|
141
|
+
return `Invalid union value: ${str}`;
|
|
142
|
+
} catch (e) {
|
|
143
|
+
return `Invalid union value`;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function pathCmp(a, b) {
|
|
147
|
+
const aPath = a.err.issues[0].path;
|
|
148
|
+
const bPath = b.err.issues[0].path;
|
|
149
|
+
if (aPath.length !== bPath.length) {
|
|
150
|
+
return bPath.length - aPath.length;
|
|
151
|
+
}
|
|
152
|
+
for (let i = 0; i < aPath.length; i++) {
|
|
153
|
+
if (bPath[i] > aPath[i]) {
|
|
154
|
+
return -1;
|
|
155
|
+
}
|
|
156
|
+
if (bPath[i] < aPath[i]) {
|
|
157
|
+
return 1;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return 0;
|
|
161
|
+
}
|
|
162
|
+
function parse(value, schema, mode) {
|
|
163
|
+
const res = test(value, schema, mode);
|
|
164
|
+
if (!res.ok) {
|
|
165
|
+
throw new TypeError(res.error);
|
|
166
|
+
}
|
|
167
|
+
return res.value;
|
|
168
|
+
}
|
|
169
|
+
function is(value, schema, mode) {
|
|
170
|
+
return test(value, schema, mode).ok;
|
|
171
|
+
}
|
|
172
|
+
function assert2(value, schema, mode) {
|
|
173
|
+
parse(value, schema, mode);
|
|
174
|
+
}
|
|
175
|
+
function test(value, schema, mode) {
|
|
176
|
+
const res = schema.try(value, mode ? { mode } : void 0);
|
|
177
|
+
if (!res.ok) {
|
|
178
|
+
return {
|
|
179
|
+
ok: false,
|
|
180
|
+
error: getMessage(res, value, schema, mode)
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
return res;
|
|
184
|
+
}
|
|
185
|
+
function testOptional(value, schema, mode) {
|
|
186
|
+
let flags = 1;
|
|
187
|
+
if (mode === "passthrough") {
|
|
188
|
+
flags = 0;
|
|
189
|
+
} else if (mode === "strip") {
|
|
190
|
+
flags = 2;
|
|
191
|
+
}
|
|
192
|
+
const res = schema.func(value, flags);
|
|
193
|
+
if (res === void 0) {
|
|
194
|
+
return { ok: true, value };
|
|
195
|
+
} else if (res.ok) {
|
|
196
|
+
return res;
|
|
197
|
+
}
|
|
198
|
+
const err2 = new v.ValitaError(res);
|
|
199
|
+
return { ok: false, error: getMessage(err2, value, schema, mode) };
|
|
200
|
+
}
|
|
201
|
+
function readonly(t) {
|
|
202
|
+
return t;
|
|
203
|
+
}
|
|
204
|
+
function readonlyObject(t) {
|
|
205
|
+
return v.object(t);
|
|
206
|
+
}
|
|
207
|
+
function readonlyArray(t) {
|
|
208
|
+
return v.array(t);
|
|
209
|
+
}
|
|
210
|
+
function readonlyRecord(t) {
|
|
211
|
+
return v.record(t);
|
|
212
|
+
}
|
|
213
|
+
var AbstractType = Object.getPrototypeOf(
|
|
214
|
+
Object.getPrototypeOf(v.string().optional())
|
|
215
|
+
).constructor;
|
|
216
|
+
function instanceOfAbstractType(obj) {
|
|
217
|
+
return obj instanceof AbstractType;
|
|
218
|
+
}
|
|
219
|
+
function deepPartial(s) {
|
|
220
|
+
const shape = {};
|
|
221
|
+
for (const [key, type] of Object.entries(s.shape)) {
|
|
222
|
+
if (type.name === "object") {
|
|
223
|
+
shape[key] = deepPartial(type).optional();
|
|
224
|
+
} else {
|
|
225
|
+
shape[key] = type.optional();
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return v.object(shape);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ../zero-protocol/src/ast.ts
|
|
232
|
+
import { compareUTF8 } from "compare-utf8";
|
|
233
|
+
|
|
234
|
+
// ../shared/src/arrays.ts
|
|
235
|
+
function defined(arr) {
|
|
236
|
+
let i = arr.findIndex((x) => x === void 0);
|
|
237
|
+
if (i < 0) {
|
|
238
|
+
return arr;
|
|
239
|
+
}
|
|
240
|
+
const defined2 = arr.slice(0, i);
|
|
241
|
+
for (i++; i < arr.length; i++) {
|
|
242
|
+
const x = arr[i];
|
|
243
|
+
if (x !== void 0) {
|
|
244
|
+
defined2.push(x);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return defined2;
|
|
248
|
+
}
|
|
249
|
+
function areEqual(arr1, arr2) {
|
|
250
|
+
return arr1.length === arr2.length && arr1.every((e, i) => e === arr2[i]);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// ../shared/src/json-schema.ts
|
|
254
|
+
import * as valita from "@badrap/valita";
|
|
255
|
+
|
|
256
|
+
// ../shared/src/config.ts
|
|
257
|
+
var isProd = process.env.NODE_ENV === "production";
|
|
258
|
+
|
|
259
|
+
// ../shared/src/json.ts
|
|
260
|
+
function deepEqual(a, b) {
|
|
261
|
+
if (a === b) {
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
if (typeof a !== typeof b) {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
switch (typeof a) {
|
|
268
|
+
case "boolean":
|
|
269
|
+
case "number":
|
|
270
|
+
case "string":
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
a = a;
|
|
274
|
+
if (Array.isArray(a)) {
|
|
275
|
+
if (!Array.isArray(b)) {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
if (a.length !== b.length) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
for (let i = 0; i < a.length; i++) {
|
|
282
|
+
if (!deepEqual(a[i], b[i])) {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
if (a === null || b === null) {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
if (Array.isArray(b)) {
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
294
|
+
a = a;
|
|
295
|
+
b = b;
|
|
296
|
+
let aSize = 0;
|
|
297
|
+
for (const key in a) {
|
|
298
|
+
if (hasOwn(a, key)) {
|
|
299
|
+
if (!deepEqual(a[key], b[key])) {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
aSize++;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
let bSize = 0;
|
|
306
|
+
for (const key in b) {
|
|
307
|
+
if (hasOwn(b, key)) {
|
|
308
|
+
bSize++;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return aSize === bSize;
|
|
312
|
+
}
|
|
313
|
+
function assertJSONValue(v2) {
|
|
314
|
+
if (isProd) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
switch (typeof v2) {
|
|
318
|
+
case "boolean":
|
|
319
|
+
case "number":
|
|
320
|
+
case "string":
|
|
321
|
+
return;
|
|
322
|
+
case "object":
|
|
323
|
+
if (v2 === null) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
if (Array.isArray(v2)) {
|
|
327
|
+
return assertJSONArray(v2);
|
|
328
|
+
}
|
|
329
|
+
return assertObjectIsJSONObject(v2);
|
|
330
|
+
}
|
|
331
|
+
throwInvalidType(v2, "JSON value");
|
|
332
|
+
}
|
|
333
|
+
function assertJSONObject(v2) {
|
|
334
|
+
assertObject(v2);
|
|
335
|
+
assertObjectIsJSONObject(v2);
|
|
336
|
+
}
|
|
337
|
+
function assertObjectIsJSONObject(v2) {
|
|
338
|
+
for (const k in v2) {
|
|
339
|
+
if (hasOwn(v2, k)) {
|
|
340
|
+
const value = v2[k];
|
|
341
|
+
if (value !== void 0) {
|
|
342
|
+
assertJSONValue(value);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
function assertJSONArray(v2) {
|
|
348
|
+
for (const item of v2) {
|
|
349
|
+
assertJSONValue(item);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
function isJSONValue(v2, path2) {
|
|
353
|
+
switch (typeof v2) {
|
|
354
|
+
case "boolean":
|
|
355
|
+
case "number":
|
|
356
|
+
case "string":
|
|
357
|
+
return true;
|
|
358
|
+
case "object":
|
|
359
|
+
if (v2 === null) {
|
|
360
|
+
return true;
|
|
361
|
+
}
|
|
362
|
+
if (Array.isArray(v2)) {
|
|
363
|
+
return isJSONArray(v2, path2);
|
|
364
|
+
}
|
|
365
|
+
return objectIsJSONObject(v2, path2);
|
|
366
|
+
}
|
|
367
|
+
return false;
|
|
368
|
+
}
|
|
369
|
+
function isJSONObject(v2, path2) {
|
|
370
|
+
if (typeof v2 !== "object" || v2 === null) {
|
|
371
|
+
return false;
|
|
372
|
+
}
|
|
373
|
+
return objectIsJSONObject(v2, path2);
|
|
374
|
+
}
|
|
375
|
+
function objectIsJSONObject(v2, path2) {
|
|
376
|
+
for (const k in v2) {
|
|
377
|
+
if (hasOwn(v2, k)) {
|
|
378
|
+
path2.push(k);
|
|
379
|
+
const value = v2[k];
|
|
380
|
+
if (value !== void 0 && !isJSONValue(value, path2)) {
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
path2.pop();
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return true;
|
|
387
|
+
}
|
|
388
|
+
function isJSONArray(v2, path2) {
|
|
389
|
+
for (let i = 0; i < v2.length; i++) {
|
|
390
|
+
path2.push(i);
|
|
391
|
+
if (!isJSONValue(v2[i], path2)) {
|
|
392
|
+
return false;
|
|
393
|
+
}
|
|
394
|
+
path2.pop();
|
|
395
|
+
}
|
|
396
|
+
return true;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// ../shared/src/json-schema.ts
|
|
400
|
+
var path = [];
|
|
401
|
+
var jsonSchema = valita_exports.unknown().chain((v2) => {
|
|
402
|
+
if (isProd) {
|
|
403
|
+
return valita.ok(v2);
|
|
404
|
+
}
|
|
405
|
+
const rv = isJSONValue(v2, path) ? valita.ok(v2) : valita.err({
|
|
406
|
+
message: `Not a JSON value`,
|
|
407
|
+
path: path.slice()
|
|
408
|
+
});
|
|
409
|
+
path.length = 0;
|
|
410
|
+
return rv;
|
|
411
|
+
});
|
|
412
|
+
var jsonObjectSchema = valita_exports.unknown().chain((v2) => {
|
|
413
|
+
if (isProd) {
|
|
414
|
+
return valita.ok(v2);
|
|
415
|
+
}
|
|
416
|
+
const rv = isJSONObject(v2, path) ? valita.ok(v2) : valita.err({
|
|
417
|
+
message: `Not a JSON object`,
|
|
418
|
+
path: path.slice()
|
|
419
|
+
});
|
|
420
|
+
path.length = 0;
|
|
421
|
+
return rv;
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
// ../zero-protocol/src/data.ts
|
|
425
|
+
var valueSchema = valita_exports.union(jsonSchema, valita_exports.undefined());
|
|
426
|
+
var rowSchema = readonlyRecord(valueSchema);
|
|
427
|
+
|
|
428
|
+
// ../zero-protocol/src/ast.ts
|
|
429
|
+
var selectorSchema = valita_exports.string();
|
|
430
|
+
var toStaticParam = Symbol();
|
|
431
|
+
var orderingElementSchema = readonly(
|
|
432
|
+
valita_exports.tuple([selectorSchema, valita_exports.union(valita_exports.literal("asc"), valita_exports.literal("desc"))])
|
|
433
|
+
);
|
|
434
|
+
var orderingSchema = readonlyArray(orderingElementSchema);
|
|
435
|
+
var primitiveSchema = valita_exports.union(
|
|
436
|
+
valita_exports.string(),
|
|
437
|
+
valita_exports.number(),
|
|
438
|
+
valita_exports.boolean(),
|
|
439
|
+
valita_exports.null()
|
|
440
|
+
);
|
|
441
|
+
var equalityOpsSchema = valita_exports.union(
|
|
442
|
+
valita_exports.literal("="),
|
|
443
|
+
valita_exports.literal("!="),
|
|
444
|
+
valita_exports.literal("IS"),
|
|
445
|
+
valita_exports.literal("IS NOT")
|
|
446
|
+
);
|
|
447
|
+
var orderOpsSchema = valita_exports.union(
|
|
448
|
+
valita_exports.literal("<"),
|
|
449
|
+
valita_exports.literal(">"),
|
|
450
|
+
valita_exports.literal("<="),
|
|
451
|
+
valita_exports.literal(">=")
|
|
452
|
+
);
|
|
453
|
+
var likeOpsSchema = valita_exports.union(
|
|
454
|
+
valita_exports.literal("LIKE"),
|
|
455
|
+
valita_exports.literal("NOT LIKE"),
|
|
456
|
+
valita_exports.literal("ILIKE"),
|
|
457
|
+
valita_exports.literal("NOT ILIKE")
|
|
458
|
+
);
|
|
459
|
+
var inOpsSchema = valita_exports.union(valita_exports.literal("IN"), valita_exports.literal("NOT IN"));
|
|
460
|
+
var simpleOperatorSchema = valita_exports.union(
|
|
461
|
+
equalityOpsSchema,
|
|
462
|
+
orderOpsSchema,
|
|
463
|
+
likeOpsSchema,
|
|
464
|
+
inOpsSchema
|
|
465
|
+
);
|
|
466
|
+
var literalReferenceSchema = readonlyObject({
|
|
467
|
+
type: valita_exports.literal("literal"),
|
|
468
|
+
value: valita_exports.union(
|
|
469
|
+
valita_exports.string(),
|
|
470
|
+
valita_exports.number(),
|
|
471
|
+
valita_exports.boolean(),
|
|
472
|
+
valita_exports.null(),
|
|
473
|
+
readonlyArray(valita_exports.union(valita_exports.string(), valita_exports.number(), valita_exports.boolean()))
|
|
474
|
+
)
|
|
475
|
+
});
|
|
476
|
+
var columnReferenceSchema = readonlyObject({
|
|
477
|
+
type: valita_exports.literal("column"),
|
|
478
|
+
name: valita_exports.string()
|
|
479
|
+
});
|
|
480
|
+
var parameterReferenceSchema = readonlyObject({
|
|
481
|
+
type: valita_exports.literal("static"),
|
|
482
|
+
// The "namespace" of the injected parameter.
|
|
483
|
+
// Write authorization will send the value of a row
|
|
484
|
+
// prior to the mutation being run (preMutationRow).
|
|
485
|
+
// Read and write authorization will both send the
|
|
486
|
+
// current authentication data (authData).
|
|
487
|
+
anchor: valita_exports.union(valita_exports.literal("authData"), valita_exports.literal("preMutationRow")),
|
|
488
|
+
field: valita_exports.union(valita_exports.string(), valita_exports.array(valita_exports.string()))
|
|
489
|
+
});
|
|
490
|
+
var conditionValueSchema = valita_exports.union(
|
|
491
|
+
literalReferenceSchema,
|
|
492
|
+
columnReferenceSchema,
|
|
493
|
+
parameterReferenceSchema
|
|
494
|
+
);
|
|
495
|
+
var simpleConditionSchema = readonlyObject({
|
|
496
|
+
type: valita_exports.literal("simple"),
|
|
497
|
+
op: simpleOperatorSchema,
|
|
498
|
+
left: conditionValueSchema,
|
|
499
|
+
right: valita_exports.union(parameterReferenceSchema, literalReferenceSchema)
|
|
500
|
+
});
|
|
501
|
+
var correlatedSubqueryConditionOperatorSchema = valita_exports.union(valita_exports.literal("EXISTS"), valita_exports.literal("NOT EXISTS"));
|
|
502
|
+
var correlatedSubqueryConditionSchema = readonlyObject({
|
|
503
|
+
type: valita_exports.literal("correlatedSubquery"),
|
|
504
|
+
related: valita_exports.lazy(() => correlatedSubquerySchema),
|
|
505
|
+
op: correlatedSubqueryConditionOperatorSchema
|
|
506
|
+
});
|
|
507
|
+
var conditionSchema = valita_exports.union(
|
|
508
|
+
simpleConditionSchema,
|
|
509
|
+
valita_exports.lazy(() => conjunctionSchema),
|
|
510
|
+
valita_exports.lazy(() => disjunctionSchema),
|
|
511
|
+
correlatedSubqueryConditionSchema
|
|
512
|
+
);
|
|
513
|
+
var conjunctionSchema = readonlyObject({
|
|
514
|
+
type: valita_exports.literal("and"),
|
|
515
|
+
conditions: readonlyArray(conditionSchema)
|
|
516
|
+
});
|
|
517
|
+
var disjunctionSchema = readonlyObject({
|
|
518
|
+
type: valita_exports.literal("or"),
|
|
519
|
+
conditions: readonlyArray(conditionSchema)
|
|
520
|
+
});
|
|
521
|
+
function mustCompoundKey(field) {
|
|
522
|
+
assert(Array.isArray(field) && field.length >= 1);
|
|
523
|
+
return field;
|
|
524
|
+
}
|
|
525
|
+
var compoundKeySchema = readonly(
|
|
526
|
+
valita_exports.tuple([valita_exports.string()]).concat(valita_exports.array(valita_exports.string()))
|
|
527
|
+
);
|
|
528
|
+
var correlationSchema = readonlyObject({
|
|
529
|
+
parentField: compoundKeySchema,
|
|
530
|
+
childField: compoundKeySchema
|
|
531
|
+
});
|
|
532
|
+
var correlatedSubquerySchemaOmitSubquery = readonlyObject({
|
|
533
|
+
correlation: correlationSchema,
|
|
534
|
+
hidden: valita_exports.boolean().optional(),
|
|
535
|
+
system: valita_exports.union(valita_exports.literal("permissions"), valita_exports.literal("client")).optional()
|
|
536
|
+
});
|
|
537
|
+
var correlatedSubquerySchema = correlatedSubquerySchemaOmitSubquery.extend({
|
|
538
|
+
subquery: valita_exports.lazy(() => astSchema)
|
|
539
|
+
});
|
|
540
|
+
var astSchema = readonlyObject({
|
|
541
|
+
schema: valita_exports.string().optional(),
|
|
542
|
+
table: valita_exports.string(),
|
|
543
|
+
alias: valita_exports.string().optional(),
|
|
544
|
+
where: conditionSchema.optional(),
|
|
545
|
+
related: readonlyArray(correlatedSubquerySchema).optional(),
|
|
546
|
+
limit: valita_exports.number().optional(),
|
|
547
|
+
orderBy: orderingSchema.optional(),
|
|
548
|
+
start: valita_exports.object({
|
|
549
|
+
row: rowSchema,
|
|
550
|
+
exclusive: valita_exports.boolean()
|
|
551
|
+
}).optional()
|
|
552
|
+
});
|
|
553
|
+
function transformAST(ast, transform) {
|
|
554
|
+
const { tableName, columnName } = transform;
|
|
555
|
+
const colName = (c) => columnName(ast.table, c);
|
|
556
|
+
const key = (table, k) => {
|
|
557
|
+
const serverKey = k.map((col) => columnName(table, col));
|
|
558
|
+
return mustCompoundKey(serverKey);
|
|
559
|
+
};
|
|
560
|
+
const where = ast.where ? transform.where(ast.where) : void 0;
|
|
561
|
+
const transformed = {
|
|
562
|
+
schema: ast.schema,
|
|
563
|
+
table: tableName(ast.table),
|
|
564
|
+
alias: ast.alias,
|
|
565
|
+
where: where ? transformWhere(where, ast.table, transform) : void 0,
|
|
566
|
+
related: ast.related ? transform.related(
|
|
567
|
+
ast.related.map(
|
|
568
|
+
(r) => ({
|
|
569
|
+
correlation: {
|
|
570
|
+
parentField: key(ast.table, r.correlation.parentField),
|
|
571
|
+
childField: key(r.subquery.table, r.correlation.childField)
|
|
572
|
+
},
|
|
573
|
+
hidden: r.hidden,
|
|
574
|
+
subquery: transformAST(r.subquery, transform),
|
|
575
|
+
system: r.system
|
|
576
|
+
})
|
|
577
|
+
)
|
|
578
|
+
) : void 0,
|
|
579
|
+
start: ast.start ? {
|
|
580
|
+
...ast.start,
|
|
581
|
+
row: Object.fromEntries(
|
|
582
|
+
Object.entries(ast.start.row).map(([col, val]) => [
|
|
583
|
+
colName(col),
|
|
584
|
+
val
|
|
585
|
+
])
|
|
586
|
+
)
|
|
587
|
+
} : void 0,
|
|
588
|
+
limit: ast.limit,
|
|
589
|
+
orderBy: ast.orderBy?.map(([col, dir]) => [colName(col), dir])
|
|
590
|
+
};
|
|
591
|
+
return transformed;
|
|
592
|
+
}
|
|
593
|
+
function transformWhere(where, table, transform) {
|
|
594
|
+
const { columnName } = transform;
|
|
595
|
+
const condValue = (c) => c.type !== "column" ? c : { ...c, name: columnName(table, c.name) };
|
|
596
|
+
const key = (table2, k) => {
|
|
597
|
+
const serverKey = k.map((col) => columnName(table2, col));
|
|
598
|
+
return mustCompoundKey(serverKey);
|
|
599
|
+
};
|
|
600
|
+
if (where.type === "simple") {
|
|
601
|
+
return { ...where, left: condValue(where.left) };
|
|
602
|
+
} else if (where.type === "correlatedSubquery") {
|
|
603
|
+
const { correlation, subquery } = where.related;
|
|
604
|
+
return {
|
|
605
|
+
...where,
|
|
606
|
+
related: {
|
|
607
|
+
...where.related,
|
|
608
|
+
correlation: {
|
|
609
|
+
parentField: key(table, correlation.parentField),
|
|
610
|
+
childField: key(subquery.table, correlation.childField)
|
|
611
|
+
},
|
|
612
|
+
subquery: transformAST(subquery, transform)
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
return {
|
|
617
|
+
type: where.type,
|
|
618
|
+
conditions: transform.conditions(
|
|
619
|
+
where.conditions.map((c) => transformWhere(c, table, transform))
|
|
620
|
+
)
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
var normalizeCache = /* @__PURE__ */ new WeakMap();
|
|
624
|
+
var NORMALIZE_TRANSFORM = {
|
|
625
|
+
tableName: (t) => t,
|
|
626
|
+
columnName: (_, c) => c,
|
|
627
|
+
related: sortedRelated,
|
|
628
|
+
where: flattened,
|
|
629
|
+
conditions: (c) => c.sort(cmpCondition)
|
|
630
|
+
};
|
|
631
|
+
function normalizeAST(ast) {
|
|
632
|
+
let normalized = normalizeCache.get(ast);
|
|
633
|
+
if (!normalized) {
|
|
634
|
+
normalized = transformAST(ast, NORMALIZE_TRANSFORM);
|
|
635
|
+
normalizeCache.set(ast, normalized);
|
|
636
|
+
}
|
|
637
|
+
return normalized;
|
|
638
|
+
}
|
|
639
|
+
function mapAST(ast, mapper) {
|
|
640
|
+
return transformAST(ast, {
|
|
641
|
+
tableName: (table) => mapper.tableName(table),
|
|
642
|
+
columnName: (table, col) => mapper.columnName(table, col),
|
|
643
|
+
related: (r) => r,
|
|
644
|
+
where: (w) => w,
|
|
645
|
+
conditions: (c) => c
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
function mapCondition(cond, table, mapper) {
|
|
649
|
+
return transformWhere(cond, table, {
|
|
650
|
+
tableName: (table2) => mapper.tableName(table2),
|
|
651
|
+
columnName: (table2, col) => mapper.columnName(table2, col),
|
|
652
|
+
related: (r) => r,
|
|
653
|
+
where: (w) => w,
|
|
654
|
+
conditions: (c) => c
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
function sortedRelated(related) {
|
|
658
|
+
return related.sort(cmpRelated);
|
|
659
|
+
}
|
|
660
|
+
function cmpCondition(a, b) {
|
|
661
|
+
if (a.type === "simple") {
|
|
662
|
+
if (b.type !== "simple") {
|
|
663
|
+
return -1;
|
|
664
|
+
}
|
|
665
|
+
return compareValuePosition(a.left, b.left) || compareUTF8MaybeNull(a.op, b.op) || compareValuePosition(a.right, b.right);
|
|
666
|
+
}
|
|
667
|
+
if (b.type === "simple") {
|
|
668
|
+
return 1;
|
|
669
|
+
}
|
|
670
|
+
if (a.type === "correlatedSubquery") {
|
|
671
|
+
if (b.type !== "correlatedSubquery") {
|
|
672
|
+
return -1;
|
|
673
|
+
}
|
|
674
|
+
return cmpRelated(a.related, b.related) || compareUTF8MaybeNull(a.op, b.op);
|
|
675
|
+
}
|
|
676
|
+
if (b.type === "correlatedSubquery") {
|
|
677
|
+
return -1;
|
|
678
|
+
}
|
|
679
|
+
const val = compareUTF8MaybeNull(a.type, b.type);
|
|
680
|
+
if (val !== 0) {
|
|
681
|
+
return val;
|
|
682
|
+
}
|
|
683
|
+
for (let l = 0, r = 0; l < a.conditions.length && r < b.conditions.length; l++, r++) {
|
|
684
|
+
const val2 = cmpCondition(a.conditions[l], b.conditions[r]);
|
|
685
|
+
if (val2 !== 0) {
|
|
686
|
+
return val2;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
return a.conditions.length - b.conditions.length;
|
|
690
|
+
}
|
|
691
|
+
function compareValuePosition(a, b) {
|
|
692
|
+
if (a.type !== b.type) {
|
|
693
|
+
return compareUTF8(a.type, b.type);
|
|
694
|
+
}
|
|
695
|
+
switch (a.type) {
|
|
696
|
+
case "literal":
|
|
697
|
+
assert(b.type === "literal");
|
|
698
|
+
return compareUTF8(String(a.value), String(b.value));
|
|
699
|
+
case "column":
|
|
700
|
+
assert(b.type === "column");
|
|
701
|
+
return compareUTF8(a.name, b.name);
|
|
702
|
+
case "static":
|
|
703
|
+
throw new Error(
|
|
704
|
+
"Static parameters should be resolved before normalization"
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
function cmpRelated(a, b) {
|
|
709
|
+
return compareUTF8(must(a.subquery.alias), must(b.subquery.alias));
|
|
710
|
+
}
|
|
711
|
+
function flattened(cond) {
|
|
712
|
+
if (cond.type === "simple" || cond.type === "correlatedSubquery") {
|
|
713
|
+
return cond;
|
|
714
|
+
}
|
|
715
|
+
const conditions = defined(
|
|
716
|
+
cond.conditions.flatMap(
|
|
717
|
+
(c) => c.type === cond.type ? c.conditions.map((c2) => flattened(c2)) : flattened(c)
|
|
718
|
+
)
|
|
719
|
+
);
|
|
720
|
+
switch (conditions.length) {
|
|
721
|
+
case 0:
|
|
722
|
+
return void 0;
|
|
723
|
+
case 1:
|
|
724
|
+
return conditions[0];
|
|
725
|
+
default:
|
|
726
|
+
return {
|
|
727
|
+
type: cond.type,
|
|
728
|
+
conditions
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
function compareUTF8MaybeNull(a, b) {
|
|
733
|
+
if (a !== null && b !== null) {
|
|
734
|
+
return compareUTF8(a, b);
|
|
735
|
+
}
|
|
736
|
+
if (b !== null) {
|
|
737
|
+
return -1;
|
|
738
|
+
}
|
|
739
|
+
if (a !== null) {
|
|
740
|
+
return 1;
|
|
741
|
+
}
|
|
742
|
+
return 0;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
// ../zero-schema/src/table-schema.ts
|
|
746
|
+
function isOneHop(r) {
|
|
747
|
+
return r.length === 1;
|
|
748
|
+
}
|
|
749
|
+
function isTwoHop(r) {
|
|
750
|
+
return r.length === 2;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
// ../zql/src/query/query-impl.ts
|
|
754
|
+
import { resolver } from "@rocicorp/resolver";
|
|
755
|
+
|
|
756
|
+
// ../shared/src/hash.ts
|
|
757
|
+
import { xxHash32 } from "js-xxhash";
|
|
758
|
+
var h64 = (s) => hash(s, 2);
|
|
759
|
+
var h128 = (s) => hash(s, 4);
|
|
760
|
+
function hash(str, words) {
|
|
761
|
+
let hash2 = 0n;
|
|
762
|
+
for (let i = 0; i < words; i++) {
|
|
763
|
+
hash2 = (hash2 << 32n) + BigInt(xxHash32(str, i));
|
|
764
|
+
}
|
|
765
|
+
return hash2;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// ../zero-protocol/src/ast-hash.ts
|
|
769
|
+
var hashCache = /* @__PURE__ */ new WeakMap();
|
|
770
|
+
function hashOfAST(ast) {
|
|
771
|
+
const normalized = normalizeAST(ast);
|
|
772
|
+
const cached = hashCache.get(normalized);
|
|
773
|
+
if (cached) {
|
|
774
|
+
return cached;
|
|
775
|
+
}
|
|
776
|
+
const hash2 = h64(JSON.stringify(normalized)).toString(36);
|
|
777
|
+
hashCache.set(normalized, hash2);
|
|
778
|
+
return hash2;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// ../zql/src/ivm/operator.ts
|
|
782
|
+
var throwOutput = {
|
|
783
|
+
push(_change) {
|
|
784
|
+
throw new Error("Output not set");
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
|
|
788
|
+
// ../zql/src/ivm/stream.ts
|
|
789
|
+
function* take(stream, limit) {
|
|
790
|
+
if (limit < 1) {
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
let count = 0;
|
|
794
|
+
for (const v2 of stream) {
|
|
795
|
+
yield v2;
|
|
796
|
+
if (++count === limit) {
|
|
797
|
+
break;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
function first(stream) {
|
|
802
|
+
const it = stream[Symbol.iterator]();
|
|
803
|
+
const { value } = it.next();
|
|
804
|
+
it.return?.();
|
|
805
|
+
return value;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// ../zql/src/ivm/exists.ts
|
|
809
|
+
var Exists = class {
|
|
810
|
+
#input;
|
|
811
|
+
#relationshipName;
|
|
812
|
+
#storage;
|
|
813
|
+
#not;
|
|
814
|
+
#parentJoinKey;
|
|
815
|
+
#skipCache;
|
|
816
|
+
#output = throwOutput;
|
|
817
|
+
constructor(input, storage, relationshipName, parentJoinKey, type) {
|
|
818
|
+
this.#input = input;
|
|
819
|
+
this.#relationshipName = relationshipName;
|
|
820
|
+
this.#input.setOutput(this);
|
|
821
|
+
this.#storage = storage;
|
|
822
|
+
assert(this.#input.getSchema().relationships[relationshipName]);
|
|
823
|
+
this.#not = type === "NOT EXISTS";
|
|
824
|
+
this.#parentJoinKey = parentJoinKey;
|
|
825
|
+
this.#skipCache = areEqual(
|
|
826
|
+
parentJoinKey,
|
|
827
|
+
this.#input.getSchema().primaryKey
|
|
828
|
+
);
|
|
829
|
+
}
|
|
830
|
+
setOutput(output) {
|
|
831
|
+
this.#output = output;
|
|
832
|
+
}
|
|
833
|
+
destroy() {
|
|
834
|
+
this.#input.destroy();
|
|
835
|
+
}
|
|
836
|
+
getSchema() {
|
|
837
|
+
return this.#input.getSchema();
|
|
838
|
+
}
|
|
839
|
+
*fetch(req) {
|
|
840
|
+
for (const node of this.#input.fetch(req)) {
|
|
841
|
+
if (this.#filter(node)) {
|
|
842
|
+
yield node;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
*cleanup(req) {
|
|
847
|
+
for (const node of this.#input.cleanup(req)) {
|
|
848
|
+
if (this.#filter(node)) {
|
|
849
|
+
yield node;
|
|
850
|
+
} else {
|
|
851
|
+
drainStreams(node);
|
|
852
|
+
}
|
|
853
|
+
this.#delSize(node);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
push(change) {
|
|
857
|
+
switch (change.type) {
|
|
858
|
+
// add, remove and edit cannot change the size of the
|
|
859
|
+
// this.#relationshipName relationship, so simply #pushWithFilter
|
|
860
|
+
case "add":
|
|
861
|
+
case "edit": {
|
|
862
|
+
this.#pushWithFilter(change);
|
|
863
|
+
return;
|
|
864
|
+
}
|
|
865
|
+
case "remove": {
|
|
866
|
+
const size = this.#getSize(change.node);
|
|
867
|
+
if (size === void 0) {
|
|
868
|
+
return;
|
|
869
|
+
}
|
|
870
|
+
this.#pushWithFilter(change, size);
|
|
871
|
+
this.#delSize(change.node);
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
874
|
+
case "child":
|
|
875
|
+
if (change.child.relationshipName !== this.#relationshipName || change.child.change.type === "edit" || change.child.change.type === "child") {
|
|
876
|
+
this.#pushWithFilter(change);
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
switch (change.child.change.type) {
|
|
880
|
+
case "add": {
|
|
881
|
+
let size = this.#getSize(change.node);
|
|
882
|
+
if (size !== void 0) {
|
|
883
|
+
size++;
|
|
884
|
+
this.#setCachedSize(change.node, size);
|
|
885
|
+
this.#setSize(change.node, size);
|
|
886
|
+
} else {
|
|
887
|
+
size = this.#fetchSize(change.node);
|
|
888
|
+
}
|
|
889
|
+
if (size === 1) {
|
|
890
|
+
if (this.#not) {
|
|
891
|
+
this.#output.push({
|
|
892
|
+
type: "remove",
|
|
893
|
+
node: {
|
|
894
|
+
row: change.node.row,
|
|
895
|
+
relationships: {
|
|
896
|
+
...change.node.relationships,
|
|
897
|
+
[this.#relationshipName]: () => []
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
});
|
|
901
|
+
} else {
|
|
902
|
+
this.#output.push({
|
|
903
|
+
type: "add",
|
|
904
|
+
node: change.node
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
} else {
|
|
908
|
+
this.#pushWithFilter(change, size);
|
|
909
|
+
}
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
912
|
+
case "remove": {
|
|
913
|
+
let size = this.#getSize(change.node);
|
|
914
|
+
if (size !== void 0) {
|
|
915
|
+
if (size === 0) {
|
|
916
|
+
return;
|
|
917
|
+
}
|
|
918
|
+
size--;
|
|
919
|
+
this.#setCachedSize(change.node, size);
|
|
920
|
+
this.#setSize(change.node, size);
|
|
921
|
+
} else {
|
|
922
|
+
size = this.#fetchSize(change.node);
|
|
923
|
+
}
|
|
924
|
+
if (size === 0) {
|
|
925
|
+
if (this.#not) {
|
|
926
|
+
this.#output.push({
|
|
927
|
+
type: "add",
|
|
928
|
+
node: change.node
|
|
929
|
+
});
|
|
930
|
+
} else {
|
|
931
|
+
this.#output.push({
|
|
932
|
+
type: "remove",
|
|
933
|
+
node: {
|
|
934
|
+
row: change.node.row,
|
|
935
|
+
relationships: {
|
|
936
|
+
...change.node.relationships,
|
|
937
|
+
[this.#relationshipName]: () => [
|
|
938
|
+
change.child.change.node
|
|
939
|
+
]
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
} else {
|
|
945
|
+
this.#pushWithFilter(change, size);
|
|
946
|
+
}
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
return;
|
|
951
|
+
default:
|
|
952
|
+
unreachable(change);
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
/**
|
|
956
|
+
* Returns whether or not the node's this.#relationshipName
|
|
957
|
+
* relationship passes the exist/not exists filter condition.
|
|
958
|
+
* If the optional `size` is passed it is used.
|
|
959
|
+
* Otherwise, if there is a stored size for the row it is used.
|
|
960
|
+
* Otherwise the size is computed by streaming the node's
|
|
961
|
+
* relationship with this.#relationshipName (this computed size is also
|
|
962
|
+
* stored).
|
|
963
|
+
*/
|
|
964
|
+
#filter(node, size) {
|
|
965
|
+
const exists = (size ?? this.#getOrFetchSize(node)) > 0;
|
|
966
|
+
return this.#not ? !exists : exists;
|
|
967
|
+
}
|
|
968
|
+
/**
|
|
969
|
+
* Pushes a change if this.#filter is true for its row.
|
|
970
|
+
*/
|
|
971
|
+
#pushWithFilter(change, size) {
|
|
972
|
+
if (this.#filter(change.node, size)) {
|
|
973
|
+
this.#output.push(change);
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
#getSize(node) {
|
|
977
|
+
return this.#storage.get(this.#makeSizeStorageKey(node));
|
|
978
|
+
}
|
|
979
|
+
#setSize(node, size) {
|
|
980
|
+
this.#storage.set(this.#makeSizeStorageKey(node), size);
|
|
981
|
+
}
|
|
982
|
+
#setCachedSize(node, size) {
|
|
983
|
+
if (this.#skipCache) {
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
this.#storage.set(this.#makeCacheStorageKey(node), size);
|
|
987
|
+
}
|
|
988
|
+
#getCachedSize(node) {
|
|
989
|
+
if (this.#skipCache) {
|
|
990
|
+
return void 0;
|
|
991
|
+
}
|
|
992
|
+
return this.#storage.get(this.#makeCacheStorageKey(node));
|
|
993
|
+
}
|
|
994
|
+
#delSize(node) {
|
|
995
|
+
this.#storage.del(this.#makeSizeStorageKey(node));
|
|
996
|
+
if (!this.#skipCache) {
|
|
997
|
+
const cacheKey = this.#makeCacheStorageKey(node);
|
|
998
|
+
if (first(this.#storage.scan({ prefix: `${cacheKey}/` })) === void 0) {
|
|
999
|
+
this.#storage.del(cacheKey);
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
#getOrFetchSize(node) {
|
|
1004
|
+
const size = this.#getSize(node);
|
|
1005
|
+
if (size !== void 0) {
|
|
1006
|
+
return size;
|
|
1007
|
+
}
|
|
1008
|
+
return this.#fetchSize(node);
|
|
1009
|
+
}
|
|
1010
|
+
#fetchSize(node) {
|
|
1011
|
+
const cachedSize = this.#getCachedSize(node);
|
|
1012
|
+
if (cachedSize !== void 0) {
|
|
1013
|
+
this.#setSize(node, cachedSize);
|
|
1014
|
+
return cachedSize;
|
|
1015
|
+
}
|
|
1016
|
+
const relationship = node.relationships[this.#relationshipName];
|
|
1017
|
+
assert(relationship);
|
|
1018
|
+
let size = 0;
|
|
1019
|
+
for (const _relatedNode of relationship()) {
|
|
1020
|
+
size++;
|
|
1021
|
+
}
|
|
1022
|
+
this.#setCachedSize(node, size);
|
|
1023
|
+
this.#setSize(node, size);
|
|
1024
|
+
return size;
|
|
1025
|
+
}
|
|
1026
|
+
#makeCacheStorageKey(node) {
|
|
1027
|
+
return `row/${JSON.stringify(
|
|
1028
|
+
this.#getKeyValues(node, this.#parentJoinKey)
|
|
1029
|
+
)}`;
|
|
1030
|
+
}
|
|
1031
|
+
#makeSizeStorageKey(node) {
|
|
1032
|
+
return `row/${this.#skipCache ? "" : JSON.stringify(this.#getKeyValues(node, this.#parentJoinKey))}/${JSON.stringify(
|
|
1033
|
+
this.#getKeyValues(node, this.#input.getSchema().primaryKey)
|
|
1034
|
+
)}`;
|
|
1035
|
+
}
|
|
1036
|
+
#getKeyValues(node, def) {
|
|
1037
|
+
const values = [];
|
|
1038
|
+
for (const key of def) {
|
|
1039
|
+
values.push(normalizeUndefined(node.row[key]));
|
|
1040
|
+
}
|
|
1041
|
+
return values;
|
|
1042
|
+
}
|
|
1043
|
+
};
|
|
1044
|
+
|
|
1045
|
+
// ../shared/src/iterables.ts
|
|
1046
|
+
function* joinIterables(...iters) {
|
|
1047
|
+
for (const iter of iters) {
|
|
1048
|
+
yield* iter;
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
function* filterIter(iter, p) {
|
|
1052
|
+
let index = 0;
|
|
1053
|
+
for (const t of iter) {
|
|
1054
|
+
if (p(t, index++)) {
|
|
1055
|
+
yield t;
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
function* mapIter(iter, f) {
|
|
1060
|
+
let index = 0;
|
|
1061
|
+
for (const t of iter) {
|
|
1062
|
+
yield f(t, index++);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
function first2(stream) {
|
|
1066
|
+
const it = stream[Symbol.iterator]();
|
|
1067
|
+
const { value } = it.next();
|
|
1068
|
+
it.return?.();
|
|
1069
|
+
return value;
|
|
1070
|
+
}
|
|
1071
|
+
var IterWrapper = class _IterWrapper {
|
|
1072
|
+
iter;
|
|
1073
|
+
constructor(iter) {
|
|
1074
|
+
this.iter = iter;
|
|
1075
|
+
}
|
|
1076
|
+
[Symbol.iterator]() {
|
|
1077
|
+
return this.iter[Symbol.iterator]();
|
|
1078
|
+
}
|
|
1079
|
+
map(f) {
|
|
1080
|
+
return new _IterWrapper(mapIter(this.iter, f));
|
|
1081
|
+
}
|
|
1082
|
+
filter(p) {
|
|
1083
|
+
return new _IterWrapper(filterIter(this.iter, p));
|
|
1084
|
+
}
|
|
1085
|
+
};
|
|
1086
|
+
function wrapIterable(iter) {
|
|
1087
|
+
return new IterWrapper(iter);
|
|
1088
|
+
}
|
|
1089
|
+
function* mergeIterables(iterables, comparator, distinct = false) {
|
|
1090
|
+
const iterators = iterables.map((i) => i[Symbol.iterator]());
|
|
1091
|
+
try {
|
|
1092
|
+
const current = iterators.map((i) => i.next());
|
|
1093
|
+
let lastYielded;
|
|
1094
|
+
while (current.some((c) => !c.done)) {
|
|
1095
|
+
const min = current.reduce(
|
|
1096
|
+
(acc, c, i) => {
|
|
1097
|
+
if (c.done) {
|
|
1098
|
+
return acc;
|
|
1099
|
+
}
|
|
1100
|
+
if (acc === void 0 || comparator(c.value, acc[0]) < 0) {
|
|
1101
|
+
return [c.value, i];
|
|
1102
|
+
}
|
|
1103
|
+
return acc;
|
|
1104
|
+
},
|
|
1105
|
+
void 0
|
|
1106
|
+
);
|
|
1107
|
+
assert(min !== void 0, "min is undefined");
|
|
1108
|
+
current[min[1]] = iterators[min[1]].next();
|
|
1109
|
+
if (lastYielded !== void 0 && distinct && comparator(lastYielded, min[0]) === 0) {
|
|
1110
|
+
continue;
|
|
1111
|
+
}
|
|
1112
|
+
lastYielded = min[0];
|
|
1113
|
+
yield min[0];
|
|
1114
|
+
}
|
|
1115
|
+
} finally {
|
|
1116
|
+
for (const it of iterators) {
|
|
1117
|
+
it.return?.();
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
// ../zql/src/ivm/fan-in.ts
|
|
1123
|
+
var FanIn = class {
|
|
1124
|
+
#inputs;
|
|
1125
|
+
#fanOut;
|
|
1126
|
+
#schema;
|
|
1127
|
+
#output = throwOutput;
|
|
1128
|
+
constructor(fanOut, inputs) {
|
|
1129
|
+
this.#inputs = inputs;
|
|
1130
|
+
this.#schema = fanOut.getSchema();
|
|
1131
|
+
this.#fanOut = fanOut;
|
|
1132
|
+
for (const input of inputs) {
|
|
1133
|
+
input.setOutput(this);
|
|
1134
|
+
assert(this.#schema === input.getSchema(), `Schema mismatch in fan-in`);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
setOutput(output) {
|
|
1138
|
+
this.#output = output;
|
|
1139
|
+
}
|
|
1140
|
+
destroy() {
|
|
1141
|
+
for (const input of this.#inputs) {
|
|
1142
|
+
input.destroy();
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
getSchema() {
|
|
1146
|
+
return this.#schema;
|
|
1147
|
+
}
|
|
1148
|
+
fetch(req) {
|
|
1149
|
+
return this.#fetchOrCleanup((input) => input.fetch(req));
|
|
1150
|
+
}
|
|
1151
|
+
cleanup(req) {
|
|
1152
|
+
return this.#fetchOrCleanup((input) => input.cleanup(req));
|
|
1153
|
+
}
|
|
1154
|
+
*#fetchOrCleanup(streamProvider) {
|
|
1155
|
+
const iterables = this.#inputs.map((input) => streamProvider(input));
|
|
1156
|
+
yield* mergeIterables(
|
|
1157
|
+
iterables,
|
|
1158
|
+
(l, r) => must(this.#schema).compareRows(l.row, r.row),
|
|
1159
|
+
true
|
|
1160
|
+
);
|
|
1161
|
+
}
|
|
1162
|
+
push(change) {
|
|
1163
|
+
this.#fanOut.onFanInReceivedPush();
|
|
1164
|
+
this.#output.push(change);
|
|
1165
|
+
}
|
|
1166
|
+
};
|
|
1167
|
+
|
|
1168
|
+
// ../zql/src/ivm/fan-out.ts
|
|
1169
|
+
var FanOut = class {
|
|
1170
|
+
#input;
|
|
1171
|
+
#outputs = [];
|
|
1172
|
+
// FanOut is paired with a FanIn.
|
|
1173
|
+
// Once FanIn has received a push from FanOut along
|
|
1174
|
+
// any branch, FanOut no longer needs to push that value
|
|
1175
|
+
// across the rest of its outputs..
|
|
1176
|
+
#fanInReceivedPush = false;
|
|
1177
|
+
#destroyCount = 0;
|
|
1178
|
+
constructor(input) {
|
|
1179
|
+
this.#input = input;
|
|
1180
|
+
input.setOutput(this);
|
|
1181
|
+
}
|
|
1182
|
+
setOutput(output) {
|
|
1183
|
+
this.#outputs.push(output);
|
|
1184
|
+
}
|
|
1185
|
+
destroy() {
|
|
1186
|
+
if (this.#destroyCount < this.#outputs.length) {
|
|
1187
|
+
if (this.#destroyCount === 0) {
|
|
1188
|
+
this.#input.destroy();
|
|
1189
|
+
}
|
|
1190
|
+
++this.#destroyCount;
|
|
1191
|
+
} else {
|
|
1192
|
+
throw new Error("FanOut already destroyed once for each output");
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
getSchema() {
|
|
1196
|
+
return this.#input.getSchema();
|
|
1197
|
+
}
|
|
1198
|
+
fetch(req) {
|
|
1199
|
+
return this.#input.fetch(req);
|
|
1200
|
+
}
|
|
1201
|
+
cleanup(req) {
|
|
1202
|
+
return this.#input.cleanup(req);
|
|
1203
|
+
}
|
|
1204
|
+
onFanInReceivedPush() {
|
|
1205
|
+
this.#fanInReceivedPush = true;
|
|
1206
|
+
}
|
|
1207
|
+
push(change) {
|
|
1208
|
+
this.#fanInReceivedPush = false;
|
|
1209
|
+
for (const out of this.#outputs) {
|
|
1210
|
+
out.push(change);
|
|
1211
|
+
if (this.#fanInReceivedPush) {
|
|
1212
|
+
return;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
};
|
|
1217
|
+
|
|
1218
|
+
// ../zql/src/ivm/maybe-split-and-push-edit-change.ts
|
|
1219
|
+
function maybeSplitAndPushEditChange(change, predicate, output) {
|
|
1220
|
+
const oldWasPresent = predicate(change.oldNode.row);
|
|
1221
|
+
const newIsPresent = predicate(change.node.row);
|
|
1222
|
+
if (oldWasPresent && newIsPresent) {
|
|
1223
|
+
output.push(change);
|
|
1224
|
+
} else if (oldWasPresent && !newIsPresent) {
|
|
1225
|
+
output.push({
|
|
1226
|
+
type: "remove",
|
|
1227
|
+
node: change.oldNode
|
|
1228
|
+
});
|
|
1229
|
+
} else if (!oldWasPresent && newIsPresent) {
|
|
1230
|
+
output.push({
|
|
1231
|
+
type: "add",
|
|
1232
|
+
node: change.node
|
|
1233
|
+
});
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
// ../zql/src/ivm/filter-push.ts
|
|
1238
|
+
function filterPush(change, output, predicate) {
|
|
1239
|
+
if (!predicate) {
|
|
1240
|
+
output.push(change);
|
|
1241
|
+
return;
|
|
1242
|
+
}
|
|
1243
|
+
switch (change.type) {
|
|
1244
|
+
case "add":
|
|
1245
|
+
case "remove":
|
|
1246
|
+
if (predicate(change.node.row)) {
|
|
1247
|
+
output.push(change);
|
|
1248
|
+
}
|
|
1249
|
+
break;
|
|
1250
|
+
case "child":
|
|
1251
|
+
if (predicate(change.node.row)) {
|
|
1252
|
+
output.push(change);
|
|
1253
|
+
}
|
|
1254
|
+
break;
|
|
1255
|
+
case "edit":
|
|
1256
|
+
maybeSplitAndPushEditChange(change, predicate, output);
|
|
1257
|
+
break;
|
|
1258
|
+
default:
|
|
1259
|
+
unreachable(change);
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
// ../zql/src/ivm/filter.ts
|
|
1264
|
+
var Filter = class {
|
|
1265
|
+
#input;
|
|
1266
|
+
#predicate;
|
|
1267
|
+
#output = throwOutput;
|
|
1268
|
+
constructor(input, predicate) {
|
|
1269
|
+
this.#input = input;
|
|
1270
|
+
this.#predicate = predicate;
|
|
1271
|
+
input.setOutput(this);
|
|
1272
|
+
}
|
|
1273
|
+
setOutput(output) {
|
|
1274
|
+
this.#output = output;
|
|
1275
|
+
}
|
|
1276
|
+
destroy() {
|
|
1277
|
+
this.#input.destroy();
|
|
1278
|
+
}
|
|
1279
|
+
getSchema() {
|
|
1280
|
+
return this.#input.getSchema();
|
|
1281
|
+
}
|
|
1282
|
+
*fetch(req) {
|
|
1283
|
+
for (const node of this.#input.fetch(req)) {
|
|
1284
|
+
if (this.#predicate(node.row)) {
|
|
1285
|
+
yield node;
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
*cleanup(req) {
|
|
1290
|
+
for (const node of this.#input.cleanup(req)) {
|
|
1291
|
+
if (this.#predicate(node.row)) {
|
|
1292
|
+
yield node;
|
|
1293
|
+
} else {
|
|
1294
|
+
drainStreams(node);
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
push(change) {
|
|
1299
|
+
filterPush(change, this.#output, this.#predicate);
|
|
1300
|
+
}
|
|
1301
|
+
};
|
|
1302
|
+
|
|
1303
|
+
// ../zql/src/ivm/join.ts
|
|
1304
|
+
var Join = class {
|
|
1305
|
+
#parent;
|
|
1306
|
+
#child;
|
|
1307
|
+
#storage;
|
|
1308
|
+
#parentKey;
|
|
1309
|
+
#childKey;
|
|
1310
|
+
#relationshipName;
|
|
1311
|
+
#schema;
|
|
1312
|
+
#output = throwOutput;
|
|
1313
|
+
constructor({
|
|
1314
|
+
parent,
|
|
1315
|
+
child,
|
|
1316
|
+
storage,
|
|
1317
|
+
parentKey,
|
|
1318
|
+
childKey,
|
|
1319
|
+
relationshipName,
|
|
1320
|
+
hidden,
|
|
1321
|
+
system
|
|
1322
|
+
}) {
|
|
1323
|
+
assert(parent !== child, "Parent and child must be different operators");
|
|
1324
|
+
assert(
|
|
1325
|
+
parentKey.length === childKey.length,
|
|
1326
|
+
"The parentKey and childKey keys must have same length"
|
|
1327
|
+
);
|
|
1328
|
+
this.#parent = parent;
|
|
1329
|
+
this.#child = child;
|
|
1330
|
+
this.#storage = storage;
|
|
1331
|
+
this.#parentKey = parentKey;
|
|
1332
|
+
this.#childKey = childKey;
|
|
1333
|
+
this.#relationshipName = relationshipName;
|
|
1334
|
+
const parentSchema = parent.getSchema();
|
|
1335
|
+
const childSchema = child.getSchema();
|
|
1336
|
+
this.#schema = {
|
|
1337
|
+
...parentSchema,
|
|
1338
|
+
relationships: {
|
|
1339
|
+
...parentSchema.relationships,
|
|
1340
|
+
[relationshipName]: {
|
|
1341
|
+
...childSchema,
|
|
1342
|
+
isHidden: hidden,
|
|
1343
|
+
system
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
};
|
|
1347
|
+
parent.setOutput({
|
|
1348
|
+
push: (change) => this.#pushParent(change)
|
|
1349
|
+
});
|
|
1350
|
+
child.setOutput({
|
|
1351
|
+
push: (change) => this.#pushChild(change)
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
destroy() {
|
|
1355
|
+
this.#parent.destroy();
|
|
1356
|
+
this.#child.destroy();
|
|
1357
|
+
}
|
|
1358
|
+
setOutput(output) {
|
|
1359
|
+
this.#output = output;
|
|
1360
|
+
}
|
|
1361
|
+
getSchema() {
|
|
1362
|
+
return this.#schema;
|
|
1363
|
+
}
|
|
1364
|
+
*fetch(req) {
|
|
1365
|
+
for (const parentNode of this.#parent.fetch(req)) {
|
|
1366
|
+
yield this.#processParentNode(
|
|
1367
|
+
parentNode.row,
|
|
1368
|
+
parentNode.relationships,
|
|
1369
|
+
"fetch"
|
|
1370
|
+
);
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
*cleanup(req) {
|
|
1374
|
+
for (const parentNode of this.#parent.cleanup(req)) {
|
|
1375
|
+
yield this.#processParentNode(
|
|
1376
|
+
parentNode.row,
|
|
1377
|
+
parentNode.relationships,
|
|
1378
|
+
"cleanup"
|
|
1379
|
+
);
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
#pushParent(change) {
|
|
1383
|
+
switch (change.type) {
|
|
1384
|
+
case "add":
|
|
1385
|
+
this.#output.push({
|
|
1386
|
+
type: "add",
|
|
1387
|
+
node: this.#processParentNode(
|
|
1388
|
+
change.node.row,
|
|
1389
|
+
change.node.relationships,
|
|
1390
|
+
"fetch"
|
|
1391
|
+
)
|
|
1392
|
+
});
|
|
1393
|
+
break;
|
|
1394
|
+
case "remove":
|
|
1395
|
+
this.#output.push({
|
|
1396
|
+
type: "remove",
|
|
1397
|
+
node: this.#processParentNode(
|
|
1398
|
+
change.node.row,
|
|
1399
|
+
change.node.relationships,
|
|
1400
|
+
"cleanup"
|
|
1401
|
+
)
|
|
1402
|
+
});
|
|
1403
|
+
break;
|
|
1404
|
+
case "child":
|
|
1405
|
+
this.#output.push({
|
|
1406
|
+
type: "child",
|
|
1407
|
+
node: this.#processParentNode(
|
|
1408
|
+
change.node.row,
|
|
1409
|
+
change.node.relationships,
|
|
1410
|
+
"fetch"
|
|
1411
|
+
),
|
|
1412
|
+
child: change.child
|
|
1413
|
+
});
|
|
1414
|
+
break;
|
|
1415
|
+
case "edit": {
|
|
1416
|
+
if (rowEqualsForCompoundKey(
|
|
1417
|
+
change.oldNode.row,
|
|
1418
|
+
change.node.row,
|
|
1419
|
+
this.#parentKey
|
|
1420
|
+
)) {
|
|
1421
|
+
this.#output.push({
|
|
1422
|
+
type: "edit",
|
|
1423
|
+
oldNode: this.#processParentNode(
|
|
1424
|
+
change.oldNode.row,
|
|
1425
|
+
change.oldNode.relationships,
|
|
1426
|
+
"cleanup"
|
|
1427
|
+
),
|
|
1428
|
+
node: this.#processParentNode(
|
|
1429
|
+
change.node.row,
|
|
1430
|
+
change.node.relationships,
|
|
1431
|
+
"fetch"
|
|
1432
|
+
)
|
|
1433
|
+
});
|
|
1434
|
+
} else {
|
|
1435
|
+
this.#pushParent({
|
|
1436
|
+
type: "remove",
|
|
1437
|
+
node: change.oldNode
|
|
1438
|
+
});
|
|
1439
|
+
this.#pushParent({
|
|
1440
|
+
type: "add",
|
|
1441
|
+
node: change.node
|
|
1442
|
+
});
|
|
1443
|
+
}
|
|
1444
|
+
break;
|
|
1445
|
+
}
|
|
1446
|
+
default:
|
|
1447
|
+
unreachable(change);
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
#pushChild(change) {
|
|
1451
|
+
const pushChildChange = (childRow, change2) => {
|
|
1452
|
+
const parentNodes = this.#parent.fetch({
|
|
1453
|
+
constraint: Object.fromEntries(
|
|
1454
|
+
this.#parentKey.map((key, i) => [key, childRow[this.#childKey[i]]])
|
|
1455
|
+
)
|
|
1456
|
+
});
|
|
1457
|
+
for (const parentNode of parentNodes) {
|
|
1458
|
+
const childChange = {
|
|
1459
|
+
type: "child",
|
|
1460
|
+
node: this.#processParentNode(
|
|
1461
|
+
parentNode.row,
|
|
1462
|
+
parentNode.relationships,
|
|
1463
|
+
"fetch"
|
|
1464
|
+
),
|
|
1465
|
+
child: {
|
|
1466
|
+
relationshipName: this.#relationshipName,
|
|
1467
|
+
change: change2
|
|
1468
|
+
}
|
|
1469
|
+
};
|
|
1470
|
+
this.#output.push(childChange);
|
|
1471
|
+
}
|
|
1472
|
+
};
|
|
1473
|
+
switch (change.type) {
|
|
1474
|
+
case "add":
|
|
1475
|
+
case "remove":
|
|
1476
|
+
pushChildChange(change.node.row, change);
|
|
1477
|
+
break;
|
|
1478
|
+
case "child":
|
|
1479
|
+
pushChildChange(change.node.row, change);
|
|
1480
|
+
break;
|
|
1481
|
+
case "edit": {
|
|
1482
|
+
const childRow = change.node.row;
|
|
1483
|
+
const oldChildRow = change.oldNode.row;
|
|
1484
|
+
if (rowEqualsForCompoundKey(oldChildRow, childRow, this.#childKey)) {
|
|
1485
|
+
pushChildChange(childRow, change);
|
|
1486
|
+
} else {
|
|
1487
|
+
pushChildChange(oldChildRow, {
|
|
1488
|
+
type: "remove",
|
|
1489
|
+
node: change.oldNode
|
|
1490
|
+
});
|
|
1491
|
+
pushChildChange(childRow, {
|
|
1492
|
+
type: "add",
|
|
1493
|
+
node: change.node
|
|
1494
|
+
});
|
|
1495
|
+
}
|
|
1496
|
+
break;
|
|
1497
|
+
}
|
|
1498
|
+
default:
|
|
1499
|
+
unreachable(change);
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
#processParentNode(parentNodeRow, parentNodeRelations, mode) {
|
|
1503
|
+
let method = mode;
|
|
1504
|
+
let storageUpdated = false;
|
|
1505
|
+
const childStream = () => {
|
|
1506
|
+
if (!storageUpdated) {
|
|
1507
|
+
if (mode === "cleanup") {
|
|
1508
|
+
this.#storage.del(
|
|
1509
|
+
makeStorageKey(
|
|
1510
|
+
this.#parentKey,
|
|
1511
|
+
this.#parent.getSchema().primaryKey,
|
|
1512
|
+
parentNodeRow
|
|
1513
|
+
)
|
|
1514
|
+
);
|
|
1515
|
+
const empty = [
|
|
1516
|
+
...take(
|
|
1517
|
+
this.#storage.scan({
|
|
1518
|
+
prefix: makeStorageKeyPrefix(parentNodeRow, this.#parentKey)
|
|
1519
|
+
}),
|
|
1520
|
+
1
|
|
1521
|
+
)
|
|
1522
|
+
].length === 0;
|
|
1523
|
+
method = empty ? "cleanup" : "fetch";
|
|
1524
|
+
}
|
|
1525
|
+
storageUpdated = true;
|
|
1526
|
+
if (mode === "fetch") {
|
|
1527
|
+
this.#storage.set(
|
|
1528
|
+
makeStorageKey(
|
|
1529
|
+
this.#parentKey,
|
|
1530
|
+
this.#parent.getSchema().primaryKey,
|
|
1531
|
+
parentNodeRow
|
|
1532
|
+
),
|
|
1533
|
+
true
|
|
1534
|
+
);
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
return this.#child[method]({
|
|
1538
|
+
constraint: Object.fromEntries(
|
|
1539
|
+
this.#childKey.map((key, i) => [
|
|
1540
|
+
key,
|
|
1541
|
+
parentNodeRow[this.#parentKey[i]]
|
|
1542
|
+
])
|
|
1543
|
+
)
|
|
1544
|
+
});
|
|
1545
|
+
};
|
|
1546
|
+
return {
|
|
1547
|
+
row: parentNodeRow,
|
|
1548
|
+
relationships: {
|
|
1549
|
+
...parentNodeRelations,
|
|
1550
|
+
[this.#relationshipName]: childStream
|
|
1551
|
+
}
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
1554
|
+
};
|
|
1555
|
+
function makeStorageKeyForValues(values) {
|
|
1556
|
+
const json = JSON.stringify(["pKeySet", ...values]);
|
|
1557
|
+
return json.substring(1, json.length - 1) + ",";
|
|
1558
|
+
}
|
|
1559
|
+
function makeStorageKeyPrefix(row, key) {
|
|
1560
|
+
return makeStorageKeyForValues(key.map((k) => row[k]));
|
|
1561
|
+
}
|
|
1562
|
+
function makeStorageKey(key, primaryKey, row) {
|
|
1563
|
+
const values = key.map((k) => row[k]);
|
|
1564
|
+
for (const key2 of primaryKey) {
|
|
1565
|
+
values.push(row[key2]);
|
|
1566
|
+
}
|
|
1567
|
+
return makeStorageKeyForValues(values);
|
|
1568
|
+
}
|
|
1569
|
+
function rowEqualsForCompoundKey(a, b, key) {
|
|
1570
|
+
for (let i = 0; i < key.length; i++) {
|
|
1571
|
+
if (!valuesEqual(a[key[i]], b[key[i]])) {
|
|
1572
|
+
return false;
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
return true;
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
// ../zql/src/ivm/skip.ts
|
|
1579
|
+
var Skip = class {
|
|
1580
|
+
#input;
|
|
1581
|
+
#bound;
|
|
1582
|
+
#comparator;
|
|
1583
|
+
#output = throwOutput;
|
|
1584
|
+
constructor(input, bound) {
|
|
1585
|
+
this.#input = input;
|
|
1586
|
+
this.#bound = bound;
|
|
1587
|
+
this.#comparator = input.getSchema().compareRows;
|
|
1588
|
+
input.setOutput(this);
|
|
1589
|
+
}
|
|
1590
|
+
getSchema() {
|
|
1591
|
+
return this.#input.getSchema();
|
|
1592
|
+
}
|
|
1593
|
+
fetch(req) {
|
|
1594
|
+
return this.#fetchOrCleanup("fetch", req);
|
|
1595
|
+
}
|
|
1596
|
+
cleanup(req) {
|
|
1597
|
+
return this.#fetchOrCleanup("fetch", req);
|
|
1598
|
+
}
|
|
1599
|
+
*#fetchOrCleanup(method, req) {
|
|
1600
|
+
const start = this.#getStart(req);
|
|
1601
|
+
if (start === "empty") {
|
|
1602
|
+
return;
|
|
1603
|
+
}
|
|
1604
|
+
const nodes = this.#input[method]({ ...req, start });
|
|
1605
|
+
if (!req.reverse) {
|
|
1606
|
+
yield* nodes;
|
|
1607
|
+
return;
|
|
1608
|
+
}
|
|
1609
|
+
for (const node of nodes) {
|
|
1610
|
+
if (!this.#shouldBePresent(node.row)) {
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
yield node;
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
setOutput(output) {
|
|
1617
|
+
this.#output = output;
|
|
1618
|
+
}
|
|
1619
|
+
destroy() {
|
|
1620
|
+
this.#input.destroy();
|
|
1621
|
+
}
|
|
1622
|
+
#shouldBePresent(row) {
|
|
1623
|
+
const cmp2 = this.#comparator(this.#bound.row, row);
|
|
1624
|
+
return cmp2 < 0 || cmp2 === 0 && !this.#bound.exclusive;
|
|
1625
|
+
}
|
|
1626
|
+
push(change) {
|
|
1627
|
+
const shouldBePresent = (row) => this.#shouldBePresent(row);
|
|
1628
|
+
if (change.type === "edit") {
|
|
1629
|
+
maybeSplitAndPushEditChange(change, shouldBePresent, this.#output);
|
|
1630
|
+
return;
|
|
1631
|
+
}
|
|
1632
|
+
change;
|
|
1633
|
+
if (shouldBePresent(change.node.row)) {
|
|
1634
|
+
this.#output.push(change);
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
#getStart(req) {
|
|
1638
|
+
const boundStart = {
|
|
1639
|
+
row: this.#bound.row,
|
|
1640
|
+
basis: this.#bound.exclusive ? "after" : "at"
|
|
1641
|
+
};
|
|
1642
|
+
if (!req.start) {
|
|
1643
|
+
if (req.reverse) {
|
|
1644
|
+
return void 0;
|
|
1645
|
+
}
|
|
1646
|
+
return boundStart;
|
|
1647
|
+
}
|
|
1648
|
+
const cmp2 = this.#comparator(this.#bound.row, req.start.row);
|
|
1649
|
+
if (!req.reverse) {
|
|
1650
|
+
if (cmp2 > 0) {
|
|
1651
|
+
return boundStart;
|
|
1652
|
+
}
|
|
1653
|
+
if (cmp2 === 0) {
|
|
1654
|
+
if (this.#bound.exclusive || req.start.basis === "after") {
|
|
1655
|
+
return {
|
|
1656
|
+
row: this.#bound.row,
|
|
1657
|
+
basis: "after"
|
|
1658
|
+
};
|
|
1659
|
+
}
|
|
1660
|
+
return boundStart;
|
|
1661
|
+
}
|
|
1662
|
+
return req.start;
|
|
1663
|
+
}
|
|
1664
|
+
req.reverse;
|
|
1665
|
+
if (cmp2 > 0) {
|
|
1666
|
+
return "empty";
|
|
1667
|
+
}
|
|
1668
|
+
if (cmp2 === 0) {
|
|
1669
|
+
if (!this.#bound.exclusive && req.start.basis === "at") {
|
|
1670
|
+
return boundStart;
|
|
1671
|
+
}
|
|
1672
|
+
return "empty";
|
|
1673
|
+
}
|
|
1674
|
+
return req.start;
|
|
1675
|
+
}
|
|
1676
|
+
};
|
|
1677
|
+
|
|
1678
|
+
// ../zql/src/ivm/take.ts
|
|
1679
|
+
var MAX_BOUND_KEY = "maxBound";
|
|
1680
|
+
var Take = class {
|
|
1681
|
+
#input;
|
|
1682
|
+
#storage;
|
|
1683
|
+
#limit;
|
|
1684
|
+
#partitionKey;
|
|
1685
|
+
#partitionKeyComparator;
|
|
1686
|
+
#output = throwOutput;
|
|
1687
|
+
constructor(input, storage, limit, partitionKey) {
|
|
1688
|
+
assert(limit >= 0);
|
|
1689
|
+
assertOrderingIncludesPK(
|
|
1690
|
+
input.getSchema().sort,
|
|
1691
|
+
input.getSchema().primaryKey
|
|
1692
|
+
);
|
|
1693
|
+
input.setOutput(this);
|
|
1694
|
+
this.#input = input;
|
|
1695
|
+
this.#storage = storage;
|
|
1696
|
+
this.#limit = limit;
|
|
1697
|
+
this.#partitionKey = partitionKey;
|
|
1698
|
+
this.#partitionKeyComparator = partitionKey && makePartitionKeyComparator(partitionKey);
|
|
1699
|
+
}
|
|
1700
|
+
setOutput(output) {
|
|
1701
|
+
this.#output = output;
|
|
1702
|
+
}
|
|
1703
|
+
getSchema() {
|
|
1704
|
+
return this.#input.getSchema();
|
|
1705
|
+
}
|
|
1706
|
+
*fetch(req) {
|
|
1707
|
+
if (!this.#partitionKey || req.constraint && constraintMatchesPartitionKey(req.constraint, this.#partitionKey)) {
|
|
1708
|
+
const takeStateKey = getTakeStateKey(this.#partitionKey, req.constraint);
|
|
1709
|
+
const takeState = this.#storage.get(takeStateKey);
|
|
1710
|
+
if (!takeState) {
|
|
1711
|
+
yield* this.#initialFetch(req);
|
|
1712
|
+
return;
|
|
1713
|
+
}
|
|
1714
|
+
if (takeState.bound === void 0) {
|
|
1715
|
+
return;
|
|
1716
|
+
}
|
|
1717
|
+
for (const inputNode of this.#input.fetch(req)) {
|
|
1718
|
+
if (this.getSchema().compareRows(takeState.bound, inputNode.row) < 0) {
|
|
1719
|
+
return;
|
|
1720
|
+
}
|
|
1721
|
+
yield inputNode;
|
|
1722
|
+
}
|
|
1723
|
+
return;
|
|
1724
|
+
}
|
|
1725
|
+
const maxBound = this.#storage.get(MAX_BOUND_KEY);
|
|
1726
|
+
if (maxBound === void 0) {
|
|
1727
|
+
return;
|
|
1728
|
+
}
|
|
1729
|
+
for (const inputNode of this.#input.fetch(req)) {
|
|
1730
|
+
if (this.getSchema().compareRows(inputNode.row, maxBound) > 0) {
|
|
1731
|
+
return;
|
|
1732
|
+
}
|
|
1733
|
+
const takeStateKey = getTakeStateKey(this.#partitionKey, inputNode.row);
|
|
1734
|
+
const takeState = this.#storage.get(takeStateKey);
|
|
1735
|
+
if (takeState?.bound !== void 0 && this.getSchema().compareRows(takeState.bound, inputNode.row) >= 0) {
|
|
1736
|
+
yield inputNode;
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
*#initialFetch(req) {
|
|
1741
|
+
assert(req.start === void 0);
|
|
1742
|
+
assert(!req.reverse);
|
|
1743
|
+
assert(constraintMatchesPartitionKey(req.constraint, this.#partitionKey));
|
|
1744
|
+
if (this.#limit === 0) {
|
|
1745
|
+
return;
|
|
1746
|
+
}
|
|
1747
|
+
const takeStateKey = getTakeStateKey(this.#partitionKey, req.constraint);
|
|
1748
|
+
assert(this.#storage.get(takeStateKey) === void 0);
|
|
1749
|
+
let size = 0;
|
|
1750
|
+
let bound;
|
|
1751
|
+
let downstreamEarlyReturn = true;
|
|
1752
|
+
let exceptionThrown = false;
|
|
1753
|
+
try {
|
|
1754
|
+
for (const inputNode of this.#input.fetch(req)) {
|
|
1755
|
+
yield inputNode;
|
|
1756
|
+
bound = inputNode.row;
|
|
1757
|
+
size++;
|
|
1758
|
+
if (size === this.#limit) {
|
|
1759
|
+
break;
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
downstreamEarlyReturn = false;
|
|
1763
|
+
} catch (e) {
|
|
1764
|
+
exceptionThrown = true;
|
|
1765
|
+
throw e;
|
|
1766
|
+
} finally {
|
|
1767
|
+
if (!exceptionThrown) {
|
|
1768
|
+
this.#setTakeState(
|
|
1769
|
+
takeStateKey,
|
|
1770
|
+
size,
|
|
1771
|
+
bound,
|
|
1772
|
+
this.#storage.get(MAX_BOUND_KEY)
|
|
1773
|
+
);
|
|
1774
|
+
assert(
|
|
1775
|
+
!downstreamEarlyReturn,
|
|
1776
|
+
"Unexpected early return prevented full hydration"
|
|
1777
|
+
);
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
*cleanup(req) {
|
|
1782
|
+
assert(req.start === void 0);
|
|
1783
|
+
assert(constraintMatchesPartitionKey(req.constraint, this.#partitionKey));
|
|
1784
|
+
const takeStateKey = getTakeStateKey(this.#partitionKey, req.constraint);
|
|
1785
|
+
this.#storage.del(takeStateKey);
|
|
1786
|
+
let size = 0;
|
|
1787
|
+
for (const inputNode of this.#input.cleanup(req)) {
|
|
1788
|
+
if (size === this.#limit) {
|
|
1789
|
+
return;
|
|
1790
|
+
}
|
|
1791
|
+
size++;
|
|
1792
|
+
yield inputNode;
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
#getStateAndConstraint(row) {
|
|
1796
|
+
const takeStateKey = getTakeStateKey(this.#partitionKey, row);
|
|
1797
|
+
const takeState = this.#storage.get(takeStateKey);
|
|
1798
|
+
let maxBound;
|
|
1799
|
+
let constraint;
|
|
1800
|
+
if (takeState) {
|
|
1801
|
+
maxBound = this.#storage.get(MAX_BOUND_KEY);
|
|
1802
|
+
constraint = this.#partitionKey && Object.fromEntries(
|
|
1803
|
+
this.#partitionKey.map((key) => [key, row[key]])
|
|
1804
|
+
);
|
|
1805
|
+
}
|
|
1806
|
+
return { takeState, takeStateKey, maxBound, constraint };
|
|
1807
|
+
}
|
|
1808
|
+
push(change) {
|
|
1809
|
+
if (change.type === "edit") {
|
|
1810
|
+
this.#pushEditChange(change);
|
|
1811
|
+
return;
|
|
1812
|
+
}
|
|
1813
|
+
const { takeState, takeStateKey, maxBound, constraint } = this.#getStateAndConstraint(change.node.row);
|
|
1814
|
+
if (!takeState) {
|
|
1815
|
+
return;
|
|
1816
|
+
}
|
|
1817
|
+
const { compareRows } = this.getSchema();
|
|
1818
|
+
if (change.type === "add") {
|
|
1819
|
+
if (takeState.size < this.#limit) {
|
|
1820
|
+
this.#setTakeState(
|
|
1821
|
+
takeStateKey,
|
|
1822
|
+
takeState.size + 1,
|
|
1823
|
+
takeState.bound === void 0 || compareRows(takeState.bound, change.node.row) < 0 ? change.node.row : takeState.bound,
|
|
1824
|
+
maxBound
|
|
1825
|
+
);
|
|
1826
|
+
this.#output.push(change);
|
|
1827
|
+
return;
|
|
1828
|
+
}
|
|
1829
|
+
if (takeState.bound === void 0 || compareRows(change.node.row, takeState.bound) >= 0) {
|
|
1830
|
+
return;
|
|
1831
|
+
}
|
|
1832
|
+
let beforeBoundNode;
|
|
1833
|
+
let boundNode;
|
|
1834
|
+
if (this.#limit === 1) {
|
|
1835
|
+
boundNode = must(
|
|
1836
|
+
first(
|
|
1837
|
+
this.#input.fetch({
|
|
1838
|
+
start: {
|
|
1839
|
+
row: takeState.bound,
|
|
1840
|
+
basis: "at"
|
|
1841
|
+
},
|
|
1842
|
+
constraint
|
|
1843
|
+
})
|
|
1844
|
+
)
|
|
1845
|
+
);
|
|
1846
|
+
} else {
|
|
1847
|
+
[boundNode, beforeBoundNode] = take(
|
|
1848
|
+
this.#input.fetch({
|
|
1849
|
+
start: {
|
|
1850
|
+
row: takeState.bound,
|
|
1851
|
+
basis: "at"
|
|
1852
|
+
},
|
|
1853
|
+
constraint,
|
|
1854
|
+
reverse: true
|
|
1855
|
+
}),
|
|
1856
|
+
2
|
|
1857
|
+
);
|
|
1858
|
+
}
|
|
1859
|
+
const removeChange = {
|
|
1860
|
+
type: "remove",
|
|
1861
|
+
node: boundNode
|
|
1862
|
+
};
|
|
1863
|
+
this.#setTakeState(
|
|
1864
|
+
takeStateKey,
|
|
1865
|
+
takeState.size,
|
|
1866
|
+
beforeBoundNode === void 0 || compareRows(change.node.row, beforeBoundNode.row) > 0 ? change.node.row : beforeBoundNode.row,
|
|
1867
|
+
maxBound
|
|
1868
|
+
);
|
|
1869
|
+
this.#output.push(removeChange);
|
|
1870
|
+
this.#output.push(change);
|
|
1871
|
+
} else if (change.type === "remove") {
|
|
1872
|
+
if (takeState.bound === void 0) {
|
|
1873
|
+
return;
|
|
1874
|
+
}
|
|
1875
|
+
const compToBound = compareRows(change.node.row, takeState.bound);
|
|
1876
|
+
if (compToBound > 0) {
|
|
1877
|
+
return;
|
|
1878
|
+
}
|
|
1879
|
+
const [beforeBoundNode] = take(
|
|
1880
|
+
this.#input.fetch({
|
|
1881
|
+
start: {
|
|
1882
|
+
row: takeState.bound,
|
|
1883
|
+
basis: "after"
|
|
1884
|
+
},
|
|
1885
|
+
constraint,
|
|
1886
|
+
reverse: true
|
|
1887
|
+
}),
|
|
1888
|
+
1
|
|
1889
|
+
);
|
|
1890
|
+
let newBound;
|
|
1891
|
+
if (beforeBoundNode) {
|
|
1892
|
+
const push = compareRows(beforeBoundNode.row, takeState.bound) > 0;
|
|
1893
|
+
newBound = {
|
|
1894
|
+
node: beforeBoundNode,
|
|
1895
|
+
push
|
|
1896
|
+
};
|
|
1897
|
+
}
|
|
1898
|
+
if (!newBound?.push) {
|
|
1899
|
+
for (const node of this.#input.fetch({
|
|
1900
|
+
start: {
|
|
1901
|
+
row: takeState.bound,
|
|
1902
|
+
basis: "at"
|
|
1903
|
+
},
|
|
1904
|
+
constraint
|
|
1905
|
+
})) {
|
|
1906
|
+
const push = compareRows(node.row, takeState.bound) > 0;
|
|
1907
|
+
newBound = {
|
|
1908
|
+
node,
|
|
1909
|
+
push
|
|
1910
|
+
};
|
|
1911
|
+
if (push) {
|
|
1912
|
+
break;
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
if (newBound?.push) {
|
|
1917
|
+
this.#setTakeState(
|
|
1918
|
+
takeStateKey,
|
|
1919
|
+
takeState.size,
|
|
1920
|
+
newBound.node.row,
|
|
1921
|
+
maxBound
|
|
1922
|
+
);
|
|
1923
|
+
this.#output.push(change);
|
|
1924
|
+
this.#output.push({
|
|
1925
|
+
type: "add",
|
|
1926
|
+
node: newBound.node
|
|
1927
|
+
});
|
|
1928
|
+
return;
|
|
1929
|
+
}
|
|
1930
|
+
this.#setTakeState(
|
|
1931
|
+
takeStateKey,
|
|
1932
|
+
takeState.size - 1,
|
|
1933
|
+
newBound?.node.row,
|
|
1934
|
+
maxBound
|
|
1935
|
+
);
|
|
1936
|
+
this.#output.push(change);
|
|
1937
|
+
} else if (change.type === "child") {
|
|
1938
|
+
if (takeState.bound && compareRows(change.node.row, takeState.bound) <= 0) {
|
|
1939
|
+
this.#output.push(change);
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
#pushEditChange(change) {
|
|
1944
|
+
if (this.#partitionKeyComparator && this.#partitionKeyComparator(change.oldNode.row, change.node.row) !== 0) {
|
|
1945
|
+
this.push({
|
|
1946
|
+
type: "remove",
|
|
1947
|
+
node: change.oldNode
|
|
1948
|
+
});
|
|
1949
|
+
this.push({
|
|
1950
|
+
type: "add",
|
|
1951
|
+
node: change.node
|
|
1952
|
+
});
|
|
1953
|
+
return;
|
|
1954
|
+
}
|
|
1955
|
+
const { takeState, takeStateKey, maxBound, constraint } = this.#getStateAndConstraint(change.oldNode.row);
|
|
1956
|
+
if (!takeState) {
|
|
1957
|
+
return;
|
|
1958
|
+
}
|
|
1959
|
+
assert(takeState.bound, "Bound should be set");
|
|
1960
|
+
const { compareRows } = this.getSchema();
|
|
1961
|
+
const oldCmp = compareRows(change.oldNode.row, takeState.bound);
|
|
1962
|
+
const newCmp = compareRows(change.node.row, takeState.bound);
|
|
1963
|
+
const replaceBoundAndForwardChange = () => {
|
|
1964
|
+
this.#setTakeState(
|
|
1965
|
+
takeStateKey,
|
|
1966
|
+
takeState.size,
|
|
1967
|
+
change.node.row,
|
|
1968
|
+
maxBound
|
|
1969
|
+
);
|
|
1970
|
+
this.#output.push(change);
|
|
1971
|
+
};
|
|
1972
|
+
if (oldCmp === 0) {
|
|
1973
|
+
if (newCmp === 0) {
|
|
1974
|
+
this.#output.push(change);
|
|
1975
|
+
return;
|
|
1976
|
+
}
|
|
1977
|
+
if (newCmp < 0) {
|
|
1978
|
+
if (this.#limit === 1) {
|
|
1979
|
+
replaceBoundAndForwardChange();
|
|
1980
|
+
return;
|
|
1981
|
+
}
|
|
1982
|
+
const beforeBoundNode = must(
|
|
1983
|
+
first(
|
|
1984
|
+
this.#input.fetch({
|
|
1985
|
+
start: {
|
|
1986
|
+
row: takeState.bound,
|
|
1987
|
+
basis: "after"
|
|
1988
|
+
},
|
|
1989
|
+
constraint,
|
|
1990
|
+
reverse: true
|
|
1991
|
+
})
|
|
1992
|
+
)
|
|
1993
|
+
);
|
|
1994
|
+
this.#setTakeState(
|
|
1995
|
+
takeStateKey,
|
|
1996
|
+
takeState.size,
|
|
1997
|
+
beforeBoundNode.row,
|
|
1998
|
+
maxBound
|
|
1999
|
+
);
|
|
2000
|
+
this.#output.push(change);
|
|
2001
|
+
return;
|
|
2002
|
+
}
|
|
2003
|
+
assert(newCmp > 0);
|
|
2004
|
+
const newBoundNode = must(
|
|
2005
|
+
first(
|
|
2006
|
+
this.#input.fetch({
|
|
2007
|
+
start: {
|
|
2008
|
+
row: takeState.bound,
|
|
2009
|
+
basis: "at"
|
|
2010
|
+
},
|
|
2011
|
+
constraint
|
|
2012
|
+
})
|
|
2013
|
+
)
|
|
2014
|
+
);
|
|
2015
|
+
if (compareRows(newBoundNode.row, change.node.row) === 0) {
|
|
2016
|
+
replaceBoundAndForwardChange();
|
|
2017
|
+
return;
|
|
2018
|
+
}
|
|
2019
|
+
this.#setTakeState(
|
|
2020
|
+
takeStateKey,
|
|
2021
|
+
takeState.size,
|
|
2022
|
+
newBoundNode.row,
|
|
2023
|
+
maxBound
|
|
2024
|
+
);
|
|
2025
|
+
this.#output.push({
|
|
2026
|
+
type: "remove",
|
|
2027
|
+
node: change.oldNode
|
|
2028
|
+
});
|
|
2029
|
+
this.#output.push({
|
|
2030
|
+
type: "add",
|
|
2031
|
+
node: newBoundNode
|
|
2032
|
+
});
|
|
2033
|
+
return;
|
|
2034
|
+
}
|
|
2035
|
+
if (oldCmp > 0) {
|
|
2036
|
+
assert(newCmp !== 0, "Invalid state. Row has duplicate primary key");
|
|
2037
|
+
if (newCmp > 0) {
|
|
2038
|
+
return;
|
|
2039
|
+
}
|
|
2040
|
+
assert(newCmp < 0);
|
|
2041
|
+
const [oldBoundNode, newBoundNode] = take(
|
|
2042
|
+
this.#input.fetch({
|
|
2043
|
+
start: {
|
|
2044
|
+
row: takeState.bound,
|
|
2045
|
+
basis: "at"
|
|
2046
|
+
},
|
|
2047
|
+
constraint,
|
|
2048
|
+
reverse: true
|
|
2049
|
+
}),
|
|
2050
|
+
2
|
|
2051
|
+
);
|
|
2052
|
+
this.#setTakeState(
|
|
2053
|
+
takeStateKey,
|
|
2054
|
+
takeState.size,
|
|
2055
|
+
newBoundNode.row,
|
|
2056
|
+
maxBound
|
|
2057
|
+
);
|
|
2058
|
+
this.#output.push({
|
|
2059
|
+
type: "remove",
|
|
2060
|
+
node: oldBoundNode
|
|
2061
|
+
});
|
|
2062
|
+
this.#output.push({
|
|
2063
|
+
type: "add",
|
|
2064
|
+
node: change.node
|
|
2065
|
+
});
|
|
2066
|
+
return;
|
|
2067
|
+
}
|
|
2068
|
+
if (oldCmp < 0) {
|
|
2069
|
+
assert(newCmp !== 0, "Invalid state. Row has duplicate primary key");
|
|
2070
|
+
if (newCmp < 0) {
|
|
2071
|
+
this.#output.push(change);
|
|
2072
|
+
return;
|
|
2073
|
+
}
|
|
2074
|
+
assert(newCmp > 0);
|
|
2075
|
+
const afterBoundNode = must(
|
|
2076
|
+
first(
|
|
2077
|
+
this.#input.fetch({
|
|
2078
|
+
start: {
|
|
2079
|
+
row: takeState.bound,
|
|
2080
|
+
basis: "after"
|
|
2081
|
+
},
|
|
2082
|
+
constraint
|
|
2083
|
+
})
|
|
2084
|
+
)
|
|
2085
|
+
);
|
|
2086
|
+
if (compareRows(afterBoundNode.row, change.node.row) === 0) {
|
|
2087
|
+
replaceBoundAndForwardChange();
|
|
2088
|
+
return;
|
|
2089
|
+
}
|
|
2090
|
+
this.#setTakeState(
|
|
2091
|
+
takeStateKey,
|
|
2092
|
+
takeState.size,
|
|
2093
|
+
afterBoundNode.row,
|
|
2094
|
+
maxBound
|
|
2095
|
+
);
|
|
2096
|
+
this.#output.push({
|
|
2097
|
+
type: "remove",
|
|
2098
|
+
node: change.oldNode
|
|
2099
|
+
});
|
|
2100
|
+
this.#output.push({
|
|
2101
|
+
type: "add",
|
|
2102
|
+
node: afterBoundNode
|
|
2103
|
+
});
|
|
2104
|
+
return;
|
|
2105
|
+
}
|
|
2106
|
+
unreachable();
|
|
2107
|
+
}
|
|
2108
|
+
#setTakeState(takeStateKey, size, bound, maxBound) {
|
|
2109
|
+
this.#storage.set(takeStateKey, {
|
|
2110
|
+
size,
|
|
2111
|
+
bound
|
|
2112
|
+
});
|
|
2113
|
+
if (bound !== void 0 && (maxBound === void 0 || this.getSchema().compareRows(bound, maxBound) > 0)) {
|
|
2114
|
+
this.#storage.set(MAX_BOUND_KEY, bound);
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
destroy() {
|
|
2118
|
+
this.#input.destroy();
|
|
2119
|
+
}
|
|
2120
|
+
};
|
|
2121
|
+
function getTakeStateKey(partitionKey, rowOrConstraint) {
|
|
2122
|
+
const partitionValues = [];
|
|
2123
|
+
if (partitionKey && rowOrConstraint) {
|
|
2124
|
+
for (const key of partitionKey) {
|
|
2125
|
+
partitionValues.push(rowOrConstraint[key]);
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
return JSON.stringify(["take", ...partitionValues]);
|
|
2129
|
+
}
|
|
2130
|
+
function constraintMatchesPartitionKey(constraint, partitionKey) {
|
|
2131
|
+
if (constraint === void 0 || partitionKey === void 0) {
|
|
2132
|
+
return constraint === partitionKey;
|
|
2133
|
+
}
|
|
2134
|
+
if (partitionKey.length !== Object.keys(constraint).length) {
|
|
2135
|
+
return false;
|
|
2136
|
+
}
|
|
2137
|
+
for (const key of partitionKey) {
|
|
2138
|
+
if (!hasOwn(constraint, key)) {
|
|
2139
|
+
return false;
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
return true;
|
|
2143
|
+
}
|
|
2144
|
+
function makePartitionKeyComparator(partitionKey) {
|
|
2145
|
+
return (a, b) => {
|
|
2146
|
+
for (const key of partitionKey) {
|
|
2147
|
+
const cmp2 = compareValues(a[key], b[key]);
|
|
2148
|
+
if (cmp2 !== 0) {
|
|
2149
|
+
return cmp2;
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
return 0;
|
|
2153
|
+
};
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
// ../zql/src/builder/like.ts
|
|
2157
|
+
function getLikePredicate(pattern, flags) {
|
|
2158
|
+
const op = getLikeOp(String(pattern), flags);
|
|
2159
|
+
return (lhs) => {
|
|
2160
|
+
assertString(lhs);
|
|
2161
|
+
return op(String(lhs));
|
|
2162
|
+
};
|
|
2163
|
+
}
|
|
2164
|
+
function getLikeOp(pattern, flags) {
|
|
2165
|
+
if (!/_|%|\\/.test(pattern)) {
|
|
2166
|
+
if (flags === "i") {
|
|
2167
|
+
const rhsLower = pattern.toLowerCase();
|
|
2168
|
+
return (lhs) => lhs.toLowerCase() === rhsLower;
|
|
2169
|
+
}
|
|
2170
|
+
return (lhs) => lhs === pattern;
|
|
2171
|
+
}
|
|
2172
|
+
const re = patternToRegExp(pattern, flags);
|
|
2173
|
+
return (lhs) => re.test(lhs);
|
|
2174
|
+
}
|
|
2175
|
+
var specialCharsRe = /[$()*+.?[\]\\^{|}]/;
|
|
2176
|
+
function patternToRegExp(source, flags = "") {
|
|
2177
|
+
let pattern = "^";
|
|
2178
|
+
for (let i = 0; i < source.length; i++) {
|
|
2179
|
+
let c = source[i];
|
|
2180
|
+
switch (c) {
|
|
2181
|
+
case "%":
|
|
2182
|
+
pattern += ".*";
|
|
2183
|
+
break;
|
|
2184
|
+
case "_":
|
|
2185
|
+
pattern += ".";
|
|
2186
|
+
break;
|
|
2187
|
+
// @ts-expect-error fallthrough
|
|
2188
|
+
case "\\":
|
|
2189
|
+
if (i === source.length - 1) {
|
|
2190
|
+
throw new Error("LIKE pattern must not end with escape character");
|
|
2191
|
+
}
|
|
2192
|
+
i++;
|
|
2193
|
+
c = source[i];
|
|
2194
|
+
// fall through
|
|
2195
|
+
default:
|
|
2196
|
+
if (specialCharsRe.test(c)) {
|
|
2197
|
+
pattern += "\\";
|
|
2198
|
+
}
|
|
2199
|
+
pattern += c;
|
|
2200
|
+
break;
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
return new RegExp(pattern + "$", flags + "m");
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2206
|
+
// ../zql/src/builder/filter.ts
|
|
2207
|
+
function createPredicate(condition) {
|
|
2208
|
+
if (condition.type !== "simple") {
|
|
2209
|
+
const predicates = condition.conditions.map((c) => createPredicate(c));
|
|
2210
|
+
return condition.type === "and" ? (row) => {
|
|
2211
|
+
for (const predicate of predicates) {
|
|
2212
|
+
if (!predicate(row)) {
|
|
2213
|
+
return false;
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
return true;
|
|
2217
|
+
} : (row) => {
|
|
2218
|
+
for (const predicate of predicates) {
|
|
2219
|
+
if (predicate(row)) {
|
|
2220
|
+
return true;
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
return false;
|
|
2224
|
+
};
|
|
2225
|
+
}
|
|
2226
|
+
const { left } = condition;
|
|
2227
|
+
const { right } = condition;
|
|
2228
|
+
assert(
|
|
2229
|
+
right.type !== "static",
|
|
2230
|
+
"static values should be resolved before creating predicates"
|
|
2231
|
+
);
|
|
2232
|
+
assert(
|
|
2233
|
+
left.type !== "static",
|
|
2234
|
+
"static values should be resolved before creating predicates"
|
|
2235
|
+
);
|
|
2236
|
+
switch (condition.op) {
|
|
2237
|
+
case "IS":
|
|
2238
|
+
case "IS NOT": {
|
|
2239
|
+
const impl2 = createIsPredicate(right.value, condition.op);
|
|
2240
|
+
if (left.type === "literal") {
|
|
2241
|
+
const result = impl2(left.value);
|
|
2242
|
+
return () => result;
|
|
2243
|
+
}
|
|
2244
|
+
return (row) => impl2(row[left.name]);
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
if (right.value === null || right.value === void 0) {
|
|
2248
|
+
return (_row) => false;
|
|
2249
|
+
}
|
|
2250
|
+
const impl = createPredicateImpl(right.value, condition.op);
|
|
2251
|
+
if (left.type === "literal") {
|
|
2252
|
+
if (left.value === null || left.value === void 0) {
|
|
2253
|
+
return (_row) => false;
|
|
2254
|
+
}
|
|
2255
|
+
const result = impl(left.value);
|
|
2256
|
+
return () => result;
|
|
2257
|
+
}
|
|
2258
|
+
return (row) => {
|
|
2259
|
+
const lhs = row[left.name];
|
|
2260
|
+
if (lhs === null || lhs === void 0) {
|
|
2261
|
+
return false;
|
|
2262
|
+
}
|
|
2263
|
+
return impl(lhs);
|
|
2264
|
+
};
|
|
2265
|
+
}
|
|
2266
|
+
function createIsPredicate(rhs, operator) {
|
|
2267
|
+
switch (operator) {
|
|
2268
|
+
case "IS":
|
|
2269
|
+
return (lhs) => lhs === rhs;
|
|
2270
|
+
case "IS NOT":
|
|
2271
|
+
return (lhs) => lhs !== rhs;
|
|
2272
|
+
}
|
|
2273
|
+
}
|
|
2274
|
+
function createPredicateImpl(rhs, operator) {
|
|
2275
|
+
switch (operator) {
|
|
2276
|
+
case "=":
|
|
2277
|
+
return (lhs) => lhs === rhs;
|
|
2278
|
+
case "!=":
|
|
2279
|
+
return (lhs) => lhs !== rhs;
|
|
2280
|
+
case "<":
|
|
2281
|
+
return (lhs) => lhs < rhs;
|
|
2282
|
+
case "<=":
|
|
2283
|
+
return (lhs) => lhs <= rhs;
|
|
2284
|
+
case ">":
|
|
2285
|
+
return (lhs) => lhs > rhs;
|
|
2286
|
+
case ">=":
|
|
2287
|
+
return (lhs) => lhs >= rhs;
|
|
2288
|
+
case "LIKE":
|
|
2289
|
+
return getLikePredicate(rhs, "");
|
|
2290
|
+
case "NOT LIKE":
|
|
2291
|
+
return not(getLikePredicate(rhs, ""));
|
|
2292
|
+
case "ILIKE":
|
|
2293
|
+
return getLikePredicate(rhs, "i");
|
|
2294
|
+
case "NOT ILIKE":
|
|
2295
|
+
return not(getLikePredicate(rhs, "i"));
|
|
2296
|
+
case "IN": {
|
|
2297
|
+
assert(Array.isArray(rhs));
|
|
2298
|
+
const set = new Set(rhs);
|
|
2299
|
+
return (lhs) => set.has(lhs);
|
|
2300
|
+
}
|
|
2301
|
+
case "NOT IN": {
|
|
2302
|
+
assert(Array.isArray(rhs));
|
|
2303
|
+
const set = new Set(rhs);
|
|
2304
|
+
return (lhs) => !set.has(lhs);
|
|
2305
|
+
}
|
|
2306
|
+
default:
|
|
2307
|
+
operator;
|
|
2308
|
+
throw new Error(`Unexpected operator: ${operator}`);
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
function not(f) {
|
|
2312
|
+
return (lhs) => !f(lhs);
|
|
2313
|
+
}
|
|
2314
|
+
function transformFilters(filters) {
|
|
2315
|
+
if (!filters) {
|
|
2316
|
+
return { filters: void 0, conditionsRemoved: false };
|
|
2317
|
+
}
|
|
2318
|
+
switch (filters.type) {
|
|
2319
|
+
case "simple":
|
|
2320
|
+
return { filters, conditionsRemoved: false };
|
|
2321
|
+
case "correlatedSubquery":
|
|
2322
|
+
return { filters: void 0, conditionsRemoved: true };
|
|
2323
|
+
case "and": {
|
|
2324
|
+
const transformedConditions = [];
|
|
2325
|
+
for (const cond of filters.conditions) {
|
|
2326
|
+
assert(cond.type === "simple" || cond.type === "correlatedSubquery");
|
|
2327
|
+
if (cond.type === "simple") {
|
|
2328
|
+
transformedConditions.push(cond);
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
const conditionsRemoved = transformedConditions.length !== filters.conditions.length;
|
|
2332
|
+
if (transformedConditions.length === 0) {
|
|
2333
|
+
return { filters: void 0, conditionsRemoved };
|
|
2334
|
+
}
|
|
2335
|
+
if (transformedConditions.length === 1) {
|
|
2336
|
+
return {
|
|
2337
|
+
filters: transformedConditions[0],
|
|
2338
|
+
conditionsRemoved
|
|
2339
|
+
};
|
|
2340
|
+
}
|
|
2341
|
+
return {
|
|
2342
|
+
filters: {
|
|
2343
|
+
type: "and",
|
|
2344
|
+
conditions: transformedConditions
|
|
2345
|
+
},
|
|
2346
|
+
conditionsRemoved
|
|
2347
|
+
};
|
|
2348
|
+
}
|
|
2349
|
+
case "or": {
|
|
2350
|
+
const transformedConditions = [];
|
|
2351
|
+
let conditionsRemoved = false;
|
|
2352
|
+
for (const cond of filters.conditions) {
|
|
2353
|
+
assert(cond.type !== "or");
|
|
2354
|
+
const transformed = transformFilters(cond);
|
|
2355
|
+
if (transformed.filters === void 0) {
|
|
2356
|
+
return { filters: void 0, conditionsRemoved: true };
|
|
2357
|
+
}
|
|
2358
|
+
conditionsRemoved = conditionsRemoved || transformed.conditionsRemoved;
|
|
2359
|
+
transformedConditions.push(transformed.filters);
|
|
2360
|
+
}
|
|
2361
|
+
return {
|
|
2362
|
+
filters: { type: "or", conditions: transformedConditions },
|
|
2363
|
+
conditionsRemoved
|
|
2364
|
+
};
|
|
2365
|
+
}
|
|
2366
|
+
default:
|
|
2367
|
+
unreachable(filters);
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
|
|
2371
|
+
// ../zql/src/builder/builder.ts
|
|
2372
|
+
function buildPipeline(ast, delegate) {
|
|
2373
|
+
return buildPipelineInternal(ast, delegate);
|
|
2374
|
+
}
|
|
2375
|
+
function buildPipelineInternal(ast, delegate, partitionKey) {
|
|
2376
|
+
const source = delegate.getSource(ast.table);
|
|
2377
|
+
if (!source) {
|
|
2378
|
+
throw new Error(`Source not found: ${ast.table}`);
|
|
2379
|
+
}
|
|
2380
|
+
const conn = source.connect(must(ast.orderBy), ast.where);
|
|
2381
|
+
let end = conn;
|
|
2382
|
+
const { fullyAppliedFilters } = conn;
|
|
2383
|
+
ast = uniquifyCorrelatedSubqueryConditionAliases(ast);
|
|
2384
|
+
if (ast.start) {
|
|
2385
|
+
end = new Skip(end, ast.start);
|
|
2386
|
+
}
|
|
2387
|
+
for (const csq of gatherCorrelatedSubqueryQueriesFromCondition(ast.where)) {
|
|
2388
|
+
end = applyCorrelatedSubQuery(csq, delegate, end);
|
|
2389
|
+
}
|
|
2390
|
+
if (ast.where && !fullyAppliedFilters) {
|
|
2391
|
+
end = applyWhere(end, ast.where, delegate);
|
|
2392
|
+
}
|
|
2393
|
+
if (ast.limit) {
|
|
2394
|
+
end = new Take(end, delegate.createStorage(), ast.limit, partitionKey);
|
|
2395
|
+
}
|
|
2396
|
+
if (ast.related) {
|
|
2397
|
+
for (const csq of ast.related) {
|
|
2398
|
+
end = applyCorrelatedSubQuery(csq, delegate, end);
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
return end;
|
|
2402
|
+
}
|
|
2403
|
+
function applyWhere(input, condition, delegate) {
|
|
2404
|
+
switch (condition.type) {
|
|
2405
|
+
case "and":
|
|
2406
|
+
return applyAnd(input, condition, delegate);
|
|
2407
|
+
case "or":
|
|
2408
|
+
return applyOr(input, condition, delegate);
|
|
2409
|
+
case "correlatedSubquery":
|
|
2410
|
+
return applyCorrelatedSubqueryCondition(input, condition, delegate);
|
|
2411
|
+
case "simple":
|
|
2412
|
+
return applySimpleCondition(input, condition);
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
function applyAnd(input, condition, delegate) {
|
|
2416
|
+
for (const subCondition of condition.conditions) {
|
|
2417
|
+
input = applyWhere(input, subCondition, delegate);
|
|
2418
|
+
}
|
|
2419
|
+
return input;
|
|
2420
|
+
}
|
|
2421
|
+
function applyOr(input, condition, delegate) {
|
|
2422
|
+
const [subqueryConditions, otherConditions] = groupSubqueryConditions(condition);
|
|
2423
|
+
if (subqueryConditions.length === 0) {
|
|
2424
|
+
return new Filter(
|
|
2425
|
+
input,
|
|
2426
|
+
createPredicate({
|
|
2427
|
+
type: "or",
|
|
2428
|
+
conditions: otherConditions
|
|
2429
|
+
})
|
|
2430
|
+
);
|
|
2431
|
+
}
|
|
2432
|
+
const fanOut = new FanOut(input);
|
|
2433
|
+
const branches = subqueryConditions.map(
|
|
2434
|
+
(subCondition) => applyWhere(fanOut, subCondition, delegate)
|
|
2435
|
+
);
|
|
2436
|
+
if (otherConditions.length > 0) {
|
|
2437
|
+
branches.push(
|
|
2438
|
+
new Filter(
|
|
2439
|
+
fanOut,
|
|
2440
|
+
createPredicate({
|
|
2441
|
+
type: "or",
|
|
2442
|
+
conditions: otherConditions
|
|
2443
|
+
})
|
|
2444
|
+
)
|
|
2445
|
+
);
|
|
2446
|
+
}
|
|
2447
|
+
return new FanIn(fanOut, branches);
|
|
2448
|
+
}
|
|
2449
|
+
function groupSubqueryConditions(condition) {
|
|
2450
|
+
const partitioned = [[], []];
|
|
2451
|
+
for (const subCondition of condition.conditions) {
|
|
2452
|
+
if (isNotAndDoesNotContainSubquery(subCondition)) {
|
|
2453
|
+
partitioned[1].push(subCondition);
|
|
2454
|
+
} else {
|
|
2455
|
+
partitioned[0].push(subCondition);
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
return partitioned;
|
|
2459
|
+
}
|
|
2460
|
+
function isNotAndDoesNotContainSubquery(condition) {
|
|
2461
|
+
if (condition.type === "correlatedSubquery") {
|
|
2462
|
+
return false;
|
|
2463
|
+
}
|
|
2464
|
+
if (condition.type === "and") {
|
|
2465
|
+
return condition.conditions.every(isNotAndDoesNotContainSubquery);
|
|
2466
|
+
}
|
|
2467
|
+
assert(condition.type !== "or", "where conditions are expected to be in DNF");
|
|
2468
|
+
return true;
|
|
2469
|
+
}
|
|
2470
|
+
function applySimpleCondition(input, condition) {
|
|
2471
|
+
return new Filter(input, createPredicate(condition));
|
|
2472
|
+
}
|
|
2473
|
+
function applyCorrelatedSubQuery(sq, delegate, end) {
|
|
2474
|
+
assert(sq.subquery.alias, "Subquery must have an alias");
|
|
2475
|
+
const child = buildPipelineInternal(
|
|
2476
|
+
sq.subquery,
|
|
2477
|
+
delegate,
|
|
2478
|
+
sq.correlation.childField
|
|
2479
|
+
);
|
|
2480
|
+
end = new Join({
|
|
2481
|
+
parent: end,
|
|
2482
|
+
child,
|
|
2483
|
+
storage: delegate.createStorage(),
|
|
2484
|
+
parentKey: sq.correlation.parentField,
|
|
2485
|
+
childKey: sq.correlation.childField,
|
|
2486
|
+
relationshipName: sq.subquery.alias,
|
|
2487
|
+
hidden: sq.hidden ?? false,
|
|
2488
|
+
system: sq.system ?? "client"
|
|
2489
|
+
});
|
|
2490
|
+
return end;
|
|
2491
|
+
}
|
|
2492
|
+
function applyCorrelatedSubqueryCondition(input, condition, delegate) {
|
|
2493
|
+
assert(condition.op === "EXISTS" || condition.op === "NOT EXISTS");
|
|
2494
|
+
return new Exists(
|
|
2495
|
+
input,
|
|
2496
|
+
delegate.createStorage(),
|
|
2497
|
+
must(condition.related.subquery.alias),
|
|
2498
|
+
condition.related.correlation.parentField,
|
|
2499
|
+
condition.op
|
|
2500
|
+
);
|
|
2501
|
+
}
|
|
2502
|
+
function gatherCorrelatedSubqueryQueriesFromCondition(condition) {
|
|
2503
|
+
const csqs = [];
|
|
2504
|
+
const gather = (condition2) => {
|
|
2505
|
+
if (condition2.type === "correlatedSubquery") {
|
|
2506
|
+
assert(condition2.op === "EXISTS" || condition2.op === "NOT EXISTS");
|
|
2507
|
+
csqs.push({
|
|
2508
|
+
...condition2.related,
|
|
2509
|
+
subquery: {
|
|
2510
|
+
...condition2.related.subquery,
|
|
2511
|
+
limit: condition2.related.system === "permissions" ? PERMISSIONS_EXISTS_LIMIT : EXISTS_LIMIT
|
|
2512
|
+
}
|
|
2513
|
+
});
|
|
2514
|
+
return;
|
|
2515
|
+
}
|
|
2516
|
+
if (condition2.type === "and" || condition2.type === "or") {
|
|
2517
|
+
for (const c of condition2.conditions) {
|
|
2518
|
+
gather(c);
|
|
2519
|
+
}
|
|
2520
|
+
return;
|
|
2521
|
+
}
|
|
2522
|
+
};
|
|
2523
|
+
if (condition) {
|
|
2524
|
+
gather(condition);
|
|
2525
|
+
}
|
|
2526
|
+
return csqs;
|
|
2527
|
+
}
|
|
2528
|
+
var EXISTS_LIMIT = 3;
|
|
2529
|
+
var PERMISSIONS_EXISTS_LIMIT = 1;
|
|
2530
|
+
function assertOrderingIncludesPK(ordering, pk) {
|
|
2531
|
+
const orderingFields = ordering.map(([field]) => field);
|
|
2532
|
+
const missingFields = pk.filter((pkField) => !orderingFields.includes(pkField));
|
|
2533
|
+
if (missingFields.length > 0) {
|
|
2534
|
+
throw new Error(
|
|
2535
|
+
`Ordering must include all primary key fields. Missing: ${missingFields.join(
|
|
2536
|
+
", "
|
|
2537
|
+
)}. ZQL automatically appends primary key fields to the ordering if they are missing
|
|
2538
|
+
so a common cause of this error is a casing mismatch between Postgres and ZQL.
|
|
2539
|
+
E.g., "userid" vs "userID".
|
|
2540
|
+
You may want to add double-quotes around your Postgres column names to prevent Postgres from lower-casing them:
|
|
2541
|
+
https://www.postgresql.org/docs/current/sql-syntax-lexical.htm`
|
|
2542
|
+
);
|
|
2543
|
+
}
|
|
2544
|
+
}
|
|
2545
|
+
function uniquifyCorrelatedSubqueryConditionAliases(ast) {
|
|
2546
|
+
if (!ast.where) {
|
|
2547
|
+
return ast;
|
|
2548
|
+
}
|
|
2549
|
+
const { where } = ast;
|
|
2550
|
+
if (where.type !== "and" && where.type !== "or") {
|
|
2551
|
+
return ast;
|
|
2552
|
+
}
|
|
2553
|
+
let count = 0;
|
|
2554
|
+
const uniquifyCorrelatedSubquery = (csqc) => ({
|
|
2555
|
+
...csqc,
|
|
2556
|
+
related: {
|
|
2557
|
+
...csqc.related,
|
|
2558
|
+
subquery: {
|
|
2559
|
+
...csqc.related.subquery,
|
|
2560
|
+
alias: (csqc.related.subquery.alias ?? "") + "_" + count++
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
});
|
|
2564
|
+
const uniquifyAnd = (and2) => {
|
|
2565
|
+
const conds2 = [];
|
|
2566
|
+
for (const cond of and2.conditions) {
|
|
2567
|
+
if (cond.type === "correlatedSubquery") {
|
|
2568
|
+
conds2.push(uniquifyCorrelatedSubquery(cond));
|
|
2569
|
+
} else {
|
|
2570
|
+
conds2.push(cond);
|
|
2571
|
+
}
|
|
2572
|
+
}
|
|
2573
|
+
return {
|
|
2574
|
+
...and2,
|
|
2575
|
+
conditions: conds2
|
|
2576
|
+
};
|
|
2577
|
+
};
|
|
2578
|
+
if (where.type === "and") {
|
|
2579
|
+
return {
|
|
2580
|
+
...ast,
|
|
2581
|
+
where: uniquifyAnd(where)
|
|
2582
|
+
};
|
|
2583
|
+
}
|
|
2584
|
+
const conds = [];
|
|
2585
|
+
for (const cond of where.conditions) {
|
|
2586
|
+
if (cond.type === "simple") {
|
|
2587
|
+
conds.push(cond);
|
|
2588
|
+
} else if (cond.type === "correlatedSubquery") {
|
|
2589
|
+
conds.push(uniquifyCorrelatedSubquery(cond));
|
|
2590
|
+
} else if (cond.type === "and") {
|
|
2591
|
+
conds.push(uniquifyAnd(cond));
|
|
2592
|
+
}
|
|
2593
|
+
}
|
|
2594
|
+
return {
|
|
2595
|
+
...ast,
|
|
2596
|
+
where: {
|
|
2597
|
+
...where,
|
|
2598
|
+
conditions: conds
|
|
2599
|
+
}
|
|
2600
|
+
};
|
|
2601
|
+
}
|
|
2602
|
+
|
|
2603
|
+
// ../zql/src/ivm/array-view.ts
|
|
2604
|
+
var ArrayView = class {
|
|
2605
|
+
#input;
|
|
2606
|
+
#listeners = /* @__PURE__ */ new Set();
|
|
2607
|
+
#schema;
|
|
2608
|
+
#format;
|
|
2609
|
+
// Synthetic "root" entry that has a single "" relationship, so that we can
|
|
2610
|
+
// treat all changes, including the root change, generically.
|
|
2611
|
+
#root;
|
|
2612
|
+
onDestroy;
|
|
2613
|
+
#dirty = false;
|
|
2614
|
+
#complete = false;
|
|
2615
|
+
constructor(input, format = { singular: false, relationships: {} }, queryComplete = true) {
|
|
2616
|
+
this.#input = input;
|
|
2617
|
+
this.#schema = input.getSchema();
|
|
2618
|
+
this.#format = format;
|
|
2619
|
+
this.#root = { "": format.singular ? void 0 : [] };
|
|
2620
|
+
input.setOutput(this);
|
|
2621
|
+
if (queryComplete === true) {
|
|
2622
|
+
this.#complete = true;
|
|
2623
|
+
} else {
|
|
2624
|
+
void queryComplete.then(() => {
|
|
2625
|
+
this.#complete = true;
|
|
2626
|
+
this.#fireListeners();
|
|
2627
|
+
});
|
|
2628
|
+
}
|
|
2629
|
+
this.#hydrate();
|
|
2630
|
+
}
|
|
2631
|
+
get data() {
|
|
2632
|
+
return this.#root[""];
|
|
2633
|
+
}
|
|
2634
|
+
addListener(listener) {
|
|
2635
|
+
assert(!this.#listeners.has(listener), "Listener already registered");
|
|
2636
|
+
this.#listeners.add(listener);
|
|
2637
|
+
this.#fireListener(listener);
|
|
2638
|
+
return () => {
|
|
2639
|
+
this.#listeners.delete(listener);
|
|
2640
|
+
};
|
|
2641
|
+
}
|
|
2642
|
+
#fireListeners() {
|
|
2643
|
+
for (const listener of this.#listeners) {
|
|
2644
|
+
this.#fireListener(listener);
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
#fireListener(listener) {
|
|
2648
|
+
listener(
|
|
2649
|
+
this.data,
|
|
2650
|
+
this.#complete ? "complete" : "unknown"
|
|
2651
|
+
);
|
|
2652
|
+
}
|
|
2653
|
+
destroy() {
|
|
2654
|
+
this.onDestroy?.();
|
|
2655
|
+
}
|
|
2656
|
+
#hydrate() {
|
|
2657
|
+
this.#dirty = true;
|
|
2658
|
+
for (const node of this.#input.fetch({})) {
|
|
2659
|
+
applyChange(
|
|
2660
|
+
this.#root,
|
|
2661
|
+
{ type: "add", node },
|
|
2662
|
+
this.#schema,
|
|
2663
|
+
"",
|
|
2664
|
+
this.#format
|
|
2665
|
+
);
|
|
2666
|
+
}
|
|
2667
|
+
this.flush();
|
|
2668
|
+
}
|
|
2669
|
+
push(change) {
|
|
2670
|
+
this.#dirty = true;
|
|
2671
|
+
applyChange(this.#root, change, this.#schema, "", this.#format);
|
|
2672
|
+
}
|
|
2673
|
+
flush() {
|
|
2674
|
+
if (!this.#dirty) {
|
|
2675
|
+
return;
|
|
2676
|
+
}
|
|
2677
|
+
this.#dirty = false;
|
|
2678
|
+
this.#fireListeners();
|
|
2679
|
+
}
|
|
2680
|
+
};
|
|
2681
|
+
|
|
2682
|
+
// ../zql/src/query/expression.ts
|
|
2683
|
+
var ExpressionBuilder = class {
|
|
2684
|
+
#exists;
|
|
2685
|
+
constructor(exists) {
|
|
2686
|
+
this.#exists = exists;
|
|
2687
|
+
this.exists = this.exists.bind(this);
|
|
2688
|
+
}
|
|
2689
|
+
get eb() {
|
|
2690
|
+
return this;
|
|
2691
|
+
}
|
|
2692
|
+
cmp(field, opOrValue, value) {
|
|
2693
|
+
return cmp(field, opOrValue, value);
|
|
2694
|
+
}
|
|
2695
|
+
cmpLit(left, op, right) {
|
|
2696
|
+
return {
|
|
2697
|
+
type: "simple",
|
|
2698
|
+
left: isParameterReference(left) ? left[toStaticParam]() : { type: "literal", value: left },
|
|
2699
|
+
right: isParameterReference(right) ? right[toStaticParam]() : { type: "literal", value: right },
|
|
2700
|
+
op
|
|
2701
|
+
};
|
|
2702
|
+
}
|
|
2703
|
+
and = and;
|
|
2704
|
+
or = or;
|
|
2705
|
+
not = not2;
|
|
2706
|
+
exists(relationship, cb) {
|
|
2707
|
+
return this.#exists(relationship, cb);
|
|
2708
|
+
}
|
|
2709
|
+
};
|
|
2710
|
+
function and(...conditions) {
|
|
2711
|
+
const expressions = filterTrue(filterUndefined(conditions));
|
|
2712
|
+
if (expressions.length === 1) {
|
|
2713
|
+
return expressions[0];
|
|
2714
|
+
}
|
|
2715
|
+
if (expressions.some(isAlwaysFalse)) {
|
|
2716
|
+
return FALSE;
|
|
2717
|
+
}
|
|
2718
|
+
return { type: "and", conditions: expressions };
|
|
2719
|
+
}
|
|
2720
|
+
function or(...conditions) {
|
|
2721
|
+
const expressions = filterFalse(filterUndefined(conditions));
|
|
2722
|
+
if (expressions.length === 1) {
|
|
2723
|
+
return expressions[0];
|
|
2724
|
+
}
|
|
2725
|
+
if (expressions.some(isAlwaysTrue)) {
|
|
2726
|
+
return TRUE;
|
|
2727
|
+
}
|
|
2728
|
+
return { type: "or", conditions: expressions };
|
|
2729
|
+
}
|
|
2730
|
+
function not2(expression) {
|
|
2731
|
+
switch (expression.type) {
|
|
2732
|
+
case "and":
|
|
2733
|
+
return {
|
|
2734
|
+
type: "or",
|
|
2735
|
+
conditions: expression.conditions.map(not2)
|
|
2736
|
+
};
|
|
2737
|
+
case "or":
|
|
2738
|
+
return {
|
|
2739
|
+
type: "and",
|
|
2740
|
+
conditions: expression.conditions.map(not2)
|
|
2741
|
+
};
|
|
2742
|
+
case "correlatedSubquery":
|
|
2743
|
+
return {
|
|
2744
|
+
type: "correlatedSubquery",
|
|
2745
|
+
related: expression.related,
|
|
2746
|
+
op: negateOperator(expression.op)
|
|
2747
|
+
};
|
|
2748
|
+
case "simple":
|
|
2749
|
+
return {
|
|
2750
|
+
type: "simple",
|
|
2751
|
+
op: negateOperator(expression.op),
|
|
2752
|
+
left: expression.left,
|
|
2753
|
+
right: expression.right
|
|
2754
|
+
};
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
function cmp(field, opOrValue, value) {
|
|
2758
|
+
let op;
|
|
2759
|
+
if (value === void 0) {
|
|
2760
|
+
value = opOrValue;
|
|
2761
|
+
op = "=";
|
|
2762
|
+
} else {
|
|
2763
|
+
op = opOrValue;
|
|
2764
|
+
}
|
|
2765
|
+
return {
|
|
2766
|
+
type: "simple",
|
|
2767
|
+
left: { type: "column", name: field },
|
|
2768
|
+
right: isParameterReference(value) ? value[toStaticParam]() : { type: "literal", value },
|
|
2769
|
+
op
|
|
2770
|
+
};
|
|
2771
|
+
}
|
|
2772
|
+
function isParameterReference(value) {
|
|
2773
|
+
return value !== null && typeof value === "object" && value[toStaticParam];
|
|
2774
|
+
}
|
|
2775
|
+
var TRUE = {
|
|
2776
|
+
type: "and",
|
|
2777
|
+
conditions: []
|
|
2778
|
+
};
|
|
2779
|
+
var FALSE = {
|
|
2780
|
+
type: "or",
|
|
2781
|
+
conditions: []
|
|
2782
|
+
};
|
|
2783
|
+
function isAlwaysTrue(condition) {
|
|
2784
|
+
return condition.type === "and" && condition.conditions.length === 0;
|
|
2785
|
+
}
|
|
2786
|
+
function isAlwaysFalse(condition) {
|
|
2787
|
+
return condition.type === "or" && condition.conditions.length === 0;
|
|
2788
|
+
}
|
|
2789
|
+
function flatten(type, conditions) {
|
|
2790
|
+
const flattened2 = [];
|
|
2791
|
+
for (const c of conditions) {
|
|
2792
|
+
if (c.type === type) {
|
|
2793
|
+
flattened2.push(...c.conditions);
|
|
2794
|
+
} else {
|
|
2795
|
+
flattened2.push(c);
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
return flattened2;
|
|
2799
|
+
}
|
|
2800
|
+
var negateSimpleOperatorMap = {
|
|
2801
|
+
["="]: "!=",
|
|
2802
|
+
["!="]: "=",
|
|
2803
|
+
["<"]: ">=",
|
|
2804
|
+
[">"]: "<=",
|
|
2805
|
+
[">="]: "<",
|
|
2806
|
+
["<="]: ">",
|
|
2807
|
+
["IN"]: "NOT IN",
|
|
2808
|
+
["NOT IN"]: "IN",
|
|
2809
|
+
["LIKE"]: "NOT LIKE",
|
|
2810
|
+
["NOT LIKE"]: "LIKE",
|
|
2811
|
+
["ILIKE"]: "NOT ILIKE",
|
|
2812
|
+
["NOT ILIKE"]: "ILIKE",
|
|
2813
|
+
["IS"]: "IS NOT",
|
|
2814
|
+
["IS NOT"]: "IS"
|
|
2815
|
+
};
|
|
2816
|
+
var negateOperatorMap = {
|
|
2817
|
+
...negateSimpleOperatorMap,
|
|
2818
|
+
["EXISTS"]: "NOT EXISTS",
|
|
2819
|
+
["NOT EXISTS"]: "EXISTS"
|
|
2820
|
+
};
|
|
2821
|
+
function negateOperator(op) {
|
|
2822
|
+
return must(negateOperatorMap[op]);
|
|
2823
|
+
}
|
|
2824
|
+
function filterUndefined(array5) {
|
|
2825
|
+
return array5.filter((e) => e !== void 0);
|
|
2826
|
+
}
|
|
2827
|
+
function filterTrue(conditions) {
|
|
2828
|
+
return conditions.filter((c) => !isAlwaysTrue(c));
|
|
2829
|
+
}
|
|
2830
|
+
function filterFalse(conditions) {
|
|
2831
|
+
return conditions.filter((c) => !isAlwaysFalse(c));
|
|
2832
|
+
}
|
|
2833
|
+
|
|
2834
|
+
// ../zql/src/query/dnf.ts
|
|
2835
|
+
function dnf(condition) {
|
|
2836
|
+
return unwrap(dnfInner(condition));
|
|
2837
|
+
}
|
|
2838
|
+
function dnfInner(condition) {
|
|
2839
|
+
switch (condition.type) {
|
|
2840
|
+
case "simple":
|
|
2841
|
+
case "correlatedSubquery":
|
|
2842
|
+
return { type: "or", conditions: [condition] };
|
|
2843
|
+
case "and":
|
|
2844
|
+
return distributeAnd(condition.conditions.map(dnfInner));
|
|
2845
|
+
case "or":
|
|
2846
|
+
return {
|
|
2847
|
+
type: "or",
|
|
2848
|
+
conditions: flatten(
|
|
2849
|
+
"or",
|
|
2850
|
+
condition.conditions.map(dnfInner).flatMap((c) => c.conditions)
|
|
2851
|
+
)
|
|
2852
|
+
};
|
|
2853
|
+
default:
|
|
2854
|
+
unreachable(condition);
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2857
|
+
function distributeAnd(conditions) {
|
|
2858
|
+
if (conditions.length === 0) {
|
|
2859
|
+
return { type: "or", conditions: [TRUE] };
|
|
2860
|
+
}
|
|
2861
|
+
return conditions.reduce((acc, orCondition) => {
|
|
2862
|
+
const newConditions = [];
|
|
2863
|
+
for (const accCondition of acc.conditions) {
|
|
2864
|
+
for (const orSubCondition of orCondition.conditions) {
|
|
2865
|
+
newConditions.push({
|
|
2866
|
+
type: "and",
|
|
2867
|
+
conditions: [accCondition, orSubCondition]
|
|
2868
|
+
});
|
|
2869
|
+
}
|
|
2870
|
+
}
|
|
2871
|
+
return {
|
|
2872
|
+
type: "or",
|
|
2873
|
+
conditions: flatten("or", newConditions)
|
|
2874
|
+
};
|
|
2875
|
+
});
|
|
2876
|
+
}
|
|
2877
|
+
function unwrap(c) {
|
|
2878
|
+
if (c.type === "simple" || c.type === "correlatedSubquery") {
|
|
2879
|
+
return c;
|
|
2880
|
+
}
|
|
2881
|
+
if (c.conditions.length === 1) {
|
|
2882
|
+
return unwrap(c.conditions[0]);
|
|
2883
|
+
}
|
|
2884
|
+
return { type: c.type, conditions: flatten(c.type, c.conditions.map(unwrap)) };
|
|
2885
|
+
}
|
|
2886
|
+
|
|
2887
|
+
// ../zql/src/query/query-impl.ts
|
|
2888
|
+
var astForTestingSymbol = Symbol();
|
|
2889
|
+
function newQuery(delegate, schema, table) {
|
|
2890
|
+
return new QueryImpl(delegate, schema, table);
|
|
2891
|
+
}
|
|
2892
|
+
function newQueryWithDetails(delegate, schema, tableName, ast, ttl, format) {
|
|
2893
|
+
return new QueryImpl(delegate, schema, tableName, ast, ttl, format);
|
|
2894
|
+
}
|
|
2895
|
+
function staticParam(anchorClass, field) {
|
|
2896
|
+
return {
|
|
2897
|
+
type: "static",
|
|
2898
|
+
anchor: anchorClass,
|
|
2899
|
+
// for backwards compatibility
|
|
2900
|
+
field: field.length === 1 ? field[0] : field
|
|
2901
|
+
};
|
|
2902
|
+
}
|
|
2903
|
+
var SUBQ_PREFIX = "zsubq_";
|
|
2904
|
+
var AbstractQuery = class {
|
|
2905
|
+
#schema;
|
|
2906
|
+
#tableName;
|
|
2907
|
+
#ast;
|
|
2908
|
+
#ttl;
|
|
2909
|
+
#format;
|
|
2910
|
+
#hash = "";
|
|
2911
|
+
constructor(schema, tableName, ast = { table: tableName }, ttl, format) {
|
|
2912
|
+
this.#schema = schema;
|
|
2913
|
+
this.#tableName = tableName;
|
|
2914
|
+
this.#ast = ast;
|
|
2915
|
+
this.#ttl = ttl;
|
|
2916
|
+
this.#format = format ?? { singular: false, relationships: {} };
|
|
2917
|
+
}
|
|
2918
|
+
get format() {
|
|
2919
|
+
return this.#format;
|
|
2920
|
+
}
|
|
2921
|
+
// Not part of Query or QueryInternal interface
|
|
2922
|
+
get [astForTestingSymbol]() {
|
|
2923
|
+
return this.#ast;
|
|
2924
|
+
}
|
|
2925
|
+
hash() {
|
|
2926
|
+
if (!this.#hash) {
|
|
2927
|
+
const ast = this._completeAst();
|
|
2928
|
+
const hash2 = hashOfAST(ast);
|
|
2929
|
+
this.#hash = hash2;
|
|
2930
|
+
}
|
|
2931
|
+
return this.#hash;
|
|
2932
|
+
}
|
|
2933
|
+
one() {
|
|
2934
|
+
return this._newQuery(
|
|
2935
|
+
this.#schema,
|
|
2936
|
+
this.#tableName,
|
|
2937
|
+
{
|
|
2938
|
+
...this.#ast,
|
|
2939
|
+
limit: 1
|
|
2940
|
+
},
|
|
2941
|
+
this.#ttl,
|
|
2942
|
+
{
|
|
2943
|
+
...this.#format,
|
|
2944
|
+
singular: true
|
|
2945
|
+
}
|
|
2946
|
+
);
|
|
2947
|
+
}
|
|
2948
|
+
whereExists(relationship, cb) {
|
|
2949
|
+
return this.where(({ exists }) => exists(relationship, cb));
|
|
2950
|
+
}
|
|
2951
|
+
related(relationship, cb) {
|
|
2952
|
+
if (relationship.startsWith(SUBQ_PREFIX)) {
|
|
2953
|
+
throw new Error(
|
|
2954
|
+
`Relationship names may not start with "${SUBQ_PREFIX}". That is a reserved prefix.`
|
|
2955
|
+
);
|
|
2956
|
+
}
|
|
2957
|
+
cb = cb ?? ((q) => q);
|
|
2958
|
+
const related = this.#schema.relationships[this.#tableName][relationship];
|
|
2959
|
+
assert(related, "Invalid relationship");
|
|
2960
|
+
if (isOneHop(related)) {
|
|
2961
|
+
const { destSchema, destField, sourceField, cardinality } = related[0];
|
|
2962
|
+
const sq = cb(
|
|
2963
|
+
this._newQuery(
|
|
2964
|
+
this.#schema,
|
|
2965
|
+
destSchema,
|
|
2966
|
+
{
|
|
2967
|
+
table: destSchema,
|
|
2968
|
+
alias: relationship
|
|
2969
|
+
},
|
|
2970
|
+
this.#ttl,
|
|
2971
|
+
{
|
|
2972
|
+
relationships: {},
|
|
2973
|
+
singular: cardinality === "one"
|
|
2974
|
+
}
|
|
2975
|
+
)
|
|
2976
|
+
);
|
|
2977
|
+
assert(
|
|
2978
|
+
isCompoundKey(sourceField),
|
|
2979
|
+
"The source of a relationship must specify at last 1 field"
|
|
2980
|
+
);
|
|
2981
|
+
assert(
|
|
2982
|
+
isCompoundKey(destField),
|
|
2983
|
+
"The destination of a relationship must specify at last 1 field"
|
|
2984
|
+
);
|
|
2985
|
+
assert(
|
|
2986
|
+
sourceField.length === destField.length,
|
|
2987
|
+
"The source and destination of a relationship must have the same number of fields"
|
|
2988
|
+
);
|
|
2989
|
+
return this._newQuery(
|
|
2990
|
+
this.#schema,
|
|
2991
|
+
this.#tableName,
|
|
2992
|
+
{
|
|
2993
|
+
...this.#ast,
|
|
2994
|
+
related: [
|
|
2995
|
+
...this.#ast.related ?? [],
|
|
2996
|
+
{
|
|
2997
|
+
system: this._system,
|
|
2998
|
+
correlation: {
|
|
2999
|
+
parentField: sourceField,
|
|
3000
|
+
childField: destField
|
|
3001
|
+
},
|
|
3002
|
+
subquery: addPrimaryKeysToAst(
|
|
3003
|
+
this.#schema.tables[destSchema],
|
|
3004
|
+
sq.#ast
|
|
3005
|
+
)
|
|
3006
|
+
}
|
|
3007
|
+
]
|
|
3008
|
+
},
|
|
3009
|
+
this.#ttl,
|
|
3010
|
+
{
|
|
3011
|
+
...this.#format,
|
|
3012
|
+
relationships: {
|
|
3013
|
+
...this.#format.relationships,
|
|
3014
|
+
[relationship]: sq.#format
|
|
3015
|
+
}
|
|
3016
|
+
}
|
|
3017
|
+
);
|
|
3018
|
+
}
|
|
3019
|
+
if (isTwoHop(related)) {
|
|
3020
|
+
assert(related.length === 2, "Invalid relationship");
|
|
3021
|
+
const [firstRelation, secondRelation] = related;
|
|
3022
|
+
const { destSchema } = secondRelation;
|
|
3023
|
+
const junctionSchema = firstRelation.destSchema;
|
|
3024
|
+
const sq = cb(
|
|
3025
|
+
this._newQuery(
|
|
3026
|
+
this.#schema,
|
|
3027
|
+
destSchema,
|
|
3028
|
+
{
|
|
3029
|
+
table: destSchema,
|
|
3030
|
+
alias: relationship
|
|
3031
|
+
},
|
|
3032
|
+
this.#ttl,
|
|
3033
|
+
{
|
|
3034
|
+
relationships: {},
|
|
3035
|
+
singular: secondRelation.cardinality === "one"
|
|
3036
|
+
}
|
|
3037
|
+
)
|
|
3038
|
+
);
|
|
3039
|
+
assert(isCompoundKey(firstRelation.sourceField), "Invalid relationship");
|
|
3040
|
+
assert(isCompoundKey(firstRelation.destField), "Invalid relationship");
|
|
3041
|
+
assert(isCompoundKey(secondRelation.sourceField), "Invalid relationship");
|
|
3042
|
+
assert(isCompoundKey(secondRelation.destField), "Invalid relationship");
|
|
3043
|
+
return this._newQuery(
|
|
3044
|
+
this.#schema,
|
|
3045
|
+
this.#tableName,
|
|
3046
|
+
{
|
|
3047
|
+
...this.#ast,
|
|
3048
|
+
related: [
|
|
3049
|
+
...this.#ast.related ?? [],
|
|
3050
|
+
{
|
|
3051
|
+
system: this._system,
|
|
3052
|
+
correlation: {
|
|
3053
|
+
parentField: firstRelation.sourceField,
|
|
3054
|
+
childField: firstRelation.destField
|
|
3055
|
+
},
|
|
3056
|
+
hidden: true,
|
|
3057
|
+
subquery: {
|
|
3058
|
+
table: junctionSchema,
|
|
3059
|
+
alias: relationship,
|
|
3060
|
+
orderBy: addPrimaryKeys(
|
|
3061
|
+
this.#schema.tables[junctionSchema],
|
|
3062
|
+
void 0
|
|
3063
|
+
),
|
|
3064
|
+
related: [
|
|
3065
|
+
{
|
|
3066
|
+
system: this._system,
|
|
3067
|
+
correlation: {
|
|
3068
|
+
parentField: secondRelation.sourceField,
|
|
3069
|
+
childField: secondRelation.destField
|
|
3070
|
+
},
|
|
3071
|
+
subquery: addPrimaryKeysToAst(
|
|
3072
|
+
this.#schema.tables[destSchema],
|
|
3073
|
+
sq.#ast
|
|
3074
|
+
)
|
|
3075
|
+
}
|
|
3076
|
+
]
|
|
3077
|
+
}
|
|
3078
|
+
}
|
|
3079
|
+
]
|
|
3080
|
+
},
|
|
3081
|
+
this.#ttl,
|
|
3082
|
+
{
|
|
3083
|
+
...this.#format,
|
|
3084
|
+
relationships: {
|
|
3085
|
+
...this.#format.relationships,
|
|
3086
|
+
[relationship]: sq.#format
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3089
|
+
);
|
|
3090
|
+
}
|
|
3091
|
+
throw new Error(`Invalid relationship ${relationship}`);
|
|
3092
|
+
}
|
|
3093
|
+
where(fieldOrExpressionFactory, opOrValue, value) {
|
|
3094
|
+
let cond;
|
|
3095
|
+
if (typeof fieldOrExpressionFactory === "function") {
|
|
3096
|
+
cond = fieldOrExpressionFactory(
|
|
3097
|
+
new ExpressionBuilder(this._exists)
|
|
3098
|
+
);
|
|
3099
|
+
} else {
|
|
3100
|
+
assert(opOrValue !== void 0, "Invalid condition");
|
|
3101
|
+
cond = cmp(fieldOrExpressionFactory, opOrValue, value);
|
|
3102
|
+
}
|
|
3103
|
+
const existingWhere = this.#ast.where;
|
|
3104
|
+
if (existingWhere) {
|
|
3105
|
+
cond = and(existingWhere, cond);
|
|
3106
|
+
}
|
|
3107
|
+
return this._newQuery(
|
|
3108
|
+
this.#schema,
|
|
3109
|
+
this.#tableName,
|
|
3110
|
+
{
|
|
3111
|
+
...this.#ast,
|
|
3112
|
+
where: dnf(cond)
|
|
3113
|
+
},
|
|
3114
|
+
this.#ttl,
|
|
3115
|
+
this.#format
|
|
3116
|
+
);
|
|
3117
|
+
}
|
|
3118
|
+
start(row, opts) {
|
|
3119
|
+
return this._newQuery(
|
|
3120
|
+
this.#schema,
|
|
3121
|
+
this.#tableName,
|
|
3122
|
+
{
|
|
3123
|
+
...this.#ast,
|
|
3124
|
+
start: {
|
|
3125
|
+
row,
|
|
3126
|
+
exclusive: !opts?.inclusive
|
|
3127
|
+
}
|
|
3128
|
+
},
|
|
3129
|
+
this.#ttl,
|
|
3130
|
+
this.#format
|
|
3131
|
+
);
|
|
3132
|
+
}
|
|
3133
|
+
limit(limit) {
|
|
3134
|
+
if (limit < 0) {
|
|
3135
|
+
throw new Error("Limit must be non-negative");
|
|
3136
|
+
}
|
|
3137
|
+
if ((limit | 0) !== limit) {
|
|
3138
|
+
throw new Error("Limit must be an integer");
|
|
3139
|
+
}
|
|
3140
|
+
return this._newQuery(
|
|
3141
|
+
this.#schema,
|
|
3142
|
+
this.#tableName,
|
|
3143
|
+
{
|
|
3144
|
+
...this.#ast,
|
|
3145
|
+
limit
|
|
3146
|
+
},
|
|
3147
|
+
this.#ttl,
|
|
3148
|
+
this.#format
|
|
3149
|
+
);
|
|
3150
|
+
}
|
|
3151
|
+
orderBy(field, direction) {
|
|
3152
|
+
return this._newQuery(
|
|
3153
|
+
this.#schema,
|
|
3154
|
+
this.#tableName,
|
|
3155
|
+
{
|
|
3156
|
+
...this.#ast,
|
|
3157
|
+
orderBy: [...this.#ast.orderBy ?? [], [field, direction]]
|
|
3158
|
+
},
|
|
3159
|
+
this.#ttl,
|
|
3160
|
+
this.#format
|
|
3161
|
+
);
|
|
3162
|
+
}
|
|
3163
|
+
_exists = (relationship, cb = (q) => q) => {
|
|
3164
|
+
const related = this.#schema.relationships[this.#tableName][relationship];
|
|
3165
|
+
assert(related, "Invalid relationship");
|
|
3166
|
+
if (isOneHop(related)) {
|
|
3167
|
+
const { destSchema, sourceField, destField } = related[0];
|
|
3168
|
+
assert(isCompoundKey(sourceField), "Invalid relationship");
|
|
3169
|
+
assert(isCompoundKey(destField), "Invalid relationship");
|
|
3170
|
+
const sq = cb(
|
|
3171
|
+
this._newQuery(
|
|
3172
|
+
this.#schema,
|
|
3173
|
+
destSchema,
|
|
3174
|
+
{
|
|
3175
|
+
table: destSchema,
|
|
3176
|
+
alias: `${SUBQ_PREFIX}${relationship}`
|
|
3177
|
+
},
|
|
3178
|
+
this.#ttl,
|
|
3179
|
+
void 0
|
|
3180
|
+
)
|
|
3181
|
+
);
|
|
3182
|
+
return {
|
|
3183
|
+
type: "correlatedSubquery",
|
|
3184
|
+
related: {
|
|
3185
|
+
system: this._system,
|
|
3186
|
+
correlation: {
|
|
3187
|
+
parentField: sourceField,
|
|
3188
|
+
childField: destField
|
|
3189
|
+
},
|
|
3190
|
+
subquery: addPrimaryKeysToAst(
|
|
3191
|
+
this.#schema.tables[destSchema],
|
|
3192
|
+
sq.#ast
|
|
3193
|
+
)
|
|
3194
|
+
},
|
|
3195
|
+
op: "EXISTS"
|
|
3196
|
+
};
|
|
3197
|
+
}
|
|
3198
|
+
if (isTwoHop(related)) {
|
|
3199
|
+
assert(related.length === 2, "Invalid relationship");
|
|
3200
|
+
const [firstRelation, secondRelation] = related;
|
|
3201
|
+
assert(isCompoundKey(firstRelation.sourceField), "Invalid relationship");
|
|
3202
|
+
assert(isCompoundKey(firstRelation.destField), "Invalid relationship");
|
|
3203
|
+
assert(isCompoundKey(secondRelation.sourceField), "Invalid relationship");
|
|
3204
|
+
assert(isCompoundKey(secondRelation.destField), "Invalid relationship");
|
|
3205
|
+
const { destSchema } = secondRelation;
|
|
3206
|
+
const junctionSchema = firstRelation.destSchema;
|
|
3207
|
+
const queryToDest = cb(
|
|
3208
|
+
this._newQuery(
|
|
3209
|
+
this.#schema,
|
|
3210
|
+
destSchema,
|
|
3211
|
+
{
|
|
3212
|
+
table: destSchema,
|
|
3213
|
+
alias: `${SUBQ_PREFIX}${relationship}`
|
|
3214
|
+
},
|
|
3215
|
+
this.#ttl,
|
|
3216
|
+
void 0
|
|
3217
|
+
)
|
|
3218
|
+
);
|
|
3219
|
+
return {
|
|
3220
|
+
type: "correlatedSubquery",
|
|
3221
|
+
related: {
|
|
3222
|
+
system: this._system,
|
|
3223
|
+
correlation: {
|
|
3224
|
+
parentField: firstRelation.sourceField,
|
|
3225
|
+
childField: firstRelation.destField
|
|
3226
|
+
},
|
|
3227
|
+
subquery: {
|
|
3228
|
+
table: junctionSchema,
|
|
3229
|
+
alias: `${SUBQ_PREFIX}${relationship}`,
|
|
3230
|
+
orderBy: addPrimaryKeys(
|
|
3231
|
+
this.#schema.tables[junctionSchema],
|
|
3232
|
+
void 0
|
|
3233
|
+
),
|
|
3234
|
+
where: {
|
|
3235
|
+
type: "correlatedSubquery",
|
|
3236
|
+
related: {
|
|
3237
|
+
system: this._system,
|
|
3238
|
+
correlation: {
|
|
3239
|
+
parentField: secondRelation.sourceField,
|
|
3240
|
+
childField: secondRelation.destField
|
|
3241
|
+
},
|
|
3242
|
+
subquery: addPrimaryKeysToAst(
|
|
3243
|
+
this.#schema.tables[destSchema],
|
|
3244
|
+
queryToDest.#ast
|
|
3245
|
+
)
|
|
3246
|
+
},
|
|
3247
|
+
op: "EXISTS"
|
|
3248
|
+
}
|
|
3249
|
+
}
|
|
3250
|
+
},
|
|
3251
|
+
op: "EXISTS"
|
|
3252
|
+
};
|
|
3253
|
+
}
|
|
3254
|
+
throw new Error(`Invalid relationship ${relationship}`);
|
|
3255
|
+
};
|
|
3256
|
+
#completedAST;
|
|
3257
|
+
_completeAst() {
|
|
3258
|
+
if (!this.#completedAST) {
|
|
3259
|
+
const finalOrderBy = addPrimaryKeys(
|
|
3260
|
+
this.#schema.tables[this.#tableName],
|
|
3261
|
+
this.#ast.orderBy
|
|
3262
|
+
);
|
|
3263
|
+
if (this.#ast.start) {
|
|
3264
|
+
const { row } = this.#ast.start;
|
|
3265
|
+
const narrowedRow = {};
|
|
3266
|
+
for (const [field] of finalOrderBy) {
|
|
3267
|
+
narrowedRow[field] = row[field];
|
|
3268
|
+
}
|
|
3269
|
+
this.#completedAST = {
|
|
3270
|
+
...this.#ast,
|
|
3271
|
+
start: {
|
|
3272
|
+
...this.#ast.start,
|
|
3273
|
+
row: narrowedRow
|
|
3274
|
+
},
|
|
3275
|
+
orderBy: finalOrderBy
|
|
3276
|
+
};
|
|
3277
|
+
} else {
|
|
3278
|
+
this.#completedAST = {
|
|
3279
|
+
...this.#ast,
|
|
3280
|
+
orderBy: addPrimaryKeys(
|
|
3281
|
+
this.#schema.tables[this.#tableName],
|
|
3282
|
+
this.#ast.orderBy
|
|
3283
|
+
)
|
|
3284
|
+
};
|
|
3285
|
+
}
|
|
3286
|
+
}
|
|
3287
|
+
return this.#completedAST;
|
|
3288
|
+
}
|
|
3289
|
+
};
|
|
3290
|
+
var completedAstSymbol = Symbol();
|
|
3291
|
+
var QueryImpl = class extends AbstractQuery {
|
|
3292
|
+
#delegate;
|
|
3293
|
+
constructor(delegate, schema, tableName, ast, ttl, format) {
|
|
3294
|
+
super(schema, tableName, ast, ttl, format);
|
|
3295
|
+
this.#delegate = delegate;
|
|
3296
|
+
}
|
|
3297
|
+
_system = "client";
|
|
3298
|
+
get [completedAstSymbol]() {
|
|
3299
|
+
return this._completeAst();
|
|
3300
|
+
}
|
|
3301
|
+
_newQuery(schema, tableName, ast, ttl, format) {
|
|
3302
|
+
return newQueryWithDetails(
|
|
3303
|
+
this.#delegate,
|
|
3304
|
+
schema,
|
|
3305
|
+
tableName,
|
|
3306
|
+
ast,
|
|
3307
|
+
ttl,
|
|
3308
|
+
format
|
|
3309
|
+
);
|
|
3310
|
+
}
|
|
3311
|
+
materialize(factory) {
|
|
3312
|
+
const ast = this._completeAst();
|
|
3313
|
+
const queryCompleteResolver = resolver();
|
|
3314
|
+
let queryGot = false;
|
|
3315
|
+
const ttl = void 0;
|
|
3316
|
+
const removeServerQuery = this.#delegate.addServerQuery(ast, ttl, (got) => {
|
|
3317
|
+
if (got) {
|
|
3318
|
+
queryGot = true;
|
|
3319
|
+
queryCompleteResolver.resolve(true);
|
|
3320
|
+
}
|
|
3321
|
+
});
|
|
3322
|
+
const input = buildPipeline(ast, this.#delegate);
|
|
3323
|
+
let removeCommitObserver;
|
|
3324
|
+
const onDestroy = () => {
|
|
3325
|
+
input.destroy();
|
|
3326
|
+
removeCommitObserver?.();
|
|
3327
|
+
removeServerQuery();
|
|
3328
|
+
};
|
|
3329
|
+
const view = this.#delegate.batchViewUpdates(
|
|
3330
|
+
() => (factory ?? arrayViewFactory)(
|
|
3331
|
+
this,
|
|
3332
|
+
input,
|
|
3333
|
+
this.format,
|
|
3334
|
+
onDestroy,
|
|
3335
|
+
(cb) => {
|
|
3336
|
+
removeCommitObserver = this.#delegate.onTransactionCommit(cb);
|
|
3337
|
+
},
|
|
3338
|
+
queryGot || queryCompleteResolver.promise
|
|
3339
|
+
)
|
|
3340
|
+
);
|
|
3341
|
+
return view;
|
|
3342
|
+
}
|
|
3343
|
+
run() {
|
|
3344
|
+
const v2 = this.materialize();
|
|
3345
|
+
const ret = v2.data;
|
|
3346
|
+
v2.destroy();
|
|
3347
|
+
return Promise.resolve(ret);
|
|
3348
|
+
}
|
|
3349
|
+
preload() {
|
|
3350
|
+
const { resolve, promise: complete } = resolver();
|
|
3351
|
+
const ast = this._completeAst();
|
|
3352
|
+
const ttl = void 0;
|
|
3353
|
+
const unsub = this.#delegate.addServerQuery(ast, ttl, (got) => {
|
|
3354
|
+
if (got) {
|
|
3355
|
+
resolve();
|
|
3356
|
+
}
|
|
3357
|
+
});
|
|
3358
|
+
return {
|
|
3359
|
+
cleanup: unsub,
|
|
3360
|
+
complete
|
|
3361
|
+
};
|
|
3362
|
+
}
|
|
3363
|
+
};
|
|
3364
|
+
function addPrimaryKeys(schema, orderBy) {
|
|
3365
|
+
orderBy = orderBy ?? [];
|
|
3366
|
+
const { primaryKey } = schema;
|
|
3367
|
+
const primaryKeysToAdd = new Set(primaryKey);
|
|
3368
|
+
for (const [field] of orderBy) {
|
|
3369
|
+
primaryKeysToAdd.delete(field);
|
|
3370
|
+
}
|
|
3371
|
+
if (primaryKeysToAdd.size === 0) {
|
|
3372
|
+
return orderBy;
|
|
3373
|
+
}
|
|
3374
|
+
return [
|
|
3375
|
+
...orderBy,
|
|
3376
|
+
...[...primaryKeysToAdd].map((key) => [key, "asc"])
|
|
3377
|
+
];
|
|
3378
|
+
}
|
|
3379
|
+
function addPrimaryKeysToAst(schema, ast) {
|
|
3380
|
+
return {
|
|
3381
|
+
...ast,
|
|
3382
|
+
orderBy: addPrimaryKeys(schema, ast.orderBy)
|
|
3383
|
+
};
|
|
3384
|
+
}
|
|
3385
|
+
function arrayViewFactory(_query, input, format, onDestroy, onTransactionCommit, queryComplete) {
|
|
3386
|
+
const v2 = new ArrayView(input, format, queryComplete);
|
|
3387
|
+
v2.onDestroy = onDestroy;
|
|
3388
|
+
onTransactionCommit(() => {
|
|
3389
|
+
v2.flush();
|
|
3390
|
+
});
|
|
3391
|
+
return v2;
|
|
3392
|
+
}
|
|
3393
|
+
function isCompoundKey(field) {
|
|
3394
|
+
return Array.isArray(field) && field.length >= 1;
|
|
3395
|
+
}
|
|
3396
|
+
|
|
3397
|
+
// ../zero-protocol/src/mutation-type-enum.ts
|
|
3398
|
+
var CRUD = "crud";
|
|
3399
|
+
var Custom = "custom";
|
|
3400
|
+
|
|
3401
|
+
// ../zero-protocol/src/primary-key.ts
|
|
3402
|
+
var primaryKeySchema = readonly(
|
|
3403
|
+
valita_exports.tuple([valita_exports.string()]).concat(valita_exports.array(valita_exports.string()))
|
|
3404
|
+
);
|
|
3405
|
+
var primaryKeyValueSchema = valita_exports.union(
|
|
3406
|
+
valita_exports.string(),
|
|
3407
|
+
valita_exports.number(),
|
|
3408
|
+
valita_exports.boolean()
|
|
3409
|
+
);
|
|
3410
|
+
var primaryKeyValueRecordSchema = readonlyRecord(
|
|
3411
|
+
primaryKeyValueSchema
|
|
3412
|
+
);
|
|
3413
|
+
|
|
3414
|
+
// ../zero-protocol/src/push.ts
|
|
3415
|
+
var CRUD_MUTATION_NAME = "_zero_crud";
|
|
3416
|
+
var insertOpSchema = valita_exports.object({
|
|
3417
|
+
op: valita_exports.literal("insert"),
|
|
3418
|
+
tableName: valita_exports.string(),
|
|
3419
|
+
primaryKey: primaryKeySchema,
|
|
3420
|
+
value: rowSchema
|
|
3421
|
+
});
|
|
3422
|
+
var upsertOpSchema = valita_exports.object({
|
|
3423
|
+
op: valita_exports.literal("upsert"),
|
|
3424
|
+
tableName: valita_exports.string(),
|
|
3425
|
+
primaryKey: primaryKeySchema,
|
|
3426
|
+
value: rowSchema
|
|
3427
|
+
});
|
|
3428
|
+
var updateOpSchema = valita_exports.object({
|
|
3429
|
+
op: valita_exports.literal("update"),
|
|
3430
|
+
tableName: valita_exports.string(),
|
|
3431
|
+
primaryKey: primaryKeySchema,
|
|
3432
|
+
// Partial value with at least the primary key fields
|
|
3433
|
+
value: rowSchema
|
|
3434
|
+
});
|
|
3435
|
+
var deleteOpSchema = valita_exports.object({
|
|
3436
|
+
op: valita_exports.literal("delete"),
|
|
3437
|
+
tableName: valita_exports.string(),
|
|
3438
|
+
primaryKey: primaryKeySchema,
|
|
3439
|
+
// Partial value representing the primary key
|
|
3440
|
+
value: primaryKeyValueRecordSchema
|
|
3441
|
+
});
|
|
3442
|
+
var crudOpSchema = valita_exports.union(
|
|
3443
|
+
insertOpSchema,
|
|
3444
|
+
upsertOpSchema,
|
|
3445
|
+
updateOpSchema,
|
|
3446
|
+
deleteOpSchema
|
|
3447
|
+
);
|
|
3448
|
+
var crudArgSchema = valita_exports.object({
|
|
3449
|
+
ops: valita_exports.array(crudOpSchema)
|
|
3450
|
+
});
|
|
3451
|
+
var crudArgsSchema = valita_exports.tuple([crudArgSchema]);
|
|
3452
|
+
var crudMutationSchema = valita_exports.object({
|
|
3453
|
+
type: valita_exports.literal(CRUD),
|
|
3454
|
+
id: valita_exports.number(),
|
|
3455
|
+
clientID: valita_exports.string(),
|
|
3456
|
+
name: valita_exports.literal(CRUD_MUTATION_NAME),
|
|
3457
|
+
args: crudArgsSchema,
|
|
3458
|
+
timestamp: valita_exports.number()
|
|
3459
|
+
});
|
|
3460
|
+
var customMutationSchema = valita_exports.object({
|
|
3461
|
+
type: valita_exports.literal(Custom),
|
|
3462
|
+
id: valita_exports.number(),
|
|
3463
|
+
clientID: valita_exports.string(),
|
|
3464
|
+
name: valita_exports.string(),
|
|
3465
|
+
args: valita_exports.array(jsonSchema),
|
|
3466
|
+
timestamp: valita_exports.number()
|
|
3467
|
+
});
|
|
3468
|
+
var mutationSchema = valita_exports.union(crudMutationSchema, customMutationSchema);
|
|
3469
|
+
var pushBodySchema = valita_exports.object({
|
|
3470
|
+
clientGroupID: valita_exports.string(),
|
|
3471
|
+
mutations: valita_exports.array(mutationSchema),
|
|
3472
|
+
pushVersion: valita_exports.number(),
|
|
3473
|
+
schemaVersion: valita_exports.number(),
|
|
3474
|
+
timestamp: valita_exports.number(),
|
|
3475
|
+
requestID: valita_exports.string()
|
|
3476
|
+
});
|
|
3477
|
+
var pushMessageSchema = valita_exports.tuple([valita_exports.literal("push"), pushBodySchema]);
|
|
3478
|
+
var mutationIDSchema = valita_exports.object({
|
|
3479
|
+
id: valita_exports.number(),
|
|
3480
|
+
clientID: valita_exports.string()
|
|
3481
|
+
});
|
|
3482
|
+
var appErrorSchema = valita_exports.object({
|
|
3483
|
+
error: valita_exports.literal("app"),
|
|
3484
|
+
details: valita_exports.string()
|
|
3485
|
+
});
|
|
3486
|
+
var zeroErrorSchema = valita_exports.object({
|
|
3487
|
+
error: valita_exports.literal("ooo-mutation")
|
|
3488
|
+
});
|
|
3489
|
+
var mutationOkSchema = valita_exports.object({});
|
|
3490
|
+
var mutationErrorSchema = valita_exports.union(appErrorSchema, zeroErrorSchema);
|
|
3491
|
+
var mutationResultSchema = valita_exports.union(mutationOkSchema, mutationErrorSchema);
|
|
3492
|
+
var mutationResponseSchema = valita_exports.object({
|
|
3493
|
+
id: mutationIDSchema,
|
|
3494
|
+
result: mutationResultSchema
|
|
3495
|
+
});
|
|
3496
|
+
var pushOkSchema = valita_exports.object({
|
|
3497
|
+
mutations: valita_exports.array(mutationResponseSchema)
|
|
3498
|
+
});
|
|
3499
|
+
var unsupportedPushVersionSchema = valita_exports.object({
|
|
3500
|
+
error: valita_exports.literal("unsupported-push-version")
|
|
3501
|
+
});
|
|
3502
|
+
var unsupportedSchemaVersionSchema = valita_exports.object({
|
|
3503
|
+
error: valita_exports.literal("unsupported-schema-version")
|
|
3504
|
+
});
|
|
3505
|
+
var pushErrorSchema = valita_exports.union(
|
|
3506
|
+
unsupportedPushVersionSchema,
|
|
3507
|
+
unsupportedSchemaVersionSchema
|
|
3508
|
+
);
|
|
3509
|
+
var pushResponseSchema = valita_exports.union(pushOkSchema, pushErrorSchema);
|
|
3510
|
+
function mapCRUD(arg, map) {
|
|
3511
|
+
return {
|
|
3512
|
+
ops: arg.ops.map(
|
|
3513
|
+
({ op, tableName, primaryKey, value }) => ({
|
|
3514
|
+
op,
|
|
3515
|
+
tableName: map.tableName(tableName),
|
|
3516
|
+
primaryKey: map.columns(tableName, primaryKey),
|
|
3517
|
+
value: map.row(tableName, value)
|
|
3518
|
+
// The cast is necessary because ts objects to the `value` field
|
|
3519
|
+
// for "delete" ops being different.
|
|
3520
|
+
})
|
|
3521
|
+
)
|
|
3522
|
+
};
|
|
3523
|
+
}
|
|
3524
|
+
|
|
3525
|
+
// ../zql/src/mutate/custom.ts
|
|
3526
|
+
function customMutatorKey(namespace, name) {
|
|
3527
|
+
assert(!namespace.includes("|"), "mutator namespaces must not include a |");
|
|
3528
|
+
assert(!name.includes("|"), "mutator names must not include a |");
|
|
3529
|
+
return `${namespace}|${name}`;
|
|
3530
|
+
}
|
|
3531
|
+
function splitMutatorKey(key) {
|
|
3532
|
+
return key.split("|");
|
|
3533
|
+
}
|
|
3534
|
+
|
|
3535
|
+
export {
|
|
3536
|
+
isProd,
|
|
3537
|
+
deepEqual,
|
|
3538
|
+
assertJSONValue,
|
|
3539
|
+
assertJSONObject,
|
|
3540
|
+
parse,
|
|
3541
|
+
assert2 as assert,
|
|
3542
|
+
test,
|
|
3543
|
+
readonlyObject,
|
|
3544
|
+
readonlyArray,
|
|
3545
|
+
readonlyRecord,
|
|
3546
|
+
valita_exports,
|
|
3547
|
+
joinIterables,
|
|
3548
|
+
first2 as first,
|
|
3549
|
+
wrapIterable,
|
|
3550
|
+
jsonSchema,
|
|
3551
|
+
jsonObjectSchema,
|
|
3552
|
+
rowSchema,
|
|
3553
|
+
toStaticParam,
|
|
3554
|
+
astSchema,
|
|
3555
|
+
normalizeAST,
|
|
3556
|
+
mapAST,
|
|
3557
|
+
mapCondition,
|
|
3558
|
+
h128,
|
|
3559
|
+
hashOfAST,
|
|
3560
|
+
filterPush,
|
|
3561
|
+
createPredicate,
|
|
3562
|
+
transformFilters,
|
|
3563
|
+
assertOrderingIncludesPK,
|
|
3564
|
+
ExpressionBuilder,
|
|
3565
|
+
newQuery,
|
|
3566
|
+
staticParam,
|
|
3567
|
+
AbstractQuery,
|
|
3568
|
+
primaryKeyValueSchema,
|
|
3569
|
+
primaryKeyValueRecordSchema,
|
|
3570
|
+
CRUD,
|
|
3571
|
+
Custom,
|
|
3572
|
+
CRUD_MUTATION_NAME,
|
|
3573
|
+
pushBodySchema,
|
|
3574
|
+
mapCRUD,
|
|
3575
|
+
customMutatorKey,
|
|
3576
|
+
splitMutatorKey
|
|
3577
|
+
};
|
|
3578
|
+
//# sourceMappingURL=chunk-P3NUVEQJ.js.map
|