summaryrefslogtreecommitdiff
path: root/src/mongo/db/query/plan_enumerator.cpp
diff options
context:
space:
mode:
authorLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-11 15:07:35 -0300
committerLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-11 15:07:35 -0300
commit4cb8841196d0625dfa3825aa326f071cd27c7b8b (patch)
tree1682a647d4463397c119183369ae6f750d5fdcff /src/mongo/db/query/plan_enumerator.cpp
parentaa03c6362cbaa767638e6eed9b031d86dd2643d1 (diff)
parent8f0827553e09872941945a093b647a4211a9db7f (diff)
Update upstream source from tag 'upstream/6.0.0'master
Update to upstream version '6.0.0' with Debian dir 5604a80ec1c96ca76f25f40d78e6ef855abec322
Diffstat (limited to 'src/mongo/db/query/plan_enumerator.cpp')
-rw-r--r--src/mongo/db/query/plan_enumerator.cpp52
1 files changed, 17 insertions, 35 deletions
diff --git a/src/mongo/db/query/plan_enumerator.cpp b/src/mongo/db/query/plan_enumerator.cpp
index 9e30afa0049..a11bc9b415a 100644
--- a/src/mongo/db/query/plan_enumerator.cpp
+++ b/src/mongo/db/query/plan_enumerator.cpp
@@ -35,7 +35,6 @@
#include "mongo/db/query/index_tag.h"
#include "mongo/db/query/indexability.h"
-#include "mongo/db/query/query_planner_common.h"
#include "mongo/logv2/log.h"
#include "mongo/util/string_map.h"
@@ -59,8 +58,8 @@ std::string getPathPrefix(std::string path) {
* is a predicate that is required to use an index.
*/
bool expressionRequiresIndex(const MatchExpression* node) {
- return QueryPlannerCommon::countNodes(node, MatchExpression::GEO_NEAR) > 0 ||
- QueryPlannerCommon::countNodes(node, MatchExpression::TEXT) > 0;
+ return CanonicalQuery::countNodes(node, MatchExpression::GEO_NEAR) > 0 ||
+ CanonicalQuery::countNodes(node, MatchExpression::TEXT) > 0;
}
size_t getPathLength(const MatchExpression* expr) {
@@ -338,8 +337,6 @@ string PlanEnumerator::NodeAssignment::toString() const {
str::stream ss;
ss << "ALL OF (lockstep): {";
ss << "\n\ttotalEnumerated: " << lockstepOrAssignment->totalEnumerated;
- ss << "\n\texhaustedLockstepIteration: "
- << lockstepOrAssignment->exhaustedLockstepIteration;
ss << "\n\tsubnodes: [ ";
for (auto&& node : lockstepOrAssignment->subnodes) {
ss << "\n\t\t{";
@@ -1290,8 +1287,6 @@ void PlanEnumerator::getIndexedPreds(MatchExpression* node,
std::vector<MatchExpression*>* indexedPreds) {
if (Indexability::nodeCanUseIndexOnOwnField(node)) {
RelevantTag* rt = static_cast<RelevantTag*>(node->getTag());
- tassert(9074700, "RelevantTag is not assigned to the match expression node", rt != nullptr);
-
if (context.elemMatchExpr) {
// If we're in an $elemMatch context, store the
// innermost parent $elemMatch, as well as the
@@ -1308,7 +1303,7 @@ void PlanEnumerator::getIndexedPreds(MatchExpression* node,
indexedPreds->push_back(node);
} else if (Indexability::isBoundsGeneratingNot(node)) {
getIndexedPreds(node->getChild(0), context, indexedPreds);
- } else if (Indexability::isBoundsGeneratingElemMatchObject(node)) {
+ } else if (MatchExpression::ELEM_MATCH_OBJECT == node->matchType()) {
PrepMemoContext childContext;
childContext.elemMatchExpr = node;
for (size_t i = 0; i < node->numChildren(); ++i) {
@@ -1694,8 +1689,8 @@ bool PlanEnumerator::LockstepOrAssignment::allIdentical() const {
return true;
}
-bool PlanEnumerator::LockstepOrAssignment::shouldResetBeforeProceeding(size_t totalEnumerated,
- size_t orLimit) const {
+bool PlanEnumerator::LockstepOrAssignment::shouldResetBeforeProceeding(
+ size_t totalEnumerated) const {
if (totalEnumerated == 0 || !exhaustedLockstepIteration) {
return false;
}
@@ -1705,12 +1700,7 @@ bool PlanEnumerator::LockstepOrAssignment::shouldResetBeforeProceeding(size_t to
if (!subnode.maxIterCount) {
return false; // Haven't yet looped over this child entirely, not ready yet.
}
- totalPossibleEnumerations *= subnode.maxIterCount.value();
- // If 'totalPossibleEnumerations' reaches the limit, we can just shortcut it. Otherwise,
- // 'totalPossibleEnumerations' could overflow if we have a large $or.
- if (totalPossibleEnumerations >= orLimit) {
- return false;
- }
+ totalPossibleEnumerations *= subnode.maxIterCount.get();
}
// If we're able to compute a total number expected enumerations, we must have already cycled
@@ -1747,7 +1737,7 @@ bool PlanEnumerator::_nextMemoForLockstepOrAssignment(
}
// Edge case: if every child has only one option available, we are already finished
// enumerating.
- if (assignment->shouldResetBeforeProceeding(assignment->totalEnumerated, _orLimit)) {
+ if (assignment->shouldResetBeforeProceeding(assignment->totalEnumerated)) {
assignment->exhaustedLockstepIteration = false;
return true; // We're back at the beginning, no need to reset.
}
@@ -1774,35 +1764,27 @@ bool PlanEnumerator::_nextMemoForLockstepOrAssignment(
}
};
advanceOnce();
- if (assignment->allIdentical()) {
- // All sub-nodes have the same enumeration state, skip this one since we already did it
- // above. This is expected to happen pretty often. For example, if we have two subnodes each
- // enumerating two states, we'd expect the order to be: 00, 11 (these two iterated above),
- // then 00 (skipped here when we fall through after finishing lockstep iteration), then 10,
- // 01, then finally 11 (skipped here).
- //
- // In this example, when we finally roll back to 00, enumeration is complete. We will fall
- // through the code below which is responsible for resetting all enumeration state to the
- // starting point (which need not reset the child nodes in this case because they already
- // all rolled back to the starting point of 00). Finally, we return true to indicate that
- // all possibilities have been enumerated.
+ while (assignment->allIdentical()) {
+ // All sub-nodes have the same enumeration state, skip this one since we already did
+ // it above. This is expected to happen pretty often. For example, if we have two subnodes
+ // each enumerating two states, we'd expect the order to be: 00, 11 (these two iterated
+ // above), then 00 (skipped by falling through above after finishing lockstep iteration),
+ // then 10, 11 (skipped here), 00 (skipped here), then finally 01.
advanceOnce();
}
// This special ordering is tricky to reset. Because it iterates the sub nodes in such a
// unique order, it can be difficult to know when it has actually finished iterating. Our
// strategy is just to compute a total and go back to the beginning once we hit that total.
- if (!assignment->shouldResetBeforeProceeding(assignment->totalEnumerated, _orLimit)) {
+ if (!assignment->shouldResetBeforeProceeding(assignment->totalEnumerated)) {
return false;
}
// Reset!
for (auto&& subnode : assignment->subnodes) {
- if (subnode.iterationCount != 0) {
- while (!nextMemo(subnode.memoId)) {
- // Keep advancing till it rolls over.
- }
- subnode.iterationCount = 0;
+ while (!nextMemo(subnode.memoId)) {
+ // Keep advancing till it rolls over.
}
+ subnode.iterationCount = 0;
}
assignment->exhaustedLockstepIteration = false;
return true;