diff options
author | David Percy <david.percy@mongodb.com> | 2023-04-05 19:19:22 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-04-25 21:03:18 +0000 |
commit | f55584c091541a27c0ccf3c1eceb5d58a4a9c896 (patch) | |
tree | fc24081ece0a082f0f7bf20be836e7e2b802058a /src/mongo/db/query/optimizer/index_bounds.cpp | |
parent | c01429db1722f1f26531e97073a8d6c5ed8182b0 (diff) | |
download | mongo-f55584c091541a27c0ccf3c1eceb5d58a4a9c896.tar.gz |
SERVER-69026 [CQF] Rewrite Sargable disjunction to RIDUnion
Diffstat (limited to 'src/mongo/db/query/optimizer/index_bounds.cpp')
-rw-r--r-- | src/mongo/db/query/optimizer/index_bounds.cpp | 65 |
1 files changed, 59 insertions, 6 deletions
diff --git a/src/mongo/db/query/optimizer/index_bounds.cpp b/src/mongo/db/query/optimizer/index_bounds.cpp index 72de5613a18..295ca6cc6a4 100644 --- a/src/mongo/db/query/optimizer/index_bounds.cpp +++ b/src/mongo/db/query/optimizer/index_bounds.cpp @@ -180,27 +180,80 @@ bool PartialSchemaRequirement::mayReturnNull(const ConstFoldFn& constFold) const return _boundProjectionName && checkMaybeHasNull(getIntervals(), constFold); }; -bool IndexPath3WComparator::operator()(const ABT& path1, const ABT& path2) const { +bool IndexPathLessComparator::operator()(const ABT& path1, const ABT& path2) const { return compareExprAndPaths(path1, path2) < 0; } -bool PartialSchemaKeyLessComparator::operator()(const PartialSchemaKey& k1, - const PartialSchemaKey& k2) const { +int PartialSchemaKeyComparator::Cmp3W::operator()(const PartialSchemaKey& k1, + const PartialSchemaKey& k2) const { if (const auto& p1 = k1._projectionName) { if (const auto& p2 = k2._projectionName) { const int projCmp = p1->compare(*p2); if (projCmp != 0) { - return projCmp < 0; + return projCmp; } // Fallthrough to comparison below. } else { - return false; + // p1 > p2 because nonempty > empty. + return 1; } } else if (k2._projectionName) { + // p1 < p2 because empty < nonempty + return -1; + } + // p1 == p2 so compare paths. + return compareExprAndPaths(k1._path, k2._path); +} +bool PartialSchemaKeyComparator::Less::operator()(const PartialSchemaKey& k1, + const PartialSchemaKey& k2) const { + return PartialSchemaKeyComparator::Cmp3W{}(k1, k2) < 0; +} + +int PartialSchemaRequirementComparator::Cmp3W::operator()( + const PartialSchemaRequirement& req1, const PartialSchemaRequirement& req2) const { + + int intervalCmp = compareIntervalExpr(req1.getIntervals(), req2.getIntervals()); + if (intervalCmp != 0) { + return intervalCmp; + } + + // Intervals are equal: compare the output bindings. + auto b1 = req1.getBoundProjectionName(); + auto b2 = req2.getBoundProjectionName(); + if (b1 && b2) { + return b1->compare(*b2); + } else if (b1) { + // b1 > b2 because nonempty > empty. + return 1; + } else if (b2) { + // b1 < b2 because empty < nonempty. + return -1; + } else { + // empty == empty. + return 0; + } +} + +bool PartialSchemaRequirementComparator::Less::operator()( + const PartialSchemaRequirement& req1, const PartialSchemaRequirement& req2) const { + + int intervalCmp = compareIntervalExpr(req1.getIntervals(), req2.getIntervals()); + if (intervalCmp < 0) { + return true; + } else if (intervalCmp > 0) { return false; } - return compareExprAndPaths(k1._path, k2._path) < 0; + // Intervals are equal: compare the output bindings. + auto b1 = req1.getBoundProjectionName(); + auto b2 = req2.getBoundProjectionName(); + if (b1 && b2) { + return b1->compare(*b2) < 0; + } else { + // If either or both optionals are empty, then the only way for + // 'b1 < b2' is '{} < {anything}'. + return !b1 && b2; + } } ResidualRequirement::ResidualRequirement(PartialSchemaKey key, |