mongo-query-normalizer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +15 -0
- package/README.md +193 -0
- package/README.zh-CN.md +194 -0
- package/dist/ast/builders.d.ts +8 -0
- package/dist/ast/builders.d.ts.map +1 -0
- package/dist/ast/builders.js +27 -0
- package/dist/ast/builders.js.map +1 -0
- package/dist/ast/contains-opaque.d.ts +3 -0
- package/dist/ast/contains-opaque.d.ts.map +1 -0
- package/dist/ast/contains-opaque.js +14 -0
- package/dist/ast/contains-opaque.js.map +1 -0
- package/dist/ast/guards.d.ts +7 -0
- package/dist/ast/guards.d.ts.map +1 -0
- package/dist/ast/guards.js +23 -0
- package/dist/ast/guards.js.map +1 -0
- package/dist/ast/hash.d.ts +4 -0
- package/dist/ast/hash.d.ts.map +1 -0
- package/dist/ast/hash.js +67 -0
- package/dist/ast/hash.js.map +1 -0
- package/dist/ast/index.d.ts +6 -0
- package/dist/ast/index.d.ts.map +1 -0
- package/dist/ast/index.js +22 -0
- package/dist/ast/index.js.map +1 -0
- package/dist/ast/types.d.ts +28 -0
- package/dist/ast/types.d.ts.map +1 -0
- package/dist/ast/types.js +3 -0
- package/dist/ast/types.js.map +1 -0
- package/dist/ast/visitor.d.ts +3 -0
- package/dist/ast/visitor.d.ts.map +1 -0
- package/dist/ast/visitor.js +12 -0
- package/dist/ast/visitor.js.map +1 -0
- package/dist/common/types.d.ts +46 -0
- package/dist/common/types.d.ts.map +1 -0
- package/dist/common/types.js +3 -0
- package/dist/common/types.js.map +1 -0
- package/dist/compile/compile.d.ts +5 -0
- package/dist/compile/compile.d.ts.map +1 -0
- package/dist/compile/compile.js +69 -0
- package/dist/compile/compile.js.map +1 -0
- package/dist/compile-selector.d.ts +9 -0
- package/dist/compile-selector.d.ts.map +1 -0
- package/dist/compile-selector.js +14 -0
- package/dist/compile-selector.js.map +1 -0
- package/dist/conflict.d.ts +18 -0
- package/dist/conflict.d.ts.map +1 -0
- package/dist/conflict.js +30 -0
- package/dist/conflict.js.map +1 -0
- package/dist/core/canonicalize.d.ts +11 -0
- package/dist/core/canonicalize.d.ts.map +1 -0
- package/dist/core/canonicalize.js +104 -0
- package/dist/core/canonicalize.js.map +1 -0
- package/dist/core/conditions.d.ts +8 -0
- package/dist/core/conditions.d.ts.map +1 -0
- package/dist/core/conditions.js +282 -0
- package/dist/core/conditions.js.map +1 -0
- package/dist/core/conflicts-and-tighten.d.ts +15 -0
- package/dist/core/conflicts-and-tighten.d.ts.map +1 -0
- package/dist/core/conflicts-and-tighten.js +26 -0
- package/dist/core/conflicts-and-tighten.js.map +1 -0
- package/dist/core/conflicts.d.ts +14 -0
- package/dist/core/conflicts.d.ts.map +1 -0
- package/dist/core/conflicts.js +157 -0
- package/dist/core/conflicts.js.map +1 -0
- package/dist/core/constraint-propagation.d.ts +15 -0
- package/dist/core/constraint-propagation.d.ts.map +1 -0
- package/dist/core/constraint-propagation.js +93 -0
- package/dist/core/constraint-propagation.js.map +1 -0
- package/dist/core/field-condition-normalize.d.ts +22 -0
- package/dist/core/field-condition-normalize.d.ts.map +1 -0
- package/dist/core/field-condition-normalize.js +225 -0
- package/dist/core/field-condition-normalize.js.map +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +14 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/normalize.d.ts +8 -0
- package/dist/core/normalize.d.ts.map +1 -0
- package/dist/core/normalize.js +44 -0
- package/dist/core/normalize.js.map +1 -0
- package/dist/core/operators.d.ts +11 -0
- package/dist/core/operators.d.ts.map +1 -0
- package/dist/core/operators.js +26 -0
- package/dist/core/operators.js.map +1 -0
- package/dist/core/predicate-merge.d.ts +9 -0
- package/dist/core/predicate-merge.d.ts.map +1 -0
- package/dist/core/predicate-merge.js +105 -0
- package/dist/core/predicate-merge.js.map +1 -0
- package/dist/core/predicateMerge.d.ts +17 -0
- package/dist/core/predicateMerge.d.ts.map +1 -0
- package/dist/core/predicateMerge.js +57 -0
- package/dist/core/predicateMerge.js.map +1 -0
- package/dist/core/simplify.d.ts +11 -0
- package/dist/core/simplify.d.ts.map +1 -0
- package/dist/core/simplify.js +128 -0
- package/dist/core/simplify.js.map +1 -0
- package/dist/core/stable-structural-key.d.ts +7 -0
- package/dist/core/stable-structural-key.d.ts.map +1 -0
- package/dist/core/stable-structural-key.js +71 -0
- package/dist/core/stable-structural-key.js.map +1 -0
- package/dist/core/utils.d.ts +16 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/core/utils.js +109 -0
- package/dist/core/utils.js.map +1 -0
- package/dist/flatten/flatten.d.ts +43 -0
- package/dist/flatten/flatten.d.ts.map +1 -0
- package/dist/flatten/flatten.js +68 -0
- package/dist/flatten/flatten.js.map +1 -0
- package/dist/flatten/index.d.ts +2 -0
- package/dist/flatten/index.d.ts.map +1 -0
- package/dist/flatten/index.js +10 -0
- package/dist/flatten/index.js.map +1 -0
- package/dist/flatten.d.ts +43 -0
- package/dist/flatten.d.ts.map +1 -0
- package/dist/flatten.js +68 -0
- package/dist/flatten.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/merge-ops.d.ts +33 -0
- package/dist/merge-ops.d.ts.map +1 -0
- package/dist/merge-ops.js +52 -0
- package/dist/merge-ops.js.map +1 -0
- package/dist/normalize-context.d.ts +16 -0
- package/dist/normalize-context.d.ts.map +1 -0
- package/dist/normalize-context.js +19 -0
- package/dist/normalize-context.js.map +1 -0
- package/dist/normalize.d.ts +6 -0
- package/dist/normalize.d.ts.map +1 -0
- package/dist/normalize.js +122 -0
- package/dist/normalize.js.map +1 -0
- package/dist/observe/diff.d.ts +7 -0
- package/dist/observe/diff.d.ts.map +1 -0
- package/dist/observe/diff.js +15 -0
- package/dist/observe/diff.js.map +1 -0
- package/dist/observe/level-boundary-hints.d.ts +11 -0
- package/dist/observe/level-boundary-hints.d.ts.map +1 -0
- package/dist/observe/level-boundary-hints.js +42 -0
- package/dist/observe/level-boundary-hints.js.map +1 -0
- package/dist/observe/level-preview-warning.d.ts +11 -0
- package/dist/observe/level-preview-warning.d.ts.map +1 -0
- package/dist/observe/level-preview-warning.js +42 -0
- package/dist/observe/level-preview-warning.js.map +1 -0
- package/dist/observe/metrics.d.ts +4 -0
- package/dist/observe/metrics.d.ts.map +1 -0
- package/dist/observe/metrics.js +30 -0
- package/dist/observe/metrics.js.map +1 -0
- package/dist/observe/warnings.d.ts +6 -0
- package/dist/observe/warnings.d.ts.map +1 -0
- package/dist/observe/warnings.js +24 -0
- package/dist/observe/warnings.js.map +1 -0
- package/dist/operations/compile.d.ts +7 -0
- package/dist/operations/compile.d.ts.map +1 -0
- package/dist/operations/compile.js +70 -0
- package/dist/operations/compile.js.map +1 -0
- package/dist/operations/conflicts-and-tighten.d.ts +29 -0
- package/dist/operations/conflicts-and-tighten.d.ts.map +1 -0
- package/dist/operations/conflicts-and-tighten.js +40 -0
- package/dist/operations/conflicts-and-tighten.js.map +1 -0
- package/dist/operations/conflicts.d.ts +28 -0
- package/dist/operations/conflicts.d.ts.map +1 -0
- package/dist/operations/conflicts.js +216 -0
- package/dist/operations/conflicts.js.map +1 -0
- package/dist/operations/conflictsAndTighten.d.ts +29 -0
- package/dist/operations/conflictsAndTighten.d.ts.map +1 -0
- package/dist/operations/conflictsAndTighten.js +40 -0
- package/dist/operations/conflictsAndTighten.js.map +1 -0
- package/dist/operations/merge.d.ts +18 -0
- package/dist/operations/merge.d.ts.map +1 -0
- package/dist/operations/merge.js +266 -0
- package/dist/operations/merge.js.map +1 -0
- package/dist/operations/parse.d.ts +20 -0
- package/dist/operations/parse.d.ts.map +1 -0
- package/dist/operations/parse.js +128 -0
- package/dist/operations/parse.js.map +1 -0
- package/dist/ops/compile-selector.d.ts +9 -0
- package/dist/ops/compile-selector.d.ts.map +1 -0
- package/dist/ops/compile-selector.js +14 -0
- package/dist/ops/compile-selector.js.map +1 -0
- package/dist/ops/index.d.ts +4 -0
- package/dist/ops/index.d.ts.map +1 -0
- package/dist/ops/index.js +14 -0
- package/dist/ops/index.js.map +1 -0
- package/dist/ops/merge-ops.d.ts +33 -0
- package/dist/ops/merge-ops.d.ts.map +1 -0
- package/dist/ops/merge-ops.js +52 -0
- package/dist/ops/merge-ops.js.map +1 -0
- package/dist/ops/parse-selector.d.ts +18 -0
- package/dist/ops/parse-selector.d.ts.map +1 -0
- package/dist/ops/parse-selector.js +29 -0
- package/dist/ops/parse-selector.js.map +1 -0
- package/dist/optimize.d.ts +18 -0
- package/dist/optimize.d.ts.map +1 -0
- package/dist/optimize.js +33 -0
- package/dist/optimize.js.map +1 -0
- package/dist/options/constants.d.ts +6 -0
- package/dist/options/constants.d.ts.map +1 -0
- package/dist/options/constants.js +72 -0
- package/dist/options/constants.js.map +1 -0
- package/dist/options/resolve.d.ts +3 -0
- package/dist/options/resolve.d.ts.map +1 -0
- package/dist/options/resolve.js +35 -0
- package/dist/options/resolve.js.map +1 -0
- package/dist/options/types.d.ts +2 -0
- package/dist/options/types.d.ts.map +1 -0
- package/dist/options/types.js +3 -0
- package/dist/options/types.js.map +1 -0
- package/dist/parse/parse.d.ts +4 -0
- package/dist/parse/parse.d.ts.map +1 -0
- package/dist/parse/parse.js +114 -0
- package/dist/parse/parse.js.map +1 -0
- package/dist/parse/plain-object.d.ts +2 -0
- package/dist/parse/plain-object.d.ts.map +1 -0
- package/dist/parse/plain-object.js +7 -0
- package/dist/parse/plain-object.js.map +1 -0
- package/dist/parse-selector.d.ts +18 -0
- package/dist/parse-selector.d.ts.map +1 -0
- package/dist/parse-selector.js +29 -0
- package/dist/parse-selector.js.map +1 -0
- package/dist/passes/canonicalize.d.ts +4 -0
- package/dist/passes/canonicalize.d.ts.map +1 -0
- package/dist/passes/canonicalize.js +40 -0
- package/dist/passes/canonicalize.js.map +1 -0
- package/dist/passes/normalize-predicate.d.ts +4 -0
- package/dist/passes/normalize-predicate.d.ts.map +1 -0
- package/dist/passes/normalize-predicate.js +57 -0
- package/dist/passes/normalize-predicate.js.map +1 -0
- package/dist/passes/normalize-shape.d.ts +4 -0
- package/dist/passes/normalize-shape.d.ts.map +1 -0
- package/dist/passes/normalize-shape.js +37 -0
- package/dist/passes/normalize-shape.js.map +1 -0
- package/dist/passes/simplify.d.ts +4 -0
- package/dist/passes/simplify.d.ts.map +1 -0
- package/dist/passes/simplify.js +49 -0
- package/dist/passes/simplify.js.map +1 -0
- package/dist/prune/conflict.d.ts +18 -0
- package/dist/prune/conflict.d.ts.map +1 -0
- package/dist/prune/conflict.js +30 -0
- package/dist/prune/conflict.js.map +1 -0
- package/dist/prune/index.d.ts +3 -0
- package/dist/prune/index.d.ts.map +1 -0
- package/dist/prune/index.js +9 -0
- package/dist/prune/index.js.map +1 -0
- package/dist/prune/prune.d.ts +11 -0
- package/dist/prune/prune.d.ts.map +1 -0
- package/dist/prune/prune.js +19 -0
- package/dist/prune/prune.js.map +1 -0
- package/dist/prune.d.ts +11 -0
- package/dist/prune.d.ts.map +1 -0
- package/dist/prune.js +19 -0
- package/dist/prune.js.map +1 -0
- package/dist/rewrite.d.ts +27 -0
- package/dist/rewrite.d.ts.map +1 -0
- package/dist/rewrite.js +62 -0
- package/dist/rewrite.js.map +1 -0
- package/dist/rules/experimental/hoist-common-predicates-from-or.d.ts +5 -0
- package/dist/rules/experimental/hoist-common-predicates-from-or.d.ts.map +1 -0
- package/dist/rules/experimental/hoist-common-predicates-from-or.js +153 -0
- package/dist/rules/experimental/hoist-common-predicates-from-or.js.map +1 -0
- package/dist/rules/logical/detect-common-predicates-in-or.d.ts +5 -0
- package/dist/rules/logical/detect-common-predicates-in-or.d.ts.map +1 -0
- package/dist/rules/logical/detect-common-predicates-in-or.js +82 -0
- package/dist/rules/logical/detect-common-predicates-in-or.js.map +1 -0
- package/dist/rules/predicate/collapse-contradictions.d.ts +5 -0
- package/dist/rules/predicate/collapse-contradictions.d.ts.map +1 -0
- package/dist/rules/predicate/collapse-contradictions.js +45 -0
- package/dist/rules/predicate/collapse-contradictions.js.map +1 -0
- package/dist/rules/predicate/dedupe-same-field-predicates.d.ts +5 -0
- package/dist/rules/predicate/dedupe-same-field-predicates.d.ts.map +1 -0
- package/dist/rules/predicate/dedupe-same-field-predicates.js +33 -0
- package/dist/rules/predicate/dedupe-same-field-predicates.js.map +1 -0
- package/dist/rules/predicate/merge-comparable-predicates.d.ts +5 -0
- package/dist/rules/predicate/merge-comparable-predicates.d.ts.map +1 -0
- package/dist/rules/predicate/merge-comparable-predicates.js +30 -0
- package/dist/rules/predicate/merge-comparable-predicates.js.map +1 -0
- package/dist/rules/predicate/merge-predicates-internal.d.ts +7 -0
- package/dist/rules/predicate/merge-predicates-internal.d.ts.map +1 -0
- package/dist/rules/predicate/merge-predicates-internal.js +186 -0
- package/dist/rules/predicate/merge-predicates-internal.js.map +1 -0
- package/dist/rules/shape/collapse-single-child-logical.d.ts +5 -0
- package/dist/rules/shape/collapse-single-child-logical.d.ts.map +1 -0
- package/dist/rules/shape/collapse-single-child-logical.js +20 -0
- package/dist/rules/shape/collapse-single-child-logical.js.map +1 -0
- package/dist/rules/shape/dedupe-logical-children.d.ts +6 -0
- package/dist/rules/shape/dedupe-logical-children.d.ts.map +1 -0
- package/dist/rules/shape/dedupe-logical-children.js +37 -0
- package/dist/rules/shape/dedupe-logical-children.js.map +1 -0
- package/dist/rules/shape/flatten-logical.d.ts +6 -0
- package/dist/rules/shape/flatten-logical.d.ts.map +1 -0
- package/dist/rules/shape/flatten-logical.js +37 -0
- package/dist/rules/shape/flatten-logical.js.map +1 -0
- package/dist/rules/shape/remove-empty-logical.d.ts +5 -0
- package/dist/rules/shape/remove-empty-logical.d.ts.map +1 -0
- package/dist/rules/shape/remove-empty-logical.js +21 -0
- package/dist/rules/shape/remove-empty-logical.js.map +1 -0
- package/dist/types.d.ts +70 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/compare-values.d.ts +6 -0
- package/dist/utils/compare-values.d.ts.map +1 -0
- package/dist/utils/compare-values.js +31 -0
- package/dist/utils/compare-values.js.map +1 -0
- package/dist/utils/deep-equal.d.ts +2 -0
- package/dist/utils/deep-equal.d.ts.map +1 -0
- package/dist/utils/deep-equal.js +30 -0
- package/dist/utils/deep-equal.js.map +1 -0
- package/dist/utils/is-opaque.d.ts +4 -0
- package/dist/utils/is-opaque.d.ts.map +1 -0
- package/dist/utils/is-opaque.js +42 -0
- package/dist/utils/is-opaque.js.map +1 -0
- package/dist/utils/stable-sort.d.ts +2 -0
- package/dist/utils/stable-sort.d.ts.map +1 -0
- package/dist/utils/stable-sort.js +16 -0
- package/dist/utils/stable-sort.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.simplify = simplify;
|
|
4
|
+
const builders_1 = require("../ast/builders");
|
|
5
|
+
const guards_1 = require("../ast/guards");
|
|
6
|
+
function simplify(node, normalizeContext) {
|
|
7
|
+
return simplifyRecursive(node, normalizeContext);
|
|
8
|
+
}
|
|
9
|
+
function simplifyRecursive(node, _normalizeContext) {
|
|
10
|
+
if (!(0, guards_1.isLogicalNode)(node)) {
|
|
11
|
+
return node;
|
|
12
|
+
}
|
|
13
|
+
const simplifiedChildren = node.children.map((child) => simplifyRecursive(child, _normalizeContext));
|
|
14
|
+
const rebuilt = node.op === "$and" ? (0, builders_1.andNode)(simplifiedChildren) : (0, builders_1.orNode)(simplifiedChildren);
|
|
15
|
+
return simplifyLogicalNode(rebuilt, _normalizeContext);
|
|
16
|
+
}
|
|
17
|
+
function simplifyLogicalNode(node, _normalizeContext) {
|
|
18
|
+
if (!(0, guards_1.isLogicalNode)(node)) {
|
|
19
|
+
return node;
|
|
20
|
+
}
|
|
21
|
+
if (node.op === "$and") {
|
|
22
|
+
if (node.children.some(guards_1.isFalseNode)) {
|
|
23
|
+
return (0, builders_1.falseNode)();
|
|
24
|
+
}
|
|
25
|
+
const filtered = node.children.filter((child) => !(0, guards_1.isTrueNode)(child));
|
|
26
|
+
if (filtered.length === 0) {
|
|
27
|
+
return (0, builders_1.trueNode)();
|
|
28
|
+
}
|
|
29
|
+
if (filtered.length === 1) {
|
|
30
|
+
return filtered[0];
|
|
31
|
+
}
|
|
32
|
+
return (0, builders_1.andNode)(filtered);
|
|
33
|
+
}
|
|
34
|
+
if (node.op === "$or") {
|
|
35
|
+
if (node.children.some(guards_1.isTrueNode)) {
|
|
36
|
+
return (0, builders_1.trueNode)();
|
|
37
|
+
}
|
|
38
|
+
const filtered = node.children.filter((child) => !(0, guards_1.isFalseNode)(child));
|
|
39
|
+
if (filtered.length === 0) {
|
|
40
|
+
return (0, builders_1.falseNode)();
|
|
41
|
+
}
|
|
42
|
+
if (filtered.length === 1) {
|
|
43
|
+
return filtered[0];
|
|
44
|
+
}
|
|
45
|
+
return (0, builders_1.orNode)(filtered);
|
|
46
|
+
}
|
|
47
|
+
return node;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=simplify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simplify.js","sourceRoot":"","sources":["../../src/passes/simplify.ts"],"names":[],"mappings":";;AAKA,4BAEC;AAPD,8CAAuE;AACvE,0CAAuE;AAIvE,SAAgB,QAAQ,CAAC,IAAe,EAAE,gBAAkC;IACxE,OAAO,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAe,EAAE,iBAAmC;IAC3E,IAAI,CAAC,IAAA,sBAAa,EAAC,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,kBAAkB,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAErG,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,IAAA,kBAAO,EAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,IAAA,iBAAM,EAAC,kBAAkB,CAAC,CAAC;IAE9F,OAAO,mBAAmB,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAe,EAAE,iBAAmC;IAC7E,IAAI,CAAC,IAAA,sBAAa,EAAC,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,IAAI,IAAI,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;QACrB,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,oBAAW,CAAC,EAAE,CAAC;YAClC,OAAO,IAAA,oBAAS,GAAE,CAAC;QACvB,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAA,mBAAU,EAAC,KAAK,CAAC,CAAC,CAAC;QAErE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,IAAA,mBAAQ,GAAE,CAAC;QACtB,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,IAAA,kBAAO,EAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC;IAED,IAAI,IAAI,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QACpB,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,mBAAU,CAAC,EAAE,CAAC;YACjC,OAAO,IAAA,mBAAQ,GAAE,CAAC;QACtB,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAA,oBAAW,EAAC,KAAK,CAAC,CAAC,CAAC;QAEtE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,IAAA,oBAAS,GAAE,CAAC;QACvB,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,IAAA,iBAAM,EAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,IAAI,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 判断内层选择子句与外层选择子句在同一字段上的条件是否冲突。
|
|
3
|
+
* 冲突时修减阶段应舍弃该子分支或合并为更严条件。
|
|
4
|
+
*
|
|
5
|
+
* @param innerClause - 内层扁平条件(单层,无 $and/$or/$nor)
|
|
6
|
+
* @param outerClause - 外层已有扁平条件
|
|
7
|
+
* @returns 若存在某字段上条件互斥则为 true
|
|
8
|
+
*/
|
|
9
|
+
export declare function hasConflictingClauses(innerClause: Record<string, unknown>, outerClause: Record<string, unknown>): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* 判断同一字段上两个条件值是否互斥(如 $eq: 1 与 $eq: 2,或 $in 与 $nin 交集为空)。
|
|
12
|
+
*
|
|
13
|
+
* @param outerValue - 外层该字段的条件值
|
|
14
|
+
* @param innerValue - 内层该字段的条件值
|
|
15
|
+
* @returns 若两条件不可能同时满足则为 true
|
|
16
|
+
*/
|
|
17
|
+
export declare function isValueConflict(outerValue: unknown, innerValue: unknown): boolean;
|
|
18
|
+
//# sourceMappingURL=conflict.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict.d.ts","sourceRoot":"","sources":["../../src/prune/conflict.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,OAAO,CAIT;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,GAAG,OAAO,CAIjF"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hasConflictingClauses = hasConflictingClauses;
|
|
4
|
+
exports.isValueConflict = isValueConflict;
|
|
5
|
+
/**
|
|
6
|
+
* 判断内层选择子句与外层选择子句在同一字段上的条件是否冲突。
|
|
7
|
+
* 冲突时修减阶段应舍弃该子分支或合并为更严条件。
|
|
8
|
+
*
|
|
9
|
+
* @param innerClause - 内层扁平条件(单层,无 $and/$or/$nor)
|
|
10
|
+
* @param outerClause - 外层已有扁平条件
|
|
11
|
+
* @returns 若存在某字段上条件互斥则为 true
|
|
12
|
+
*/
|
|
13
|
+
function hasConflictingClauses(innerClause, outerClause) {
|
|
14
|
+
void innerClause;
|
|
15
|
+
void outerClause;
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 判断同一字段上两个条件值是否互斥(如 $eq: 1 与 $eq: 2,或 $in 与 $nin 交集为空)。
|
|
20
|
+
*
|
|
21
|
+
* @param outerValue - 外层该字段的条件值
|
|
22
|
+
* @param innerValue - 内层该字段的条件值
|
|
23
|
+
* @returns 若两条件不可能同时满足则为 true
|
|
24
|
+
*/
|
|
25
|
+
function isValueConflict(outerValue, innerValue) {
|
|
26
|
+
void outerValue;
|
|
27
|
+
void innerValue;
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=conflict.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflict.js","sourceRoot":"","sources":["../../src/prune/conflict.ts"],"names":[],"mappings":";;AAQA,sDAOC;AASD,0CAIC;AA5BD;;;;;;;GAOG;AACH,SAAgB,qBAAqB,CACnC,WAAoC,EACpC,WAAoC;IAEpC,KAAK,WAAW,CAAC;IACjB,KAAK,WAAW,CAAC;IACjB,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,eAAe,CAAC,UAAmB,EAAE,UAAmB;IACtE,KAAK,UAAU,CAAC;IAChB,KAAK,UAAU,CAAC;IAChB,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prune/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isValueConflict = exports.hasConflictingClauses = exports.simplifySelector = void 0;
|
|
4
|
+
var prune_js_1 = require("./prune.js");
|
|
5
|
+
Object.defineProperty(exports, "simplifySelector", { enumerable: true, get: function () { return prune_js_1.simplifySelector; } });
|
|
6
|
+
var conflict_js_1 = require("./conflict.js");
|
|
7
|
+
Object.defineProperty(exports, "hasConflictingClauses", { enumerable: true, get: function () { return conflict_js_1.hasConflictingClauses; } });
|
|
8
|
+
Object.defineProperty(exports, "isValueConflict", { enumerable: true, get: function () { return conflict_js_1.isValueConflict; } });
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prune/index.ts"],"names":[],"mappings":";;;AAAA,uCAA8C;AAArC,4GAAA,gBAAgB,OAAA;AACzB,6CAAuE;AAA9D,oHAAA,qBAAqB,OAAA;AAAE,8GAAA,eAAe,OAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Selector } from "../common/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* 阶段一:递归修减分支(冲突消除、去重、单值提升等)。
|
|
4
|
+
* 逐层处理 $and/$or/$nor,过滤无效条件、冲突则舍弃、合并同类项,不改变整体逻辑结构。
|
|
5
|
+
* 遇到 $nor / $comment / $text / $where 时保持原样不深入优化。
|
|
6
|
+
*
|
|
7
|
+
* @param selector - 原始选择器
|
|
8
|
+
* @returns 修减后的选择器(逻辑等价或更严,无新增分支)
|
|
9
|
+
*/
|
|
10
|
+
export declare function simplifySelector(selector: Selector): Selector;
|
|
11
|
+
//# sourceMappingURL=prune.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune.d.ts","sourceRoot":"","sources":["../../src/prune/prune.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAM7D"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.simplifySelector = simplifySelector;
|
|
4
|
+
/**
|
|
5
|
+
* 阶段一:递归修减分支(冲突消除、去重、单值提升等)。
|
|
6
|
+
* 逐层处理 $and/$or/$nor,过滤无效条件、冲突则舍弃、合并同类项,不改变整体逻辑结构。
|
|
7
|
+
* 遇到 $nor / $comment / $text / $where 时保持原样不深入优化。
|
|
8
|
+
*
|
|
9
|
+
* @param selector - 原始选择器
|
|
10
|
+
* @returns 修减后的选择器(逻辑等价或更严,无新增分支)
|
|
11
|
+
*/
|
|
12
|
+
function simplifySelector(selector) {
|
|
13
|
+
// TODO: 1. 拆出 $and/$or/$nor 与 base
|
|
14
|
+
// TODO: 2. 对 $nor/$comment/$text/$where 直接 return selector
|
|
15
|
+
// TODO: 3. 对 $and/$or 每项递归 simplifySelector,再合并同类、冲突检测舍弃
|
|
16
|
+
void selector;
|
|
17
|
+
return selector;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=prune.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune.js","sourceRoot":"","sources":["../../src/prune/prune.ts"],"names":[],"mappings":";;AAUA,4CAMC;AAdD;;;;;;;GAOG;AACH,SAAgB,gBAAgB,CAAC,QAAkB;IACjD,mCAAmC;IACnC,2DAA2D;IAC3D,yDAAyD;IACzD,KAAK,QAAQ,CAAC;IACd,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
package/dist/prune.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FilterQuery } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* 阶段一:递归修减分支。
|
|
4
|
+
* 逐层处理 $and/$or/$nor,过滤无效条件、冲突则舍弃、合并同类项,不改变整体逻辑结构。
|
|
5
|
+
* 遇到 $nor / $comment / $text / $where 时保持原样不深入优化。
|
|
6
|
+
*
|
|
7
|
+
* @param query - 原始查询条件
|
|
8
|
+
* @returns 修减后的查询(逻辑等价或更严,无新增分支)
|
|
9
|
+
*/
|
|
10
|
+
export declare function pruneSelector(query: FilterQuery): FilterQuery;
|
|
11
|
+
//# sourceMappingURL=prune.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune.d.ts","sourceRoot":"","sources":["../src/prune.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAM7D"}
|
package/dist/prune.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.pruneSelector = pruneSelector;
|
|
4
|
+
/**
|
|
5
|
+
* 阶段一:递归修减分支。
|
|
6
|
+
* 逐层处理 $and/$or/$nor,过滤无效条件、冲突则舍弃、合并同类项,不改变整体逻辑结构。
|
|
7
|
+
* 遇到 $nor / $comment / $text / $where 时保持原样不深入优化。
|
|
8
|
+
*
|
|
9
|
+
* @param query - 原始查询条件
|
|
10
|
+
* @returns 修减后的查询(逻辑等价或更严,无新增分支)
|
|
11
|
+
*/
|
|
12
|
+
function pruneSelector(query) {
|
|
13
|
+
// TODO: 1. 拆出 $and/$or/$nor 与 baseQuery
|
|
14
|
+
// TODO: 2. 对 $nor/$comment/$text/$where 直接 return query
|
|
15
|
+
// TODO: 3. 对 $and/$or 每项递归 pruneSelector,再合并同类、冲突检测舍弃
|
|
16
|
+
void query;
|
|
17
|
+
return query;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=prune.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune.js","sourceRoot":"","sources":["../src/prune.ts"],"names":[],"mappings":";;AAUA,sCAMC;AAdD;;;;;;;GAOG;AACH,SAAgB,aAAa,CAAC,KAAkB;IAC9C,wCAAwC;IACxC,wDAAwD;IACxD,sDAAsD;IACtD,KAAK,KAAK,CAAC;IACX,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { SelectorAST } from "./ast/types";
|
|
2
|
+
import type { RewriteOptions, Selector } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* 仅对 AST 做重写(不 parse、不 compile),便于复用 AST 重写逻辑或做 AST 级测试/模糊测试。
|
|
5
|
+
*
|
|
6
|
+
* **单轮管线**:normalize → predicateMerge → fieldConditionNormalize → simplify → predicateMerge →
|
|
7
|
+
* fieldConditionNormalize → canonicalize。
|
|
8
|
+
*
|
|
9
|
+
* simplify 会打平 `$and` 并可能把原先隔在嵌套里的同字段 `FieldNode` 变成兄弟节点,故在 simplify
|
|
10
|
+
* 之后必须再跑一轮 merge + 字段规范化,否则 compile 会输出「同字段拆成多条 $and 子句」,再 parse
|
|
11
|
+
* 时会被合并成单字段多 op,与首轮 AST 不一致。
|
|
12
|
+
*
|
|
13
|
+
* **固定点**:对上述管线反复应用直至 AST 稳定或达到 `REWRITE_AST_MAX_PASSES`(对外仍是一次 API 调用)。
|
|
14
|
+
* 保证在已支持范围内 `rewriteAst(rewriteAst(x))` 与 `rewriteAst(x)` 结构一致。
|
|
15
|
+
*
|
|
16
|
+
* 在已建模操作符子集内输出与输入**语义等价**的 AST;可判定矛盾时为 FalseNode。
|
|
17
|
+
* `options.indexSpecs` 仅影响 canonicalize 中 `$and` 下字段节点顺序,不改变语义。
|
|
18
|
+
*/
|
|
19
|
+
export declare function rewriteAst(ast: SelectorAST, options?: RewriteOptions): SelectorAST;
|
|
20
|
+
/**
|
|
21
|
+
* 重写 MongoDB 查询过滤器:结构规范化、同字段条件合并、逻辑化简与可判定冲突下的 IMPOSSIBLE_SELECTOR。
|
|
22
|
+
*
|
|
23
|
+
* **语义**(已建模字段操作符,见 README 矩阵):输出与输入匹配同一文档集;若可证明不可满足则返回
|
|
24
|
+
* `IMPOSSIBLE_SELECTOR`。未建模字段操作符透传,本库不对其做语义变换承诺。
|
|
25
|
+
*/
|
|
26
|
+
export declare function rewriteQuerySelector(selector: Selector, options?: RewriteOptions): Selector;
|
|
27
|
+
//# sourceMappingURL=rewrite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rewrite.d.ts","sourceRoot":"","sources":["../src/rewrite.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAsBxD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,WAAW,CAUlF;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,QAAQ,CAI3F"}
|
package/dist/rewrite.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rewriteAst = rewriteAst;
|
|
4
|
+
exports.rewriteQuerySelector = rewriteQuerySelector;
|
|
5
|
+
const node_util_1 = require("node:util");
|
|
6
|
+
const core_1 = require("./core");
|
|
7
|
+
const compile_1 = require("./operations/compile");
|
|
8
|
+
const parse_1 = require("./operations/parse");
|
|
9
|
+
/** 单轮 AST 管线(供内部固定点循环调用)。 */
|
|
10
|
+
function rewriteAstOnce(ast, options) {
|
|
11
|
+
const normalized = (0, core_1.normalize)(ast);
|
|
12
|
+
const merged = (0, core_1.predicateMerge)(normalized);
|
|
13
|
+
const fieldNormalized = (0, core_1.fieldConditionNormalize)(merged);
|
|
14
|
+
const simplified = (0, core_1.simplify)(fieldNormalized);
|
|
15
|
+
const mergedAfterSimplify = (0, core_1.predicateMerge)(simplified);
|
|
16
|
+
const fieldAfterSimplify = (0, core_1.fieldConditionNormalize)(mergedAfterSimplify);
|
|
17
|
+
return (0, core_1.canonicalize)(fieldAfterSimplify, options?.indexSpecs);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 内部最多迭代次数:每轮为完整 normalize→…→canonicalize;`canonicalize` 将字段子句排到前、逻辑子句在后,
|
|
21
|
+
* 可能使下一轮 `simplify` 才在同一 `$and` 层看到 sibling 字段上下文(例如先出现 `x:false` 再化简 `$nor:[{x:true}]`)。
|
|
22
|
+
*/
|
|
23
|
+
const REWRITE_AST_MAX_PASSES = 8;
|
|
24
|
+
/**
|
|
25
|
+
* 仅对 AST 做重写(不 parse、不 compile),便于复用 AST 重写逻辑或做 AST 级测试/模糊测试。
|
|
26
|
+
*
|
|
27
|
+
* **单轮管线**:normalize → predicateMerge → fieldConditionNormalize → simplify → predicateMerge →
|
|
28
|
+
* fieldConditionNormalize → canonicalize。
|
|
29
|
+
*
|
|
30
|
+
* simplify 会打平 `$and` 并可能把原先隔在嵌套里的同字段 `FieldNode` 变成兄弟节点,故在 simplify
|
|
31
|
+
* 之后必须再跑一轮 merge + 字段规范化,否则 compile 会输出「同字段拆成多条 $and 子句」,再 parse
|
|
32
|
+
* 时会被合并成单字段多 op,与首轮 AST 不一致。
|
|
33
|
+
*
|
|
34
|
+
* **固定点**:对上述管线反复应用直至 AST 稳定或达到 `REWRITE_AST_MAX_PASSES`(对外仍是一次 API 调用)。
|
|
35
|
+
* 保证在已支持范围内 `rewriteAst(rewriteAst(x))` 与 `rewriteAst(x)` 结构一致。
|
|
36
|
+
*
|
|
37
|
+
* 在已建模操作符子集内输出与输入**语义等价**的 AST;可判定矛盾时为 FalseNode。
|
|
38
|
+
* `options.indexSpecs` 仅影响 canonicalize 中 `$and` 下字段节点顺序,不改变语义。
|
|
39
|
+
*/
|
|
40
|
+
function rewriteAst(ast, options) {
|
|
41
|
+
let current = ast;
|
|
42
|
+
for (let pass = 0; pass < REWRITE_AST_MAX_PASSES; pass += 1) {
|
|
43
|
+
const next = rewriteAstOnce(current, options);
|
|
44
|
+
if ((0, node_util_1.isDeepStrictEqual)(next, current)) {
|
|
45
|
+
return next;
|
|
46
|
+
}
|
|
47
|
+
current = next;
|
|
48
|
+
}
|
|
49
|
+
return current;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 重写 MongoDB 查询过滤器:结构规范化、同字段条件合并、逻辑化简与可判定冲突下的 IMPOSSIBLE_SELECTOR。
|
|
53
|
+
*
|
|
54
|
+
* **语义**(已建模字段操作符,见 README 矩阵):输出与输入匹配同一文档集;若可证明不可满足则返回
|
|
55
|
+
* `IMPOSSIBLE_SELECTOR`。未建模字段操作符透传,本库不对其做语义变换承诺。
|
|
56
|
+
*/
|
|
57
|
+
function rewriteQuerySelector(selector, options) {
|
|
58
|
+
const ast = (0, parse_1.parseSelector)(selector);
|
|
59
|
+
const canonical = rewriteAst(ast, options);
|
|
60
|
+
return (0, compile_1.compileSelector)(canonical);
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=rewrite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rewrite.js","sourceRoot":"","sources":["../src/rewrite.ts"],"names":[],"mappings":";;AAwCA,gCAUC;AAQD,oDAIC;AA9DD,yCAA8C;AAG9C,iCAAoG;AACpG,kDAAuD;AACvD,8CAAmD;AAEnD,6BAA6B;AAC7B,SAAS,cAAc,CAAC,GAAgB,EAAE,OAAwB;IAC9D,MAAM,UAAU,GAAG,IAAA,gBAAS,EAAC,GAAG,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,IAAA,qBAAc,EAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,eAAe,GAAG,IAAA,8BAAuB,EAAC,MAAM,CAAC,CAAC;IACxD,MAAM,UAAU,GAAG,IAAA,eAAQ,EAAC,eAAe,CAAC,CAAC;IAC7C,MAAM,mBAAmB,GAAG,IAAA,qBAAc,EAAC,UAAU,CAAC,CAAC;IACvD,MAAM,kBAAkB,GAAG,IAAA,8BAAuB,EAAC,mBAAmB,CAAC,CAAC;IACxE,OAAO,IAAA,mBAAY,EAAC,kBAAkB,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;AACjE,CAAC;AAED;;;GAGG;AACH,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAEjC;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,UAAU,CAAC,GAAgB,EAAE,OAAwB;IACjE,IAAI,OAAO,GAAgB,GAAG,CAAC;IAC/B,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,sBAAsB,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9C,IAAI,IAAA,6BAAiB,EAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,OAAO,GAAG,IAAI,CAAC;IACnB,CAAC;IACD,OAAO,OAAO,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,SAAgB,oBAAoB,CAAC,QAAkB,EAAE,OAAwB;IAC7E,MAAM,GAAG,GAAG,IAAA,qBAAa,EAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC3C,OAAO,IAAA,yBAAe,EAAC,SAAS,CAAC,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { QueryNode } from "../../ast/types";
|
|
2
|
+
import type { NormalizeContext } from "../../normalize-context";
|
|
3
|
+
export declare const RULE_ID = "experimental.hoistCommonPredicatesFromOr";
|
|
4
|
+
export declare function hoistCommonPredicatesFromOr(node: QueryNode, normalizeContext: NormalizeContext, depth?: number): QueryNode;
|
|
5
|
+
//# sourceMappingURL=hoist-common-predicates-from-or.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hoist-common-predicates-from-or.d.ts","sourceRoot":"","sources":["../../../src/rules/experimental/hoist-common-predicates-from-or.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAA0C,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACzF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAIhE,eAAO,MAAM,OAAO,6CAA6C,CAAC;AAElE,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,KAAK,SAAI,GAAG,SAAS,CAmBrH"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RULE_ID = void 0;
|
|
4
|
+
exports.hoistCommonPredicatesFromOr = hoistCommonPredicatesFromOr;
|
|
5
|
+
const builders_1 = require("../../ast/builders");
|
|
6
|
+
const contains_opaque_1 = require("../../ast/contains-opaque");
|
|
7
|
+
const hash_1 = require("../../ast/hash");
|
|
8
|
+
const guards_1 = require("../../ast/guards");
|
|
9
|
+
const metrics_1 = require("../../observe/metrics");
|
|
10
|
+
const warnings_1 = require("../../observe/warnings");
|
|
11
|
+
exports.RULE_ID = "experimental.hoistCommonPredicatesFromOr";
|
|
12
|
+
function hoistCommonPredicatesFromOr(node, normalizeContext, depth = 0) {
|
|
13
|
+
if (!(0, guards_1.isLogicalNode)(node)) {
|
|
14
|
+
return node;
|
|
15
|
+
}
|
|
16
|
+
const rewrittenChildren = node.children.map((child) => hoistCommonPredicatesFromOr(child, normalizeContext, depth + 1));
|
|
17
|
+
const rebuilt = node.op === "$and" ? (0, builders_1.andNode)(rewrittenChildren) : (0, builders_1.orNode)(rewrittenChildren);
|
|
18
|
+
if (rebuilt.op !== "$or") {
|
|
19
|
+
return rebuilt;
|
|
20
|
+
}
|
|
21
|
+
if (!canHoistFromOr(rebuilt, normalizeContext, depth)) {
|
|
22
|
+
(0, warnings_1.markRuleSkipped)(normalizeContext, exports.RULE_ID, "cannot hoist safely");
|
|
23
|
+
return rebuilt;
|
|
24
|
+
}
|
|
25
|
+
return tryHoistCommonPredicates(rebuilt, normalizeContext);
|
|
26
|
+
}
|
|
27
|
+
function canHoistFromOr(node, normalizeContext, depth) {
|
|
28
|
+
if (normalizeContext.options.level !== "experimental") {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
if (!normalizeContext.options.rules.hoistCommonPredicatesFromOr) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
if (depth > normalizeContext.options.safety.maxNormalizeDepth) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
for (const child of node.children) {
|
|
38
|
+
if ((0, contains_opaque_1.containsOpaqueNode)(child)) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
function tryHoistCommonPredicates(node, normalizeContext) {
|
|
45
|
+
const split = splitCommonPredicatesFromBranches(node.children, normalizeContext);
|
|
46
|
+
if (!split || split.common.length === 0) {
|
|
47
|
+
(0, warnings_1.markRuleSkipped)(normalizeContext, exports.RULE_ID, "no hoistable common predicates");
|
|
48
|
+
return node;
|
|
49
|
+
}
|
|
50
|
+
const nextOr = (0, builders_1.orNode)(split.branches);
|
|
51
|
+
const result = (0, builders_1.andNode)([...split.common, nextOr]);
|
|
52
|
+
const oldCount = (0, metrics_1.collectNodeStats)(node).nodeCount;
|
|
53
|
+
const newCount = (0, metrics_1.collectNodeStats)(result).nodeCount;
|
|
54
|
+
const ratio = oldCount === 0 ? 0 : newCount / oldCount;
|
|
55
|
+
if (ratio > normalizeContext.options.safety.maxNodeGrowthRatio) {
|
|
56
|
+
(0, warnings_1.bailout)(normalizeContext, `node growth ratio exceeded: ${ratio}`);
|
|
57
|
+
return node;
|
|
58
|
+
}
|
|
59
|
+
(0, warnings_1.markRuleApplied)(normalizeContext, exports.RULE_ID);
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
function splitCommonPredicatesFromBranches(branches, _normalizeContext) {
|
|
63
|
+
const normalizedBranches = [];
|
|
64
|
+
const maps = [];
|
|
65
|
+
for (const branch of branches) {
|
|
66
|
+
const fields = extractHoistableFieldNodes(branch);
|
|
67
|
+
if (!fields) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
normalizedBranches.push(fields);
|
|
71
|
+
maps.push(toPredicateMap(fields));
|
|
72
|
+
}
|
|
73
|
+
const commonMap = intersectFieldPredicateMaps(maps);
|
|
74
|
+
if (commonMap.size === 0) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
const commonFieldNodes = commonFieldNodesFrom(commonMap);
|
|
78
|
+
const nextBranches = normalizedBranches.map((fields) => {
|
|
79
|
+
const remaining = removeCommonPredicates(fields, commonMap);
|
|
80
|
+
if (remaining.length === 0) {
|
|
81
|
+
return (0, builders_1.trueNode)();
|
|
82
|
+
}
|
|
83
|
+
if (remaining.length === 1) {
|
|
84
|
+
return remaining[0];
|
|
85
|
+
}
|
|
86
|
+
return (0, builders_1.andNode)(remaining);
|
|
87
|
+
});
|
|
88
|
+
return {
|
|
89
|
+
common: commonFieldNodes,
|
|
90
|
+
branches: nextBranches,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function extractHoistableFieldNodes(branch) {
|
|
94
|
+
if ((0, guards_1.isFieldNode)(branch)) {
|
|
95
|
+
return [branch];
|
|
96
|
+
}
|
|
97
|
+
if ((0, guards_1.isLogicalNode)(branch) && branch.op === "$and") {
|
|
98
|
+
if (!branch.children.every(guards_1.isFieldNode)) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
return branch.children;
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
function toPredicateMap(fields) {
|
|
106
|
+
const m = new Map();
|
|
107
|
+
for (const f of fields) {
|
|
108
|
+
m.set(f.field, [...f.predicates]);
|
|
109
|
+
}
|
|
110
|
+
return m;
|
|
111
|
+
}
|
|
112
|
+
function intersectFieldPredicateMaps(maps) {
|
|
113
|
+
if (maps.length === 0) {
|
|
114
|
+
return new Map();
|
|
115
|
+
}
|
|
116
|
+
const result = new Map();
|
|
117
|
+
for (const [field, preds0] of maps[0]) {
|
|
118
|
+
let common = preds0;
|
|
119
|
+
for (let i = 1; i < maps.length; i += 1) {
|
|
120
|
+
const other = maps[i].get(field);
|
|
121
|
+
if (!other) {
|
|
122
|
+
common = [];
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
common = common.filter((p) => other.some((q) => (0, hash_1.hashPredicate)(p) === (0, hash_1.hashPredicate)(q)));
|
|
126
|
+
}
|
|
127
|
+
if (common.length > 0) {
|
|
128
|
+
result.set(field, common);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
function commonFieldNodesFrom(commonMap) {
|
|
134
|
+
return [...commonMap.entries()].map(([field, preds]) => (0, builders_1.fieldNode)(field, preds));
|
|
135
|
+
}
|
|
136
|
+
function removeCommonPredicates(fields, commonMap) {
|
|
137
|
+
const out = [];
|
|
138
|
+
for (const f of fields) {
|
|
139
|
+
const commonPreds = commonMap.get(f.field);
|
|
140
|
+
if (!commonPreds || commonPreds.length === 0) {
|
|
141
|
+
out.push(f);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
const commonHashes = new Set(commonPreds.map((p) => (0, hash_1.hashPredicate)(p)));
|
|
145
|
+
const remaining = f.predicates.filter((p) => !commonHashes.has((0, hash_1.hashPredicate)(p)));
|
|
146
|
+
if (remaining.length === 0) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
out.push((0, builders_1.fieldNode)(f.field, remaining));
|
|
150
|
+
}
|
|
151
|
+
return out;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=hoist-common-predicates-from-or.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hoist-common-predicates-from-or.js","sourceRoot":"","sources":["../../../src/rules/experimental/hoist-common-predicates-from-or.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { QueryNode } from "../../ast/types";
|
|
2
|
+
import type { NormalizeContext } from "../../normalize-context";
|
|
3
|
+
export declare const RULE_ID = "logical.detectCommonPredicatesInOr";
|
|
4
|
+
export declare function detectCommonPredicatesInOr(node: QueryNode, normalizeContext: NormalizeContext): QueryNode;
|
|
5
|
+
//# sourceMappingURL=detect-common-predicates-in-or.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-common-predicates-in-or.d.ts","sourceRoot":"","sources":["../../../src/rules/logical/detect-common-predicates-in-or.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAe,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,eAAO,MAAM,OAAO,uCAAuC,CAAC;AAE5D,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,gBAAgB,GAAG,SAAS,CAYzG"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RULE_ID = void 0;
|
|
4
|
+
exports.detectCommonPredicatesInOr = detectCommonPredicatesInOr;
|
|
5
|
+
const builders_1 = require("../../ast/builders");
|
|
6
|
+
const hash_1 = require("../../ast/hash");
|
|
7
|
+
const guards_1 = require("../../ast/guards");
|
|
8
|
+
const warnings_1 = require("../../observe/warnings");
|
|
9
|
+
exports.RULE_ID = "logical.detectCommonPredicatesInOr";
|
|
10
|
+
function detectCommonPredicatesInOr(node, normalizeContext) {
|
|
11
|
+
if (!(0, guards_1.isLogicalNode)(node)) {
|
|
12
|
+
return node;
|
|
13
|
+
}
|
|
14
|
+
if (node.op === "$or") {
|
|
15
|
+
detectCommonPredicates(node, normalizeContext);
|
|
16
|
+
}
|
|
17
|
+
const nextChildren = node.children.map((child) => detectCommonPredicatesInOr(child, normalizeContext));
|
|
18
|
+
return node.op === "$and" ? (0, builders_1.andNode)(nextChildren) : (0, builders_1.orNode)(nextChildren);
|
|
19
|
+
}
|
|
20
|
+
function detectCommonPredicates(node, normalizeContext) {
|
|
21
|
+
const maps = node.children.map((branch) => extractComparableFieldPredicates(branch));
|
|
22
|
+
const common = intersectPredicateMaps(maps);
|
|
23
|
+
if (common.size === 0) {
|
|
24
|
+
(0, warnings_1.markRuleSkipped)(normalizeContext, exports.RULE_ID, "no common predicates found in $or");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
(0, warnings_1.markRuleApplied)(normalizeContext, exports.RULE_ID);
|
|
28
|
+
(0, warnings_1.addWarning)(normalizeContext, `common predicates detected in $or: ${formatPredicateMap(common)}`);
|
|
29
|
+
}
|
|
30
|
+
function extractComparableFieldPredicates(node) {
|
|
31
|
+
const map = new Map();
|
|
32
|
+
if ((0, guards_1.isFieldNode)(node)) {
|
|
33
|
+
const safe = node.predicates
|
|
34
|
+
.filter((p) => !p.opaque && p.op !== "raw")
|
|
35
|
+
.map((p) => (0, hash_1.hashPredicate)(p));
|
|
36
|
+
if (safe.length > 0) {
|
|
37
|
+
map.set(node.field, safe);
|
|
38
|
+
}
|
|
39
|
+
return map;
|
|
40
|
+
}
|
|
41
|
+
if ((0, guards_1.isLogicalNode)(node) && node.op === "$and") {
|
|
42
|
+
for (const child of node.children) {
|
|
43
|
+
if (!(0, guards_1.isFieldNode)(child)) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const safe = child.predicates
|
|
47
|
+
.filter((p) => !p.opaque && p.op !== "raw")
|
|
48
|
+
.map((p) => (0, hash_1.hashPredicate)(p));
|
|
49
|
+
if (safe.length > 0) {
|
|
50
|
+
map.set(child.field, safe);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return map;
|
|
55
|
+
}
|
|
56
|
+
function intersectPredicateMaps(maps) {
|
|
57
|
+
if (maps.length === 0) {
|
|
58
|
+
return new Map();
|
|
59
|
+
}
|
|
60
|
+
const result = new Map(maps[0]);
|
|
61
|
+
for (let i = 1; i < maps.length; i += 1) {
|
|
62
|
+
for (const [field, predicates] of [...result.entries()]) {
|
|
63
|
+
const other = maps[i].get(field);
|
|
64
|
+
if (!other) {
|
|
65
|
+
result.delete(field);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const intersection = predicates.filter((p) => other.includes(p));
|
|
69
|
+
if (intersection.length === 0) {
|
|
70
|
+
result.delete(field);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
result.set(field, intersection);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
function formatPredicateMap(common) {
|
|
80
|
+
return JSON.stringify([...common.entries()]);
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=detect-common-predicates-in-or.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-common-predicates-in-or.js","sourceRoot":"","sources":["../../../src/rules/logical/detect-common-predicates-in-or.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { QueryNode } from "../../ast/types";
|
|
2
|
+
import type { NormalizeContext } from "../../normalize-context";
|
|
3
|
+
export declare const RULE_ID = "predicate.collapseContradictions";
|
|
4
|
+
export declare function collapseContradictions(node: QueryNode, normalizeContext: NormalizeContext): QueryNode;
|
|
5
|
+
//# sourceMappingURL=collapse-contradictions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collapse-contradictions.d.ts","sourceRoot":"","sources":["../../../src/rules/predicate/collapse-contradictions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAkB,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAIhE,eAAO,MAAM,OAAO,qCAAqC,CAAC;AA4B1D,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,gBAAgB,GAAG,SAAS,CAerG"}
|