diff options
-rw-r--r-- | src/mongo/db/query/index_bounds_builder.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/query/index_bounds_builder.h | 9 | ||||
-rw-r--r-- | src/mongo/db/query/interval_evaluation_tree.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/query/planner_access.cpp | 12 | ||||
-rw-r--r-- | src/mongo/db/query/planner_access.h | 2 | ||||
-rw-r--r-- | src/mongo/db/query/planner_wildcard_helpers.cpp | 9 | ||||
-rw-r--r-- | src/mongo/db/query/planner_wildcard_helpers.h | 4 |
7 files changed, 36 insertions, 11 deletions
diff --git a/src/mongo/db/query/index_bounds_builder.cpp b/src/mongo/db/query/index_bounds_builder.cpp index c347944fb3c..bd82140b5c1 100644 --- a/src/mongo/db/query/index_bounds_builder.cpp +++ b/src/mongo/db/query/index_bounds_builder.cpp @@ -409,6 +409,14 @@ void IndexBoundsBuilder::translate(const MatchExpression* expr, } } +void IndexBoundsBuilder::translate(const MatchExpression* expr, + const BSONElement& elt, + const IndexEntry& index, + OrderedIntervalList* oilOut) { + BoundsTightness tightnessOut; + _translatePredicate(expr, elt, index, oilOut, &tightnessOut, /*ietBuilder*/ nullptr); +} + namespace { IndexBoundsBuilder::BoundsTightness computeTightnessForTypeSet(const MatcherTypeSet& typeSet, const IndexEntry& index) { diff --git a/src/mongo/db/query/index_bounds_builder.h b/src/mongo/db/query/index_bounds_builder.h index 9e152bf1a42..b48228328f5 100644 --- a/src/mongo/db/query/index_bounds_builder.h +++ b/src/mongo/db/query/index_bounds_builder.h @@ -116,6 +116,15 @@ public: interval_evaluation_tree::Builder* ietBuilder); /** + * Turn the MatchExpression in 'expr' into a set of index bounds. The field that 'expr' is + * concerned with is indexed according to the keypattern element 'elt' from index 'index'. This + * function is used to evaluate index bounds from cached Interval Evaluation Trees. + */ + static void translate(const MatchExpression* expr, + const BSONElement& elt, + const IndexEntry& index, + OrderedIntervalList* oilOut); + /** * Creates bounds for 'expr' (indexed according to 'elt'). Intersects those bounds * with the bounds in oilOut, which is an in/out parameter. * diff --git a/src/mongo/db/query/interval_evaluation_tree.cpp b/src/mongo/db/query/interval_evaluation_tree.cpp index 712e6359b96..a2aae88c066 100644 --- a/src/mongo/db/query/interval_evaluation_tree.cpp +++ b/src/mongo/db/query/interval_evaluation_tree.cpp @@ -157,8 +157,7 @@ public: auto expr = _inputParamIdMap[node.inputParamId()]; OrderedIntervalList oil{}; - IndexBoundsBuilder::BoundsTightness tightness; - IndexBoundsBuilder::translate(expr, _elt, _index, &oil, &tightness, nullptr); + IndexBoundsBuilder::translate(expr, _elt, _index, &oil); return oil; } diff --git a/src/mongo/db/query/planner_access.cpp b/src/mongo/db/query/planner_access.cpp index 58d85e5f0cf..caf77f4847c 100644 --- a/src/mongo/db/query/planner_access.cpp +++ b/src/mongo/db/query/planner_access.cpp @@ -907,7 +907,7 @@ void QueryPlannerAccess::finishAndOutputLeaf(ScanBuildingState* scanState, vector<std::unique_ptr<QuerySolutionNode>>* out) { finishLeafNode(scanState->currentScan.get(), scanState->indices[scanState->currentIndexNumber], - scanState->ietBuilders); + std::move(scanState->ietBuilders)); if (MatchExpression::OR == scanState->root->matchType()) { if (orNeedsFetch(scanState)) { @@ -941,7 +941,7 @@ void QueryPlannerAccess::finishAndOutputLeaf(ScanBuildingState* scanState, void QueryPlannerAccess::finishLeafNode( QuerySolutionNode* node, const IndexEntry& index, - const std::vector<interval_evaluation_tree::Builder>& ietBuilders) { + std::vector<interval_evaluation_tree::Builder> ietBuilders) { const StageType type = node->getType(); if (STAGE_TEXT_MATCH == type) { @@ -967,7 +967,7 @@ void QueryPlannerAccess::finishLeafNode( // If this is a $** index, update and populate the keyPattern, bounds, and multikeyPaths. if (index.type == IndexType::INDEX_WILDCARD) { - wcp::finalizeWildcardIndexScanConfiguration(scan); + wcp::finalizeWildcardIndexScanConfiguration(scan, &ietBuilders); } } @@ -1357,9 +1357,9 @@ bool QueryPlannerAccess::processIndexScansElemMatch( verify(IndexTag::kNoIndex == scanState->currentIndexNumber); } - scanState->currentIndexNumber = scanState->ixtag->index; + // Reset state before producing a new leaf. + scanState->resetForNextScan(scanState->ixtag, query.isParameterized()); - scanState->tightness = IndexBoundsBuilder::INEXACT_FETCH; scanState->currentScan = makeLeafNode(query, indices[scanState->currentIndexNumber], scanState->ixtag->pos, @@ -1668,7 +1668,7 @@ std::unique_ptr<QuerySolutionNode> QueryPlannerAccess::_buildIndexedDataAccess( auto soln = makeLeafNode(query, index, tag->pos, root, &tightness, ietBuilder); verify(nullptr != soln); - finishLeafNode(soln.get(), index, ietBuilders); + finishLeafNode(soln.get(), index, std::move(ietBuilders)); if (!ownedRoot) { // We're performing access planning for the child of an array operator such as diff --git a/src/mongo/db/query/planner_access.h b/src/mongo/db/query/planner_access.h index 675915a3aa5..aff81f57b4e 100644 --- a/src/mongo/db/query/planner_access.h +++ b/src/mongo/db/query/planner_access.h @@ -392,7 +392,7 @@ private: */ static void finishLeafNode(QuerySolutionNode* node, const IndexEntry& index, - const std::vector<interval_evaluation_tree::Builder>& ietBuilders); + std::vector<interval_evaluation_tree::Builder> ietBuilders); /** * Fills in any missing bounds by calling finishLeafNode(...) for the scan contained in diff --git a/src/mongo/db/query/planner_wildcard_helpers.cpp b/src/mongo/db/query/planner_wildcard_helpers.cpp index a829a460aa6..954882006bc 100644 --- a/src/mongo/db/query/planner_wildcard_helpers.cpp +++ b/src/mongo/db/query/planner_wildcard_helpers.cpp @@ -449,7 +449,8 @@ BoundsTightness translateWildcardIndexBoundsAndTightness(const IndexEntry& index return (arrayIndicesTraversedByQuery.empty() ? tightnessIn : BoundsTightness::INEXACT_FETCH); } -void finalizeWildcardIndexScanConfiguration(IndexScanNode* scan) { +void finalizeWildcardIndexScanConfiguration( + IndexScanNode* scan, std::vector<interval_evaluation_tree::Builder>* ietBuilders) { IndexEntry* index = &scan->index; IndexBounds* bounds = &scan->bounds; @@ -459,6 +460,9 @@ void finalizeWildcardIndexScanConfiguration(IndexScanNode* scan) { invariant(index->multikeyPaths.size() == 1); invariant(bounds && bounds->fields.size() == 1); invariant(bounds->fields.front().name == index->keyPattern.firstElementFieldName()); + tassert(6536700, + "IET Builders list must be size of 1 or empty for wildcard indexes", + ietBuilders->empty() || ietBuilders->size() == 1); // For $** indexes, the IndexEntry key pattern is {'path.to.field': ±1} but the actual keys in // the index are of the form {'$_path': ±1, 'path.to.field': ±1}, where the value of the first @@ -469,6 +473,9 @@ void finalizeWildcardIndexScanConfiguration(IndexScanNode* scan) { bounds->fields.insert(bounds->fields.begin(), {"$_path"}); index->keyPattern = BSON("$_path" << index->keyPattern.firstElement() << index->keyPattern.firstElement()); + if (!ietBuilders->empty()) { + ietBuilders->emplace(ietBuilders->begin()); + } // Create a FieldRef to perform any necessary manipulations on the query path string. FieldRef queryPath{std::next(index->keyPattern.begin())->fieldNameStringData()}; diff --git a/src/mongo/db/query/planner_wildcard_helpers.h b/src/mongo/db/query/planner_wildcard_helpers.h index d152ce18cd2..807b09e7373 100644 --- a/src/mongo/db/query/planner_wildcard_helpers.h +++ b/src/mongo/db/query/planner_wildcard_helpers.h @@ -33,6 +33,7 @@ #include "mongo/db/index/multikey_paths.h" #include "mongo/db/query/index_bounds_builder.h" #include "mongo/db/query/index_entry.h" +#include "mongo/db/query/interval_evaluation_tree.h" #include "mongo/db/query/query_solution.h" namespace mongo { @@ -74,7 +75,8 @@ BoundsTightness translateWildcardIndexBoundsAndTightness(const IndexEntry& index * - Adds a new, empty entry to 'multikeyPaths' for '$_path'. * - Updates shouldDedup for index scan node. */ -void finalizeWildcardIndexScanConfiguration(IndexScanNode* scan); +void finalizeWildcardIndexScanConfiguration( + IndexScanNode* scan, std::vector<interval_evaluation_tree::Builder>* ietBuilders); /** * Returns true if the given IndexScanNode is a $** scan whose bounds overlap the object type |