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.cpp29
1 files changed, 22 insertions, 7 deletions
diff --git a/src/mongo/db/query/plan_enumerator.cpp b/src/mongo/db/query/plan_enumerator.cpp
index 4f15905dc6d..9ad6f6b81aa 100644
--- a/src/mongo/db/query/plan_enumerator.cpp
+++ b/src/mongo/db/query/plan_enumerator.cpp
@@ -35,6 +35,7 @@
#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"
@@ -58,8 +59,8 @@ std::string getPathPrefix(std::string path) {
* is a predicate that is required to use an index.
*/
bool expressionRequiresIndex(const MatchExpression* node) {
- return CanonicalQuery::countNodes(node, MatchExpression::GEO_NEAR) > 0 ||
- CanonicalQuery::countNodes(node, MatchExpression::TEXT) > 0;
+ return QueryPlannerCommon::countNodes(node, MatchExpression::GEO_NEAR) > 0 ||
+ QueryPlannerCommon::countNodes(node, MatchExpression::TEXT) > 0;
}
size_t getPathLength(const MatchExpression* expr) {
@@ -261,7 +262,8 @@ PlanEnumerator::PlanEnumerator(const PlanEnumeratorParams& params)
_ixisect(params.intersect),
_enumerateOrChildrenLockstep(params.enumerateOrChildrenLockstep),
_orLimit(params.maxSolutionsPerOr),
- _intersectLimit(params.maxIntersectPerAnd) {}
+ _intersectLimit(params.maxIntersectPerAnd),
+ _disableOrPushdown(params.disableOrPushdown) {}
PlanEnumerator::~PlanEnumerator() {
typedef stdx::unordered_map<MemoID, NodeAssignment*> MemoMap;
@@ -528,10 +530,14 @@ bool PlanEnumerator::prepMemo(MatchExpression* node, PrepMemoContext context) {
// preds to 'indexedPreds'. Adding the mandatory preds directly to 'indexedPreds' would lead
// to problems such as pulling a predicate beneath an OR into a set joined by an AND.
getIndexedPreds(node, childContext, &indexedPreds);
- // Pass in the indexed predicates as outside predicates when prepping the subnodes.
+ // Pass in the indexed predicates as outside predicates when prepping the subnodes. But if
+ // match expression optimization is disabled, skip this part: we don't want to do
+ // OR-pushdown because it relies on the expression being canonicalized.
auto childContextCopy = childContext;
- for (auto pred : indexedPreds) {
- childContextCopy.outsidePreds[pred] = OutsidePredRoute{};
+ if (MONGO_likely(!_disableOrPushdown)) {
+ for (auto pred : indexedPreds) {
+ childContextCopy.outsidePreds[pred] = OutsidePredRoute{};
+ }
}
if (!prepSubNodes(node, childContextCopy, &subnodes, &mandatorySubnodes)) {
return false;
@@ -835,6 +841,13 @@ void PlanEnumerator::assignPredicate(
MatchExpression* pred,
size_t position,
OneIndexAssignment* indexAssignment) {
+ if (MONGO_unlikely(_disableOrPushdown)) {
+ // If match expression optimization is disabled, we also disable OR-pushdown,
+ // so we should never get 'outsidePreds' here.
+ tassert(7059700,
+ "Tried to do OR-pushdown despite disableMatchExpressionOptimization",
+ outsidePreds.empty());
+ }
if (outsidePreds.find(pred) != outsidePreds.end()) {
OrPushdownTag::Destination dest;
dest.route = outsidePreds.at(pred).route;
@@ -1289,6 +1302,8 @@ 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
@@ -1305,7 +1320,7 @@ void PlanEnumerator::getIndexedPreds(MatchExpression* node,
indexedPreds->push_back(node);
} else if (Indexability::isBoundsGeneratingNot(node)) {
getIndexedPreds(node->getChild(0), context, indexedPreds);
- } else if (MatchExpression::ELEM_MATCH_OBJECT == node->matchType()) {
+ } else if (Indexability::isBoundsGeneratingElemMatchObject(node)) {
PrepMemoContext childContext;
childContext.elemMatchExpr = node;
for (size_t i = 0; i < node->numChildren(); ++i) {