diff options
Diffstat (limited to 'src/mongo/db/query/plan_enumerator.cpp')
| -rw-r--r-- | src/mongo/db/query/plan_enumerator.cpp | 15 |
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! |
