summaryrefslogtreecommitdiff
path: root/src/mongo/db/query/plan_enumerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/query/plan_enumerator.cpp')
-rw-r--r--src/mongo/db/query/plan_enumerator.cpp15
1 files changed, 10 insertions, 5 deletions
diff --git a/src/mongo/db/query/plan_enumerator.cpp b/src/mongo/db/query/plan_enumerator.cpp
index a11bc9b415a..96fc70fb99c 100644
--- a/src/mongo/db/query/plan_enumerator.cpp
+++ b/src/mongo/db/query/plan_enumerator.cpp
@@ -1689,8 +1689,8 @@ bool PlanEnumerator::LockstepOrAssignment::allIdentical() const {
return true;
}
-bool PlanEnumerator::LockstepOrAssignment::shouldResetBeforeProceeding(
- size_t totalEnumerated) const {
+bool PlanEnumerator::LockstepOrAssignment::shouldResetBeforeProceeding(size_t totalEnumerated,
+ size_t orLimit) const {
if (totalEnumerated == 0 || !exhaustedLockstepIteration) {
return false;
}
@@ -1700,7 +1700,12 @@ bool PlanEnumerator::LockstepOrAssignment::shouldResetBeforeProceeding(
if (!subnode.maxIterCount) {
return false; // Haven't yet looped over this child entirely, not ready yet.
}
- totalPossibleEnumerations *= subnode.maxIterCount.get();
+ 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;
+ }
}
// If we're able to compute a total number expected enumerations, we must have already cycled
@@ -1737,7 +1742,7 @@ bool PlanEnumerator::_nextMemoForLockstepOrAssignment(
}
// Edge case: if every child has only one option available, we are already finished
// enumerating.
- if (assignment->shouldResetBeforeProceeding(assignment->totalEnumerated)) {
+ if (assignment->shouldResetBeforeProceeding(assignment->totalEnumerated, _orLimit)) {
assignment->exhaustedLockstepIteration = false;
return true; // We're back at the beginning, no need to reset.
}
@@ -1776,7 +1781,7 @@ bool PlanEnumerator::_nextMemoForLockstepOrAssignment(
// 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)) {
+ if (!assignment->shouldResetBeforeProceeding(assignment->totalEnumerated, _orLimit)) {
return false;
}
// Reset!