summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/query/planner_analysis.cpp35
-rw-r--r--src/mongo/db/query/query_solution.cpp48
2 files changed, 47 insertions, 36 deletions
diff --git a/src/mongo/db/query/planner_analysis.cpp b/src/mongo/db/query/planner_analysis.cpp
index d98deab746b..c8b04888b30 100644
--- a/src/mongo/db/query/planner_analysis.cpp
+++ b/src/mongo/db/query/planner_analysis.cpp
@@ -324,26 +324,25 @@ bool explodeNode(const QuerySolutionNode* node,
for (size_t pidx = 0; pidx < prefixIndices.size(); pidx++) {
invariant(pidx < isn->iets.size());
const auto& iet = isn->iets[pidx];
- if (const auto* ietEval = iet.cast<interval_evaluation_tree::EvalNode>(); ietEval) {
- if (ietEval->matchType() == MatchExpression::MATCH_IN) {
- auto ietExplode = interval_evaluation_tree::IET::make<
- interval_evaluation_tree::ExplodeNode>(
- iet, std::make_pair(nodeIndex, pidx), prefixIndices[pidx]);
- child->iets.push_back(std::move(ietExplode));
- } else {
- child->iets.push_back(iet);
+ auto needsExplodeNode = [&]() {
+ if (const auto* ietEval = iet.cast<interval_evaluation_tree::EvalNode>();
+ ietEval) {
+ return ietEval->matchType() == MatchExpression::MATCH_IN;
+ } else if (const auto* ietConst =
+ iet.cast<interval_evaluation_tree::ConstNode>();
+ ietConst) {
+ return ietConst->oil.intervals.size() > 1;
}
- } else if (const auto* ietConst = iet.cast<interval_evaluation_tree::ConstNode>();
- ietConst) {
- OrderedIntervalList oilChild(ietConst->oil.name);
- oilChild.intervals.push_back(ietConst->oil.intervals[prefixIndices[pidx]]);
- invariant(oilChild.isPoint());
- auto ietConstChild =
- interval_evaluation_tree::IET::make<interval_evaluation_tree::ConstNode>(
- oilChild);
- child->iets.push_back(ietConstChild);
- } else {
MONGO_UNREACHABLE;
+ }();
+
+ if (needsExplodeNode) {
+ auto ietExplode =
+ interval_evaluation_tree::IET::make<interval_evaluation_tree::ExplodeNode>(
+ iet, std::make_pair(nodeIndex, pidx), prefixIndices[pidx]);
+ child->iets.push_back(std::move(ietExplode));
+ } else {
+ child->iets.push_back(std::move(iet));
}
}
// Copy the rest of the unexploded IETs directly into the new child.
diff --git a/src/mongo/db/query/query_solution.cpp b/src/mongo/db/query/query_solution.cpp
index 80dc94b6b64..4f7c9b161e5 100644
--- a/src/mongo/db/query/query_solution.cpp
+++ b/src/mongo/db/query/query_solution.cpp
@@ -899,27 +899,39 @@ std::set<std::string> extractEqualityFields(
// If we have an IET for this field in our index bounds, we determine whether it
// guarantees that, upon evaluation, we will have point bounds for the corresponding
- // field in our index. In particular, if the IET evaluates to a ConstNode or an equality
- // EvalNode, then this field represents an equality.
+ // field in our index. In particular, if the IET evaluates to a ConstNode, an equality
+ // EvalNode, or an ExplodeNode, then this field represents an equality.
if (iets && !iets->empty()) {
const auto& iet = (*iets)[i];
- const auto* constNodePtr = iet.cast<interval_evaluation_tree::ConstNode>();
- const auto* evalNodePtr = iet.cast<interval_evaluation_tree::EvalNode>();
- const auto isEquality =
- evalNodePtr && evalNodePtr->matchType() == MatchExpression::MatchType::EQ;
- if (!constNodePtr && !isEquality)
- continue;
+ auto mustBePointInterval = [&]() {
+ if (const auto* constNode = iet.cast<interval_evaluation_tree::ConstNode>();
+ constNode) {
+ // If we have 'constNodePtr', it must be the case that the interval that it
+ // contains is the same as 'ival'.
+ tassert(7426201,
+ "'constNode' must have a single interval",
+ constNode->oil.intervals.size() == 1);
+ tassert(
+ 7426202,
+ "'constNode' must have the same point interval as the one in 'bounds'",
+ constNode->oil.intervals[0].equals(ival));
+ return true;
+ } else if (const auto* evalNode =
+ iet.cast<interval_evaluation_tree::EvalNode>();
+ evalNode) {
+ if (evalNode->matchType() == MatchExpression::MatchType::EQ) {
+ return true;
+ }
+ } else if (const auto* explodeNode =
+ iet.cast<interval_evaluation_tree::ExplodeNode>();
+ explodeNode) {
+ return true;
+ }
+ return false;
+ }();
- // If we have 'constNodePtr', it must be the case that the interval that it contains
- // is the same as 'ival'.
- if (constNodePtr) {
- tassert(7426201,
- "'constNodePtr' must have a single interval",
- constNodePtr->oil.intervals.size() == 1);
- tassert(
- 7426202,
- "'constNodePtr' must have the same point interval as the one in 'bounds'",
- constNodePtr->oil.intervals[0].equals(ival));
+ if (!mustBePointInterval) {
+ continue;
}
}
equalityFields.insert(oil.name);