@atscript/db 0.1.146 → 0.1.148
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agg-CV7y8nC6.d.cts → agg-42CSpGDR.d.cts} +2 -2
- package/dist/{agg-D5DHsAby.d.mts → agg-Wo-smrYV.d.mts} +3 -3
- package/dist/agg.cjs +1 -1
- package/dist/agg.d.cts +2 -2
- package/dist/agg.d.mts +2 -2
- package/dist/agg.mjs +1 -1
- package/dist/{aggregate-fns-CGBv3E8S.cjs → aggregate-fns-C-UJRobm.cjs} +52 -5
- package/dist/{aggregate-fns-CfsveE1w.mjs → aggregate-fns-CyaZyb9I.mjs} +35 -6
- package/dist/aggregate-rules-D_bsCpUI.cjs +26 -0
- package/dist/aggregate-rules-jdPrxqWa.mjs +15 -0
- package/dist/{buckets-DRycmhOW.d.mts → buckets-CNdTOnei.d.mts} +832 -33
- package/dist/{buckets-DYFu0eZ8.d.cts → buckets-DJiYlMXc.d.cts} +832 -33
- package/dist/{column-diff-D_Kyuh0S.cjs → column-diff-CUU4GvYg.cjs} +1546 -193
- package/dist/{column-diff-e2oHc71_.mjs → column-diff-Cp6ZoyRE.mjs} +1529 -200
- package/dist/{db-error-D5uilS_A.mjs → db-error-Az85UhTX.mjs} +32 -1
- package/dist/{db-error-DTkkeu5b.cjs → db-error-DRQH4sLY.cjs} +55 -0
- package/dist/{column-diff-Q9UmWn5x.d.mts → fk-diff-BQ4krij8.d.cts} +48 -2
- package/dist/{column-diff-w-Mym_3w.d.cts → fk-diff-DsaIijVX.d.mts} +48 -2
- package/dist/index.cjs +95 -35
- package/dist/index.d.cts +92 -22
- package/dist/index.d.mts +92 -22
- package/dist/index.mjs +65 -35
- package/dist/{nested-writer-xfQwxplL.cjs → nested-writer-BUQvk6QT.cjs} +734 -2
- package/dist/{nested-writer-CnOOAehr.mjs → nested-writer-CUBoq1ZO.mjs} +598 -4
- package/dist/numeric-operand-B1jKH7x5.mjs +21 -0
- package/dist/numeric-operand-DKfiRLYp.cjs +26 -0
- package/dist/ops.cjs +1 -1
- package/dist/ops.mjs +1 -1
- package/dist/plugin.cjs +293 -5
- package/dist/plugin.mjs +294 -6
- package/dist/rel.cjs +2 -2
- package/dist/rel.d.cts +2 -2
- package/dist/rel.d.mts +2 -2
- package/dist/rel.mjs +2 -2
- package/dist/{relation-helpers-B-0NRKat.d.mts → relation-helpers-Ba0v49sn.d.mts} +1 -1
- package/dist/{relation-helpers-BOMm_HUI.d.cts → relation-helpers-kX7jjgME.d.cts} +1 -1
- package/dist/relation-loader-ByY1Byrl.mjs +370 -0
- package/dist/relation-loader-D8OrdH-r.cjs +369 -0
- package/dist/shared.cjs +4 -1
- package/dist/shared.d.cts +16 -4
- package/dist/shared.d.mts +16 -4
- package/dist/shared.mjs +3 -2
- package/dist/sync.cjs +11 -7
- package/dist/sync.d.cts +2 -25
- package/dist/sync.d.mts +2 -25
- package/dist/sync.mjs +11 -7
- package/dist/{validation-utils-DOsB4e6G.cjs → validation-utils-Da2GjobR.cjs} +35 -24
- package/dist/{validation-utils-CMR4fe2M.mjs → validation-utils-Dq0uZ7ef.mjs} +35 -24
- package/dist/{validator-Clu2q_7z.mjs → validator-BTiIOTKP.mjs} +9 -3
- package/dist/{validator-CVS-onRg.cjs → validator-UcuJxHNT.cjs} +8 -2
- package/dist/{validator-Bw6ks9Hy.d.mts → validator-tBNvM1qc.d.cts} +31 -7
- package/dist/{validator-Bw6ks9Hy.d.cts → validator-tBNvM1qc.d.mts} +31 -7
- package/dist/validator.cjs +2 -2
- package/dist/validator.d.cts +1 -1
- package/dist/validator.d.mts +1 -1
- package/dist/validator.mjs +2 -2
- package/package.json +8 -8
- package/dist/relation-loader-CBPY6kM7.cjs +0 -461
- package/dist/relation-loader-D9XuXaMv.mjs +0 -462
|
@@ -1,6 +1,134 @@
|
|
|
1
|
-
const require_db_error = require("./db-error-
|
|
1
|
+
const require_db_error = require("./db-error-DRQH4sLY.cjs");
|
|
2
2
|
const require_object = require("./object-Djg28csK.cjs");
|
|
3
3
|
let _atscript_typescript_utils = require("@atscript/typescript/utils");
|
|
4
|
+
let _uniqu_core = require("@uniqu/core");
|
|
5
|
+
//#region src/query/query-tree.ts
|
|
6
|
+
/**
|
|
7
|
+
* `true` when a query-tree operand is a field reference (`{ field, type? }`)
|
|
8
|
+
* rather than a literal — e.g. the right side of a field-to-field comparison.
|
|
9
|
+
* @since 0.1.136
|
|
10
|
+
*/
|
|
11
|
+
function isFieldRef(value) {
|
|
12
|
+
return value !== null && typeof value === "object" && "field" in value;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Translates a JS-emitted query tree into a FilterExpr.
|
|
16
|
+
* Resolves field references (type + field path) to physical column names
|
|
17
|
+
* via the provided resolver function.
|
|
18
|
+
*/
|
|
19
|
+
function translateQueryTree(node, resolveField) {
|
|
20
|
+
if ("$and" in node) return { $and: node.$and.map((n) => translateQueryTree(n, resolveField)) };
|
|
21
|
+
if ("$or" in node) return { $or: node.$or.map((n) => translateQueryTree(n, resolveField)) };
|
|
22
|
+
if ("$not" in node) return { $not: translateQueryTree(node.$not, resolveField) };
|
|
23
|
+
const comp = node;
|
|
24
|
+
const leftField = resolveField(comp.left);
|
|
25
|
+
if (isFieldRef(comp.right)) {
|
|
26
|
+
const rightField = resolveField(comp.right);
|
|
27
|
+
return { [leftField]: { [comp.op]: { $field: rightField } } };
|
|
28
|
+
}
|
|
29
|
+
if (comp.op === "$exists") return { [leftField]: { $exists: comp.right !== false } };
|
|
30
|
+
return { [leftField]: { [comp.op]: comp.right } };
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Calls `leaf` with the field path of every field-reference leaf of a
|
|
34
|
+
* computed-column expression (`@db.compute`), in source order — leaves name
|
|
35
|
+
* the view's own fields.
|
|
36
|
+
* @since 0.1.147
|
|
37
|
+
*/
|
|
38
|
+
function walkViewExpr(expr, leaf) {
|
|
39
|
+
if (typeof expr === "number") return;
|
|
40
|
+
if ("field" in expr) {
|
|
41
|
+
leaf(expr.field);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
for (const arg of expr.args) walkViewExpr(arg, leaf);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Evaluates a computed expression in process (the memory adapter, a test, a
|
|
48
|
+
* third-party adapter) with the semantics every adapter shares: IEEE double,
|
|
49
|
+
* a leaf is `Number()`-ed, NULL / undefined propagates as `null`, `/` by zero
|
|
50
|
+
* is `null`, `coalesce` returns its first non-null value.
|
|
51
|
+
* @since 0.1.148
|
|
52
|
+
*/
|
|
53
|
+
function evaluateExpr(expr, leaf) {
|
|
54
|
+
if (typeof expr === "number") return expr;
|
|
55
|
+
if ("field" in expr) {
|
|
56
|
+
const v = leaf(expr.field);
|
|
57
|
+
if (v === null || v === void 0) return null;
|
|
58
|
+
const n = Number(v);
|
|
59
|
+
return Number.isNaN(n) ? null : n;
|
|
60
|
+
}
|
|
61
|
+
if (expr.op === "coalesce") {
|
|
62
|
+
for (const arg of expr.args) {
|
|
63
|
+
const v = evaluateExpr(arg, leaf);
|
|
64
|
+
if (v !== null) return v;
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const a = evaluateExpr(expr.args[0], leaf);
|
|
69
|
+
if (a === null) return null;
|
|
70
|
+
if (expr.op === "neg") return -a;
|
|
71
|
+
const b = evaluateExpr(expr.args[1], leaf);
|
|
72
|
+
if (b === null) return null;
|
|
73
|
+
switch (expr.op) {
|
|
74
|
+
case "+": return a + b;
|
|
75
|
+
case "-": return a - b;
|
|
76
|
+
case "*": return a * b;
|
|
77
|
+
default: return b === 0 ? null : a / b;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Whether a computed-column expression may yield NULL: a `/` (division by
|
|
82
|
+
* zero is NULL), a leaf for which `nullableLeaf` holds, or an operation over
|
|
83
|
+
* a nullable operand — `coalesce` only when every argument is nullable.
|
|
84
|
+
* @since 0.1.147
|
|
85
|
+
*/
|
|
86
|
+
function viewExprNullable(expr, nullableLeaf) {
|
|
87
|
+
if (typeof expr === "number") return false;
|
|
88
|
+
if ("field" in expr) return nullableLeaf(expr.field);
|
|
89
|
+
if (expr.op === "/") return true;
|
|
90
|
+
if (expr.op === "coalesce") return expr.args.every((a) => viewExprNullable(a, nullableLeaf));
|
|
91
|
+
return expr.args.some((a) => viewExprNullable(a, nullableLeaf));
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The `@db.compute` expression of a view field, if any.
|
|
95
|
+
* @since 0.1.147
|
|
96
|
+
*/
|
|
97
|
+
function computeOf(fieldType) {
|
|
98
|
+
return fieldType?.metadata.get("db.compute");
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The transitive non-computed operands of the `@db.compute` field `field` of
|
|
102
|
+
* `viewType`: its leaves, a computed leaf replaced by its own operands, and
|
|
103
|
+
* (`via`) the computed fields passed through. `undefined` when `field` is not
|
|
104
|
+
* computed. Cycles are not followed (they are rejected where the view's
|
|
105
|
+
* columns are built).
|
|
106
|
+
* @since 0.1.147
|
|
107
|
+
*/
|
|
108
|
+
function computedOperands(viewType, field) {
|
|
109
|
+
const props = viewType.type.kind === "object" ? viewType.type.props : void 0;
|
|
110
|
+
const exprOf = (name) => computeOf(props?.get(name));
|
|
111
|
+
const root = exprOf(field);
|
|
112
|
+
if (root === void 0) return void 0;
|
|
113
|
+
const out = /* @__PURE__ */ new Set();
|
|
114
|
+
const via = [];
|
|
115
|
+
const seen = new Set([field]);
|
|
116
|
+
const visit = (expr) => walkViewExpr(expr, (path) => {
|
|
117
|
+
const nested = exprOf(path);
|
|
118
|
+
if (nested === void 0) out.add(path);
|
|
119
|
+
else if (!seen.has(path)) {
|
|
120
|
+
seen.add(path);
|
|
121
|
+
via.push(path);
|
|
122
|
+
visit(nested);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
visit(root);
|
|
126
|
+
return {
|
|
127
|
+
operands: [...out],
|
|
128
|
+
via
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
//#endregion
|
|
4
132
|
//#region src/rel/relation-helpers.ts
|
|
5
133
|
/**
|
|
6
134
|
* Finds the FK entry that connects a `@db.rel.to` relation to its target.
|
|
@@ -52,10 +180,462 @@ function tableNameOf(type) {
|
|
|
52
180
|
function resolveRelationTargetTable(relation) {
|
|
53
181
|
return tableNameOf(relation.targetType());
|
|
54
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* A string key of `fields`' values on `obj` — equal for rows that agree on
|
|
185
|
+
* every field (`null` / `undefined` key distinctly from any string). `read`
|
|
186
|
+
* reads one field (default: a top-level property).
|
|
187
|
+
*/
|
|
188
|
+
function compositeKey(fields, obj, read = (o, f) => o[f]) {
|
|
189
|
+
let key = "";
|
|
190
|
+
for (let i = 0; i < fields.length; i++) {
|
|
191
|
+
if (i > 0) key += "\0\0";
|
|
192
|
+
const v = read(obj, fields[i]);
|
|
193
|
+
key += v === null || v === void 0 ? "\0" : String(v);
|
|
194
|
+
}
|
|
195
|
+
return key;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Keeps, of each group of `rows` sharing `keyOf(row)`, the rows `page`
|
|
199
|
+
* selects — `$skip` / `$limit` applied per group, in the order of `rows`.
|
|
200
|
+
* The order of the kept rows is preserved.
|
|
201
|
+
*/
|
|
202
|
+
function slicePerGroup(rows, keyOf, page) {
|
|
203
|
+
const skip = page.skip ?? 0;
|
|
204
|
+
const end = page.limit === void 0 ? Infinity : skip + page.limit;
|
|
205
|
+
const seen = /* @__PURE__ */ new Map();
|
|
206
|
+
const kept = [];
|
|
207
|
+
for (const row of rows) {
|
|
208
|
+
const key = keyOf(row);
|
|
209
|
+
const index = seen.get(key) ?? 0;
|
|
210
|
+
seen.set(key, index + 1);
|
|
211
|
+
if (index >= skip && index < end) kept.push(row);
|
|
212
|
+
}
|
|
213
|
+
return kept;
|
|
214
|
+
}
|
|
215
|
+
//#endregion
|
|
216
|
+
//#region src/query/relation-filter.ts
|
|
217
|
+
/**
|
|
218
|
+
* Relational filter predicates (`{ nav: { $some | $none: <filter on the
|
|
219
|
+
* related table> } }`) — resolution against the related tables.
|
|
220
|
+
*
|
|
221
|
+
* Semantics: `rel(r, nav)` is exactly the set of related rows `$with=nav`
|
|
222
|
+
* loads for row `r` (same foreign-key pairing, the relation's
|
|
223
|
+
* `@db.rel.filter` included). `$some: F` holds when one of them matches `F`,
|
|
224
|
+
* `$none: F` when none does; a NULL foreign-key component means "no related
|
|
225
|
+
* row". The core resolves each predicate into a {@link ResolvedRelationFilter}
|
|
226
|
+
* (physical names on every side, the inner filter translated by the related
|
|
227
|
+
* table's own field mapper) before the adapter sees the filter — adapters
|
|
228
|
+
* only render it.
|
|
229
|
+
*
|
|
230
|
+
* @since 0.1.147
|
|
231
|
+
*/
|
|
232
|
+
/**
|
|
233
|
+
* Maximum nesting of relational predicates in one filter, server-added ones
|
|
234
|
+
* included (a predicate inside a predicate's operand counts one level). The
|
|
235
|
+
* core backstop for every caller; higher than moost-db's per-client limit
|
|
236
|
+
* (`REL_FILTER_CLIENT_MAX_DEPTH`) so server overlays (row scopes,
|
|
237
|
+
* `transformRelationFilter`) have headroom above what a client may send.
|
|
238
|
+
*/
|
|
239
|
+
const REL_FILTER_MAX_DEPTH = 4;
|
|
240
|
+
/** Maximum number of relational predicates in one filter (nested and server-added ones included). See {@link REL_FILTER_MAX_DEPTH}. */
|
|
241
|
+
const REL_FILTER_MAX_NODES = 16;
|
|
242
|
+
/**
|
|
243
|
+
* Cross-realm brand of {@link ResolvedRelationFilter}: `instanceof` fails when
|
|
244
|
+
* two copies of `@atscript/db` are loaded (ESM + CJS, or nested installs) and
|
|
245
|
+
* an adapter from one sees nodes built by the other.
|
|
246
|
+
*/
|
|
247
|
+
const RESOLVED_BRAND = Symbol.for("@atscript/db:ResolvedRelationFilter");
|
|
248
|
+
/**
|
|
249
|
+
* A relational predicate as adapters receive it — the operand of
|
|
250
|
+
* `FilterVisitor.relation(field, op, operand)` once the core translated the
|
|
251
|
+
* filter. Every name is physical:
|
|
252
|
+
*
|
|
253
|
+
* - `to` / `from`: `pairs` correlate a SOURCE column with a TARGET column
|
|
254
|
+
* (`target.<pair.target> = source.<pair.source>`, one pair per composite
|
|
255
|
+
* key part);
|
|
256
|
+
* - `via`: `pairs` is empty — `junction.toSource` correlates the junction
|
|
257
|
+
* with the source row, `junction.toTarget` with the target row.
|
|
258
|
+
*
|
|
259
|
+
* `filter` is the inner filter on the TARGET (already translated by the
|
|
260
|
+
* target's field mapper: renames, flattening, value formatters; nested
|
|
261
|
+
* predicates resolved the same way), conjoined with the target part of the
|
|
262
|
+
* relation's `@db.rel.filter`. `{}` matches every related row.
|
|
263
|
+
*
|
|
264
|
+
* @since 0.1.147
|
|
265
|
+
*/
|
|
266
|
+
var ResolvedRelationFilter = class {
|
|
267
|
+
/** @internal cross-realm brand (see {@link isResolvedRelationFilter}). */
|
|
268
|
+
[RESOLVED_BRAND] = true;
|
|
269
|
+
kind;
|
|
270
|
+
/** Logical navigation field name on the source table. */
|
|
271
|
+
nav;
|
|
272
|
+
source;
|
|
273
|
+
target;
|
|
274
|
+
pairs;
|
|
275
|
+
junction;
|
|
276
|
+
filter;
|
|
277
|
+
constructor(init) {
|
|
278
|
+
this.kind = init.kind;
|
|
279
|
+
this.nav = init.nav;
|
|
280
|
+
this.source = init.source;
|
|
281
|
+
this.target = init.target;
|
|
282
|
+
this.pairs = init.pairs;
|
|
283
|
+
this.junction = init.junction;
|
|
284
|
+
this.filter = init.filter;
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
/** `true` for a {@link ResolvedRelationFilter} (the resolved operand of a predicate). */
|
|
288
|
+
function isResolvedRelationFilter(value) {
|
|
289
|
+
return typeof value === "object" && value !== null && value[RESOLVED_BRAND] === true;
|
|
290
|
+
}
|
|
291
|
+
/** `true` when `value` (a filter entry's value) is an operator map with a `$some` / `$none` key. */
|
|
292
|
+
function hasRelationOp(value) {
|
|
293
|
+
if (!require_object.isPlainObject(value)) return false;
|
|
294
|
+
for (const key in value) if ((0, _uniqu_core.isRelationOp)(key)) return true;
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Pre-scan results of filters the core BUILT (translated / resolved
|
|
299
|
+
* filters, never mutated after) — adapters scan the same translated filter
|
|
300
|
+
* several times per operation. Caller-owned filters are never cached: they
|
|
301
|
+
* may be mutated between two queries.
|
|
302
|
+
*/
|
|
303
|
+
const relationFilterCache = /* @__PURE__ */ new WeakMap();
|
|
304
|
+
/** @internal Records the pre-scan result of a filter the core built. */
|
|
305
|
+
function noteRelationFilter(filter, has) {
|
|
306
|
+
if (filter && typeof filter === "object") relationFilterCache.set(filter, has);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* `true` when `filter` holds a relational predicate anywhere outside
|
|
310
|
+
* predicate operands (through `$and` / `$or` / `$not`) — the cheap pre-scan
|
|
311
|
+
* the field mappers and renderers use to keep predicate-free filters on
|
|
312
|
+
* their fast paths. Results for filters the core translated are cached.
|
|
313
|
+
*/
|
|
314
|
+
function containsRelationFilter(filter) {
|
|
315
|
+
if (!filter || typeof filter !== "object") return false;
|
|
316
|
+
const cached = relationFilterCache.get(filter);
|
|
317
|
+
if (cached !== void 0) return cached;
|
|
318
|
+
for (const [key, value] of Object.entries(filter)) if (key === "$and" || key === "$or") {
|
|
319
|
+
if (Array.isArray(value) && value.some((child) => containsRelationFilter(child))) return true;
|
|
320
|
+
} else if (key === "$not") {
|
|
321
|
+
if (containsRelationFilter(value)) return true;
|
|
322
|
+
} else if (!key.startsWith("$") && hasRelationOp(value)) return true;
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Calls `visit` for every resolved predicate of a TRANSLATED filter,
|
|
327
|
+
* depth-first: the top-level ones, then (with `nested`) those inside each
|
|
328
|
+
* operand — target filters and junction filters alike. Adapters use it to
|
|
329
|
+
* prepare per-predicate data (memory snapshots, self-referencing checks).
|
|
330
|
+
*/
|
|
331
|
+
function forEachResolvedRelation(filter, visit, nested = true) {
|
|
332
|
+
if (!filter || typeof filter !== "object") return;
|
|
333
|
+
for (const [key, value] of Object.entries(filter)) if (key === "$and" || key === "$or") {
|
|
334
|
+
if (Array.isArray(value)) for (const child of value) forEachResolvedRelation(child, visit, nested);
|
|
335
|
+
} else if (key === "$not") forEachResolvedRelation(value, visit, nested);
|
|
336
|
+
else if (!key.startsWith("$") && require_object.isPlainObject(value)) for (const [op, operand] of Object.entries(value)) {
|
|
337
|
+
if (!(0, _uniqu_core.isRelationOp)(op) || !isResolvedRelationFilter(operand)) continue;
|
|
338
|
+
visit(operand, op);
|
|
339
|
+
if (nested) {
|
|
340
|
+
forEachResolvedRelation(operand.filter, visit, nested);
|
|
341
|
+
forEachResolvedRelation(operand.junction?.filter, visit, nested);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
/** A fresh {@link TRelGuardState} for one query. */
|
|
346
|
+
function relGuardState(write = false) {
|
|
347
|
+
return {
|
|
348
|
+
depth: 0,
|
|
349
|
+
counter: { nodes: 0 },
|
|
350
|
+
write,
|
|
351
|
+
path: ""
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
function invalid(path, message) {
|
|
355
|
+
return new require_db_error.DbError("INVALID_QUERY", [{
|
|
356
|
+
path,
|
|
357
|
+
message
|
|
358
|
+
}]);
|
|
359
|
+
}
|
|
360
|
+
function notSupported(path, message) {
|
|
361
|
+
return new require_db_error.DbError("REL_FILTER_NOT_SUPPORTED", [{
|
|
362
|
+
path,
|
|
363
|
+
message
|
|
364
|
+
}]);
|
|
365
|
+
}
|
|
366
|
+
/** The present, non-empty `parts` ANDed (`{}` when none, a single one as is). */
|
|
367
|
+
function andFilters(...parts) {
|
|
368
|
+
const present = parts.filter((p) => p != null && Object.keys(p).length > 0);
|
|
369
|
+
if (present.length === 0) return {};
|
|
370
|
+
if (present.length === 1) return present[0];
|
|
371
|
+
return { $and: present };
|
|
372
|
+
}
|
|
373
|
+
const NO_STATIC_FILTER = {};
|
|
374
|
+
const staticFilterCache = /* @__PURE__ */ new WeakMap();
|
|
375
|
+
/**
|
|
376
|
+
* A relation's `@db.rel.filter` as logical filters per side — what `$with`
|
|
377
|
+
* loading and relational predicates both AND into the related rows (the
|
|
378
|
+
* filter is part of the relation's meaning). Top-level `and` conditions are
|
|
379
|
+
* split by side: an unqualified field and the related type's fields go to
|
|
380
|
+
* `target`, the `@db.rel.via` junction's to `junction`. A single condition
|
|
381
|
+
* that reads both sides (e.g. an `or` across them) or compares two fields is
|
|
382
|
+
* rejected with `INVALID_QUERY` — `name` is the navigation field (error path).
|
|
383
|
+
*
|
|
384
|
+
* @since 0.1.147
|
|
385
|
+
*/
|
|
386
|
+
function relationStaticFilter(relation, name = "") {
|
|
387
|
+
if (!relation.filter) return NO_STATIC_FILTER;
|
|
388
|
+
const cached = staticFilterCache.get(relation);
|
|
389
|
+
if (cached) return cached;
|
|
390
|
+
const targetType = relation.targetType();
|
|
391
|
+
const junctionType = relation.viaType?.();
|
|
392
|
+
const targetName = tableNameOf(targetType);
|
|
393
|
+
const junctionName = junctionType ? tableNameOf(junctionType) : void 0;
|
|
394
|
+
const sideOf = (ref) => {
|
|
395
|
+
const type = ref.type?.();
|
|
396
|
+
if (!type || type === targetType || tableNameOf(type) === targetName) return "target";
|
|
397
|
+
if (junctionType && (type === junctionType || tableNameOf(type) === junctionName)) return "junction";
|
|
398
|
+
throw invalid(name, `@db.rel.filter on "${name}" references a type other than the related type` + (junctionType ? " and the junction" : "") + " — only those can be referenced");
|
|
399
|
+
};
|
|
400
|
+
const target = [];
|
|
401
|
+
const junction = [];
|
|
402
|
+
const conjuncts = "$and" in relation.filter ? relation.filter.$and : [relation.filter];
|
|
403
|
+
for (const conjunct of conjuncts) {
|
|
404
|
+
const sides = /* @__PURE__ */ new Set();
|
|
405
|
+
collectSides(conjunct, (ref) => sides.add(sideOf(ref)), name);
|
|
406
|
+
if (sides.size > 1) throw invalid(name, `@db.rel.filter on "${name}" has a condition reading both the junction and the related type — split it into separate "and" conditions`);
|
|
407
|
+
const filter = translateQueryTree(conjunct, (ref) => ref.field);
|
|
408
|
+
(sides.has("junction") ? junction : target).push(filter);
|
|
409
|
+
}
|
|
410
|
+
const result = {
|
|
411
|
+
target: target.length > 0 ? andFilters(...target) : void 0,
|
|
412
|
+
junction: junction.length > 0 ? andFilters(...junction) : void 0
|
|
413
|
+
};
|
|
414
|
+
staticFilterCache.set(relation, result);
|
|
415
|
+
return result;
|
|
416
|
+
}
|
|
417
|
+
function collectSides(node, visit, name) {
|
|
418
|
+
if ("$and" in node) {
|
|
419
|
+
for (const child of node.$and) collectSides(child, visit, name);
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
if ("$or" in node) {
|
|
423
|
+
for (const child of node.$or) collectSides(child, visit, name);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
if ("$not" in node) {
|
|
427
|
+
collectSides(node.$not, visit, name);
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
visit(node.left);
|
|
431
|
+
if (isFieldRef(node.right)) throw invalid(name, `@db.rel.filter on "${name}" compares two fields — only field-to-value conditions are supported`);
|
|
432
|
+
}
|
|
433
|
+
function zip(left, right, a, b) {
|
|
434
|
+
return left.map((value, i) => ({
|
|
435
|
+
[a]: value,
|
|
436
|
+
[b]: right[i]
|
|
437
|
+
}));
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* The {@link TRelationFilterHost} of a readable: resolves a navigation
|
|
441
|
+
* field's related table (and junction) through `resolve` (the readable's
|
|
442
|
+
* table resolver), pairing foreign keys exactly like `$with` loading does
|
|
443
|
+
* (`findFKEntryForRelation` / `findRemoteFK`).
|
|
444
|
+
*/
|
|
445
|
+
function createRelationFilterHost(owner, resolve) {
|
|
446
|
+
const plans = /* @__PURE__ */ new Map();
|
|
447
|
+
const sameAdapter = (other, path, what) => {
|
|
448
|
+
if (!owner.getAdapter().sharesStoreWith(other.getAdapter())) throw notSupported(path, `Relational predicate on "${path}": the ${what} table lives in a different database or adapter`);
|
|
449
|
+
};
|
|
450
|
+
const planOf = (nav, path) => {
|
|
451
|
+
const cached = plans.get(nav);
|
|
452
|
+
if (cached) return cached;
|
|
453
|
+
const meta = owner.getMetadata();
|
|
454
|
+
const relation = meta.relations.get(nav);
|
|
455
|
+
if (!relation) throw invalid(path, `"$some" / "$none" are only valid on a navigation relation — "${nav}" is not one`);
|
|
456
|
+
const target = resolve(relation.targetType());
|
|
457
|
+
if (!target) throw notSupported(path, `Relational predicate on "${path}": the related table is not available`);
|
|
458
|
+
sameAdapter(target, path, "related");
|
|
459
|
+
let plan;
|
|
460
|
+
if (relation.direction === "to") {
|
|
461
|
+
const fk = findFKEntryForRelation(relation, meta.foreignKeys);
|
|
462
|
+
if (!fk) throw invalid(path, `Relation "${nav}" has no foreign key to filter by`);
|
|
463
|
+
plan = {
|
|
464
|
+
kind: "to",
|
|
465
|
+
relation,
|
|
466
|
+
target,
|
|
467
|
+
pairs: zip(fk.fields, fk.targetFields, "source", "target")
|
|
468
|
+
};
|
|
469
|
+
} else if (relation.direction === "from") {
|
|
470
|
+
const fk = findRemoteFK(target.getMetadata(), owner.tableName, relation.alias);
|
|
471
|
+
if (!fk) throw invalid(path, `Relation "${nav}" has no foreign key to filter by`);
|
|
472
|
+
plan = {
|
|
473
|
+
kind: "from",
|
|
474
|
+
relation,
|
|
475
|
+
target,
|
|
476
|
+
pairs: zip(fk.targetFields, fk.fields, "source", "target")
|
|
477
|
+
};
|
|
478
|
+
} else {
|
|
479
|
+
const junctionType = relation.viaType?.();
|
|
480
|
+
const junction = junctionType ? resolve(junctionType) : void 0;
|
|
481
|
+
if (!junction) throw notSupported(path, `Relational predicate on "${path}": the junction table is not available`);
|
|
482
|
+
sameAdapter(junction, path, "junction");
|
|
483
|
+
const junctionMeta = junction.getMetadata();
|
|
484
|
+
const fkToThis = findRemoteFK(junctionMeta, owner.tableName);
|
|
485
|
+
const fkToTarget = findRemoteFK(junctionMeta, tableNameOf(relation.targetType()));
|
|
486
|
+
if (!fkToThis || !fkToTarget) throw invalid(path, `Relation "${nav}" has no junction foreign keys to filter by`);
|
|
487
|
+
if (fkToThis === fkToTarget) throw invalid(path, `Relation "${nav}" is a self-referencing many-to-many — relational predicates cannot tell its two junction keys apart`);
|
|
488
|
+
plan = {
|
|
489
|
+
kind: "via",
|
|
490
|
+
relation,
|
|
491
|
+
target,
|
|
492
|
+
pairs: [],
|
|
493
|
+
junction: {
|
|
494
|
+
owner: junction,
|
|
495
|
+
toSource: zip(fkToThis.fields, fkToThis.targetFields, "junction", "source"),
|
|
496
|
+
toTarget: zip(fkToTarget.fields, fkToTarget.targetFields, "junction", "target")
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
plans.set(nav, plan);
|
|
501
|
+
return plan;
|
|
502
|
+
};
|
|
503
|
+
const tableOf = (o) => {
|
|
504
|
+
const adapter = o.getAdapter();
|
|
505
|
+
return {
|
|
506
|
+
table: adapter.resolveTableName(),
|
|
507
|
+
name: adapter.resolveTableName(false),
|
|
508
|
+
adapter
|
|
509
|
+
};
|
|
510
|
+
};
|
|
511
|
+
return {
|
|
512
|
+
guard(nav, op, inner, state) {
|
|
513
|
+
const path = state.path ? `${state.path}.${nav}` : nav;
|
|
514
|
+
const depth = state.depth + 1;
|
|
515
|
+
if (depth > 4) throw invalid("", `Relational predicates nest at most 4 levels deep`);
|
|
516
|
+
if (++state.counter.nodes > 16) throw invalid("", `At most 16 relational predicates per query`);
|
|
517
|
+
if (!require_object.isPlainObject(inner)) throw invalid(path, `"${op}" on "${path}" expects a filter object`);
|
|
518
|
+
const plan = planOf(nav, path);
|
|
519
|
+
relationStaticFilter(plan.relation, path);
|
|
520
|
+
try {
|
|
521
|
+
plan.target._guardRelationOperand(inner, {
|
|
522
|
+
...state,
|
|
523
|
+
depth,
|
|
524
|
+
path
|
|
525
|
+
});
|
|
526
|
+
} catch (error) {
|
|
527
|
+
throw prefixError(error, path);
|
|
528
|
+
}
|
|
529
|
+
},
|
|
530
|
+
resolve(nav, _op, inner, depth) {
|
|
531
|
+
if (depth > 4) throw invalid("", `Relational predicates nest at most 4 levels deep`);
|
|
532
|
+
const plan = planOf(nav, nav);
|
|
533
|
+
const ownerMeta = owner.getMetadata();
|
|
534
|
+
const targetMeta = plan.target.getMetadata();
|
|
535
|
+
const statics = relationStaticFilter(plan.relation, nav);
|
|
536
|
+
const filter = plan.target._resolveRelationOperand(andFilters(statics.target, inner), depth);
|
|
537
|
+
let junction;
|
|
538
|
+
if (plan.junction) {
|
|
539
|
+
const junctionMeta = plan.junction.owner.getMetadata();
|
|
540
|
+
junction = {
|
|
541
|
+
...tableOf(plan.junction.owner),
|
|
542
|
+
toSource: plan.junction.toSource.map((p) => ({
|
|
543
|
+
junction: junctionMeta.physicalPath(p.junction),
|
|
544
|
+
source: ownerMeta.physicalPath(p.source)
|
|
545
|
+
})),
|
|
546
|
+
toTarget: plan.junction.toTarget.map((p) => ({
|
|
547
|
+
junction: junctionMeta.physicalPath(p.junction),
|
|
548
|
+
target: targetMeta.physicalPath(p.target)
|
|
549
|
+
})),
|
|
550
|
+
...statics.junction ? { filter: plan.junction.owner._resolveRelationOperand(statics.junction, depth) } : {}
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
return new ResolvedRelationFilter({
|
|
554
|
+
kind: plan.kind,
|
|
555
|
+
nav,
|
|
556
|
+
source: tableOf(owner),
|
|
557
|
+
target: tableOf(plan.target),
|
|
558
|
+
pairs: plan.pairs.map((p) => ({
|
|
559
|
+
source: ownerMeta.physicalPath(p.source),
|
|
560
|
+
target: targetMeta.physicalPath(p.target)
|
|
561
|
+
})),
|
|
562
|
+
junction,
|
|
563
|
+
filter
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
/** Re-throws a related table's guard error with its paths under the navigation chain. */
|
|
569
|
+
function prefixError(error, path) {
|
|
570
|
+
if (!(error instanceof require_db_error.DbError)) return error;
|
|
571
|
+
if (error.errors.every((e) => !e.path)) return error;
|
|
572
|
+
if (error.errors.every((e) => e.path === path || e.path.startsWith(`${path}.`))) return error;
|
|
573
|
+
const errors = error.errors.map((e) => ({
|
|
574
|
+
path: e.path ? `${path}.${e.path}` : path,
|
|
575
|
+
message: e.message
|
|
576
|
+
}));
|
|
577
|
+
return new require_db_error.DbError(error.code, errors, `${errors[0]?.message ?? error.message} (in "${path}")`);
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Resolves every relational predicate of a (logical) filter through
|
|
581
|
+
* `meta.relationFilters` — the step every field-mapper entry point runs
|
|
582
|
+
* first. Predicates at the top of `filter` are at level `depth + 1`.
|
|
583
|
+
* Already-resolved operands pass through, so translating twice is safe.
|
|
584
|
+
* One pass: unchanged subtrees (and `filter` itself, when nothing needed
|
|
585
|
+
* resolving) are returned as they are.
|
|
586
|
+
*/
|
|
587
|
+
function resolveRelationFilterTree(filter, meta, depth) {
|
|
588
|
+
let out;
|
|
589
|
+
for (const [key, value] of Object.entries(filter)) {
|
|
590
|
+
let next = value;
|
|
591
|
+
if (key === "$and" || key === "$or") {
|
|
592
|
+
if (Array.isArray(value)) {
|
|
593
|
+
let children;
|
|
594
|
+
for (let i = 0; i < value.length; i++) {
|
|
595
|
+
const child = value[i];
|
|
596
|
+
if (!child || typeof child !== "object") continue;
|
|
597
|
+
const resolved = resolveRelationFilterTree(child, meta, depth);
|
|
598
|
+
if (resolved === child) continue;
|
|
599
|
+
children ??= [...value];
|
|
600
|
+
children[i] = resolved;
|
|
601
|
+
}
|
|
602
|
+
if (children) next = children;
|
|
603
|
+
}
|
|
604
|
+
} else if (key === "$not") {
|
|
605
|
+
if (value && typeof value === "object") next = resolveRelationFilterTree(value, meta, depth);
|
|
606
|
+
} else if (!key.startsWith("$") && hasRelationOp(value)) next = resolvePredicateMap(key, value, meta, depth);
|
|
607
|
+
if (next === value) continue;
|
|
608
|
+
out ??= { ...filter };
|
|
609
|
+
out[key] = next;
|
|
610
|
+
}
|
|
611
|
+
if (!out) return filter;
|
|
612
|
+
noteRelationFilter(out, true);
|
|
613
|
+
return out;
|
|
614
|
+
}
|
|
615
|
+
/** One `{ $some | $none: … }` map of `key` resolved (operands already resolved pass through). */
|
|
616
|
+
function resolvePredicateMap(key, value, meta, depth) {
|
|
617
|
+
const host = meta.relationFilters;
|
|
618
|
+
if (!host) {
|
|
619
|
+
if (!meta.navFields.has(key)) throw invalid(key, `"$some" / "$none" are only valid on a navigation relation — "${key}" is not one`);
|
|
620
|
+
throw notSupported(key, `Relational predicate on "${key}" needs the table to come from a DbSpace (no table resolver)`);
|
|
621
|
+
}
|
|
622
|
+
const ops = {};
|
|
623
|
+
for (const [op, operand] of Object.entries(value)) {
|
|
624
|
+
if (!(0, _uniqu_core.isRelationOp)(op)) throw invalid(key, `Cannot mix "$some" / "$none" with "${op}" on "${key}"`);
|
|
625
|
+
ops[op] = isResolvedRelationFilter(operand) ? operand : host.resolve(key, op, operand, depth + 1);
|
|
626
|
+
}
|
|
627
|
+
return ops;
|
|
628
|
+
}
|
|
55
629
|
//#endregion
|
|
56
630
|
//#region src/shared/keys.ts
|
|
57
|
-
/**
|
|
631
|
+
/**
|
|
632
|
+
* String form of a key value, equal across driver representations: an
|
|
633
|
+
* ObjectId stringifies to its hex, a bigint to its digits, a Date to its ISO
|
|
634
|
+
* instant, a Buffer / Uint8Array to hex.
|
|
635
|
+
*/
|
|
58
636
|
function keyString(value) {
|
|
637
|
+
if (value instanceof Date) return Number.isNaN(value.getTime()) ? "Invalid Date" : value.toISOString();
|
|
638
|
+
if (value instanceof Uint8Array) return Array.from(value, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
59
639
|
return String(value);
|
|
60
640
|
}
|
|
61
641
|
/** Key equality across driver representations (number vs numeric string, ObjectId vs hex). */
|
|
@@ -82,6 +662,20 @@ function rowMatchesKey(row, key) {
|
|
|
82
662
|
for (const field in key) if (!sameKey(require_object.getPath(row, field), key[field])) return false;
|
|
83
663
|
return true;
|
|
84
664
|
}
|
|
665
|
+
/**
|
|
666
|
+
* Identity of the key tuple `fields` of `row` for uniqueness checks, or
|
|
667
|
+
* `undefined` when any component is null / missing (a NULL never collides).
|
|
668
|
+
* Equal across driver representations (see {@link keyString}).
|
|
669
|
+
*/
|
|
670
|
+
function uniqueKeyTuple(row, fields) {
|
|
671
|
+
const parts = [];
|
|
672
|
+
for (const field of fields) {
|
|
673
|
+
const value = require_object.getPath(row, field);
|
|
674
|
+
if (value === void 0 || value === null) return void 0;
|
|
675
|
+
parts.push(keyString(value));
|
|
676
|
+
}
|
|
677
|
+
return JSON.stringify(parts);
|
|
678
|
+
}
|
|
85
679
|
//#endregion
|
|
86
680
|
//#region src/table/error-utils.ts
|
|
87
681
|
/**
|
|
@@ -877,6 +1471,30 @@ async function viaReplace(via, targets, parentPK, maxDepth, depth) {
|
|
|
877
1471
|
await viaLinkTargets(via, targets, parentPK, maxDepth, depth);
|
|
878
1472
|
}
|
|
879
1473
|
//#endregion
|
|
1474
|
+
Object.defineProperty(exports, "REL_FILTER_MAX_DEPTH", {
|
|
1475
|
+
enumerable: true,
|
|
1476
|
+
get: function() {
|
|
1477
|
+
return REL_FILTER_MAX_DEPTH;
|
|
1478
|
+
}
|
|
1479
|
+
});
|
|
1480
|
+
Object.defineProperty(exports, "REL_FILTER_MAX_NODES", {
|
|
1481
|
+
enumerable: true,
|
|
1482
|
+
get: function() {
|
|
1483
|
+
return REL_FILTER_MAX_NODES;
|
|
1484
|
+
}
|
|
1485
|
+
});
|
|
1486
|
+
Object.defineProperty(exports, "ResolvedRelationFilter", {
|
|
1487
|
+
enumerable: true,
|
|
1488
|
+
get: function() {
|
|
1489
|
+
return ResolvedRelationFilter;
|
|
1490
|
+
}
|
|
1491
|
+
});
|
|
1492
|
+
Object.defineProperty(exports, "andFilters", {
|
|
1493
|
+
enumerable: true,
|
|
1494
|
+
get: function() {
|
|
1495
|
+
return andFilters;
|
|
1496
|
+
}
|
|
1497
|
+
});
|
|
880
1498
|
Object.defineProperty(exports, "applyPatchNestedTo", {
|
|
881
1499
|
enumerable: true,
|
|
882
1500
|
get: function() {
|
|
@@ -943,12 +1561,48 @@ Object.defineProperty(exports, "checkDepthOverflow", {
|
|
|
943
1561
|
return checkDepthOverflow;
|
|
944
1562
|
}
|
|
945
1563
|
});
|
|
1564
|
+
Object.defineProperty(exports, "compositeKey", {
|
|
1565
|
+
enumerable: true,
|
|
1566
|
+
get: function() {
|
|
1567
|
+
return compositeKey;
|
|
1568
|
+
}
|
|
1569
|
+
});
|
|
1570
|
+
Object.defineProperty(exports, "computeOf", {
|
|
1571
|
+
enumerable: true,
|
|
1572
|
+
get: function() {
|
|
1573
|
+
return computeOf;
|
|
1574
|
+
}
|
|
1575
|
+
});
|
|
1576
|
+
Object.defineProperty(exports, "computedOperands", {
|
|
1577
|
+
enumerable: true,
|
|
1578
|
+
get: function() {
|
|
1579
|
+
return computedOperands;
|
|
1580
|
+
}
|
|
1581
|
+
});
|
|
1582
|
+
Object.defineProperty(exports, "containsRelationFilter", {
|
|
1583
|
+
enumerable: true,
|
|
1584
|
+
get: function() {
|
|
1585
|
+
return containsRelationFilter;
|
|
1586
|
+
}
|
|
1587
|
+
});
|
|
1588
|
+
Object.defineProperty(exports, "createRelationFilterHost", {
|
|
1589
|
+
enumerable: true,
|
|
1590
|
+
get: function() {
|
|
1591
|
+
return createRelationFilterHost;
|
|
1592
|
+
}
|
|
1593
|
+
});
|
|
946
1594
|
Object.defineProperty(exports, "enrichFkViolation", {
|
|
947
1595
|
enumerable: true,
|
|
948
1596
|
get: function() {
|
|
949
1597
|
return enrichFkViolation;
|
|
950
1598
|
}
|
|
951
1599
|
});
|
|
1600
|
+
Object.defineProperty(exports, "evaluateExpr", {
|
|
1601
|
+
enumerable: true,
|
|
1602
|
+
get: function() {
|
|
1603
|
+
return evaluateExpr;
|
|
1604
|
+
}
|
|
1605
|
+
});
|
|
952
1606
|
Object.defineProperty(exports, "findFKEntryForRelation", {
|
|
953
1607
|
enumerable: true,
|
|
954
1608
|
get: function() {
|
|
@@ -967,6 +1621,36 @@ Object.defineProperty(exports, "findRemoteFK", {
|
|
|
967
1621
|
return findRemoteFK;
|
|
968
1622
|
}
|
|
969
1623
|
});
|
|
1624
|
+
Object.defineProperty(exports, "forEachResolvedRelation", {
|
|
1625
|
+
enumerable: true,
|
|
1626
|
+
get: function() {
|
|
1627
|
+
return forEachResolvedRelation;
|
|
1628
|
+
}
|
|
1629
|
+
});
|
|
1630
|
+
Object.defineProperty(exports, "hasRelationOp", {
|
|
1631
|
+
enumerable: true,
|
|
1632
|
+
get: function() {
|
|
1633
|
+
return hasRelationOp;
|
|
1634
|
+
}
|
|
1635
|
+
});
|
|
1636
|
+
Object.defineProperty(exports, "isFieldRef", {
|
|
1637
|
+
enumerable: true,
|
|
1638
|
+
get: function() {
|
|
1639
|
+
return isFieldRef;
|
|
1640
|
+
}
|
|
1641
|
+
});
|
|
1642
|
+
Object.defineProperty(exports, "isResolvedRelationFilter", {
|
|
1643
|
+
enumerable: true,
|
|
1644
|
+
get: function() {
|
|
1645
|
+
return isResolvedRelationFilter;
|
|
1646
|
+
}
|
|
1647
|
+
});
|
|
1648
|
+
Object.defineProperty(exports, "noteRelationFilter", {
|
|
1649
|
+
enumerable: true,
|
|
1650
|
+
get: function() {
|
|
1651
|
+
return noteRelationFilter;
|
|
1652
|
+
}
|
|
1653
|
+
});
|
|
970
1654
|
Object.defineProperty(exports, "pkTupleKey", {
|
|
971
1655
|
enumerable: true,
|
|
972
1656
|
get: function() {
|
|
@@ -991,12 +1675,30 @@ Object.defineProperty(exports, "preValidateNestedFrom", {
|
|
|
991
1675
|
return preValidateNestedFrom;
|
|
992
1676
|
}
|
|
993
1677
|
});
|
|
1678
|
+
Object.defineProperty(exports, "relGuardState", {
|
|
1679
|
+
enumerable: true,
|
|
1680
|
+
get: function() {
|
|
1681
|
+
return relGuardState;
|
|
1682
|
+
}
|
|
1683
|
+
});
|
|
1684
|
+
Object.defineProperty(exports, "relationStaticFilter", {
|
|
1685
|
+
enumerable: true,
|
|
1686
|
+
get: function() {
|
|
1687
|
+
return relationStaticFilter;
|
|
1688
|
+
}
|
|
1689
|
+
});
|
|
994
1690
|
Object.defineProperty(exports, "remapDeleteFkViolation", {
|
|
995
1691
|
enumerable: true,
|
|
996
1692
|
get: function() {
|
|
997
1693
|
return remapDeleteFkViolation;
|
|
998
1694
|
}
|
|
999
1695
|
});
|
|
1696
|
+
Object.defineProperty(exports, "resolveRelationFilterTree", {
|
|
1697
|
+
enumerable: true,
|
|
1698
|
+
get: function() {
|
|
1699
|
+
return resolveRelationFilterTree;
|
|
1700
|
+
}
|
|
1701
|
+
});
|
|
1000
1702
|
Object.defineProperty(exports, "resolveRelationTargetTable", {
|
|
1001
1703
|
enumerable: true,
|
|
1002
1704
|
get: function() {
|
|
@@ -1015,15 +1717,45 @@ Object.defineProperty(exports, "sameKey", {
|
|
|
1015
1717
|
return sameKey;
|
|
1016
1718
|
}
|
|
1017
1719
|
});
|
|
1720
|
+
Object.defineProperty(exports, "slicePerGroup", {
|
|
1721
|
+
enumerable: true,
|
|
1722
|
+
get: function() {
|
|
1723
|
+
return slicePerGroup;
|
|
1724
|
+
}
|
|
1725
|
+
});
|
|
1018
1726
|
Object.defineProperty(exports, "tableNameOf", {
|
|
1019
1727
|
enumerable: true,
|
|
1020
1728
|
get: function() {
|
|
1021
1729
|
return tableNameOf;
|
|
1022
1730
|
}
|
|
1023
1731
|
});
|
|
1732
|
+
Object.defineProperty(exports, "translateQueryTree", {
|
|
1733
|
+
enumerable: true,
|
|
1734
|
+
get: function() {
|
|
1735
|
+
return translateQueryTree;
|
|
1736
|
+
}
|
|
1737
|
+
});
|
|
1738
|
+
Object.defineProperty(exports, "uniqueKeyTuple", {
|
|
1739
|
+
enumerable: true,
|
|
1740
|
+
get: function() {
|
|
1741
|
+
return uniqueKeyTuple;
|
|
1742
|
+
}
|
|
1743
|
+
});
|
|
1024
1744
|
Object.defineProperty(exports, "validateBatch", {
|
|
1025
1745
|
enumerable: true,
|
|
1026
1746
|
get: function() {
|
|
1027
1747
|
return validateBatch;
|
|
1028
1748
|
}
|
|
1029
1749
|
});
|
|
1750
|
+
Object.defineProperty(exports, "viewExprNullable", {
|
|
1751
|
+
enumerable: true,
|
|
1752
|
+
get: function() {
|
|
1753
|
+
return viewExprNullable;
|
|
1754
|
+
}
|
|
1755
|
+
});
|
|
1756
|
+
Object.defineProperty(exports, "walkViewExpr", {
|
|
1757
|
+
enumerable: true,
|
|
1758
|
+
get: function() {
|
|
1759
|
+
return walkViewExpr;
|
|
1760
|
+
}
|
|
1761
|
+
});
|