summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/query/index_bounds_builder.cpp8
-rw-r--r--src/mongo/db/query/index_bounds_builder.h9
-rw-r--r--src/mongo/db/query/interval_evaluation_tree.cpp3
-rw-r--r--src/mongo/db/query/planner_access.cpp12
-rw-r--r--src/mongo/db/query/planner_access.h2
-rw-r--r--src/mongo/db/query/planner_wildcard_helpers.cpp9
-rw-r--r--src/mongo/db/query/planner_wildcard_helpers.h4
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