diff options
author | Max Hirschhorn <max.hirschhorn@mongodb.com> | 2016-05-08 14:16:24 -0400 |
---|---|---|
committer | Max Hirschhorn <max.hirschhorn@mongodb.com> | 2016-05-08 14:16:24 -0400 |
commit | 65222c4b5146cc6b8930e784149e5aade132a8fc (patch) | |
tree | d5be9207ce18b8ee179571d3db5d4ac480eaf404 | |
parent | d32ecd37d47aba04636d8dda335ecbbad82307e5 (diff) | |
download | mongo-65222c4b5146cc6b8930e784149e5aade132a8fc.tar.gz |
SERVER-22726 Represent lack of path-level multikey info as empty vector.
Removes usages of boost::optional<MultikeyPaths>, where boost::none had
previously represented the lack of path-level multikey info.
-rw-r--r-- | src/mongo/db/index/multikey_paths.h | 8 | ||||
-rw-r--r-- | src/mongo/db/query/index_entry.h | 7 | ||||
-rw-r--r-- | src/mongo/db/query/plan_enumerator.cpp | 23 |
3 files changed, 22 insertions, 16 deletions
diff --git a/src/mongo/db/index/multikey_paths.h b/src/mongo/db/index/multikey_paths.h index 7f0eb2e0b6a..794c9478093 100644 --- a/src/mongo/db/index/multikey_paths.h +++ b/src/mongo/db/index/multikey_paths.h @@ -34,12 +34,14 @@ namespace mongo { -// A vector with size equal to the number of elements in the index key pattern. Each element in -// the vector is an ordered set of positions (starting at 0) into the corresponding indexed -// field that represent what prefixes of the indexed field causes the index to be multikey. +// If non-empty, a vector with size equal to the number of elements in the index key pattern. Each +// element in the vector is an ordered set of positions (starting at 0) into the corresponding +// indexed field that represent what prefixes of the indexed field cause the index to be multikey. // // For example, with the index {'a.b': 1, 'a.c': 1} where the paths "a" and "a.b" cause the // index to be multikey, we'd have a std::vector<std::set<size_t>>{{0U, 1U}, {0U}}. +// +// An empty vector is used to represent that the index doesn't support path-level multikey tracking. using MultikeyPaths = std::vector<std::set<std::size_t>>; } // namespace mongo diff --git a/src/mongo/db/query/index_entry.h b/src/mongo/db/query/index_entry.h index 7b336515954..185b7ae6bed 100644 --- a/src/mongo/db/query/index_entry.h +++ b/src/mongo/db/query/index_entry.h @@ -28,7 +28,6 @@ #pragma once -#include <boost/optional.hpp> #include <string> #include "mongo/db/index/multikey_paths.h" @@ -106,7 +105,11 @@ struct IndexEntry { bool multikey; - boost::optional<MultikeyPaths> multikeyPaths; + // If non-empty, 'multikeyPaths' is a vector with size equal to the number of elements in the + // index key pattern. Each element in the vector is an ordered set of positions (starting at 0) + // into the corresponding indexed field that represent what prefixes of the indexed field cause + // the index to be multikey. + MultikeyPaths multikeyPaths; bool sparse; diff --git a/src/mongo/db/query/plan_enumerator.cpp b/src/mongo/db/query/plan_enumerator.cpp index 8a135e89c5d..c6fe53a1c37 100644 --- a/src/mongo/db/query/plan_enumerator.cpp +++ b/src/mongo/db/query/plan_enumerator.cpp @@ -91,10 +91,9 @@ using PossibleFirstAssignment = std::vector<MatchExpression*>; void getPossibleFirstAssignments(const IndexEntry& thisIndex, const vector<MatchExpression*>& predsOverLeadingField, std::vector<PossibleFirstAssignment>* possibleFirstAssignments) { - invariant(thisIndex.multikey && thisIndex.multikeyPaths); - const auto& multikeyPaths = *thisIndex.multikeyPaths; + invariant(thisIndex.multikey && !thisIndex.multikeyPaths.empty()); - if (multikeyPaths[0].empty()) { + if (thisIndex.multikeyPaths[0].empty()) { // No prefix of the leading index field causes the index to be multikey. In other words, the // index isn't multikey as a result of the leading index field. We can then safely assign // all predicates on it to the index and the access planner will intersect the bounds. @@ -140,7 +139,8 @@ void getPossibleFirstAssignments(const IndexEntry& thisIndex, // Since the multikey path components are 0-indexed, 'elemMatchRootLength' actually // corresponds to the path component immediately following the root of the $elemMatch. - if (multikeyPaths[0].lower_bound(elemMatchRootLength) == multikeyPaths[0].end()) { + if (thisIndex.multikeyPaths[0].lower_bound(elemMatchRootLength) == + thisIndex.multikeyPaths[0].end()) { // The root of the $elemMatch is the longest prefix of the leading index field that // causes the index to be multikey, so we can assign all of the leaf expressions in the // $elemMatch to the index. @@ -615,7 +615,7 @@ bool PlanEnumerator::enumerateMandatoryIndex(const IndexToPredMap& idxToFirst, const vector<MatchExpression*>& predsOverLeadingField = it->second; - if (thisIndex.multikey && thisIndex.multikeyPaths) { + if (thisIndex.multikey && !thisIndex.multikeyPaths.empty()) { // 2dsphere indexes are the only special index type that should ever have path-level // multikey information. invariant(INDEX_2DSPHERE == thisIndex.type); @@ -794,7 +794,7 @@ void PlanEnumerator::enumerateOneIndex(const IndexToPredMap& idxToFirst, for (IndexToPredMap::const_iterator it = idxToFirst.begin(); it != idxToFirst.end(); ++it) { const IndexEntry& thisIndex = (*_indices)[it->first]; - if (thisIndex.multikey && thisIndex.multikeyPaths) { + if (thisIndex.multikey && !thisIndex.multikeyPaths.empty()) { // We have path-level information about what causes 'thisIndex' to be multikey and can // use this information to get tighter bounds by assigning additional predicates to the // index. @@ -1292,8 +1292,7 @@ void PlanEnumerator::assignMultikeySafePredicates(const std::vector<MatchExpress invariant(indexAssignment->preds.size() == indexAssignment->positions.size()); const IndexEntry& thisIndex = (*_indices)[indexAssignment->index]; - invariant(thisIndex.multikeyPaths); - const auto& multikeyPaths = *thisIndex.multikeyPaths; + invariant(!thisIndex.multikeyPaths.empty()); // 'used' is a map from each prefix of a queried path that causes 'thisIndex' to be multikey to // the 'elemMatchExpr' of the associated leaf expression's RelevantTag. We use it to ensure that @@ -1311,7 +1310,8 @@ void PlanEnumerator::assignMultikeySafePredicates(const std::vector<MatchExpress // 'assignedPred' has already been assigned to 'thisIndex', so canAssignPredToIndex() ought // to return true. - const bool shouldHaveAssigned = canAssignPredToIndex(rt, multikeyPaths[posInIdx], &used); + const bool shouldHaveAssigned = + canAssignPredToIndex(rt, thisIndex.multikeyPaths[posInIdx], &used); if (!shouldHaveAssigned) { // However, there are cases with multikey 2dsphere indexes where the mandatory predicate // is still safe to compound with, even though a prefix of it that causes the index to @@ -1335,7 +1335,7 @@ void PlanEnumerator::assignMultikeySafePredicates(const std::vector<MatchExpress continue; } - if (multikeyPaths[posInIdx].empty()) { + if (thisIndex.multikeyPaths[posInIdx].empty()) { // We can always intersect or compound the bounds when no prefix of the queried path // causes the index to be multikey. indexAssignment->preds.push_back(couldAssignPred); @@ -1345,7 +1345,8 @@ void PlanEnumerator::assignMultikeySafePredicates(const std::vector<MatchExpress // See if any of the predicates that are already assigned to 'thisIndex' prevent us from // assigning 'couldAssignPred' as well. - const bool shouldAssign = canAssignPredToIndex(rt, multikeyPaths[posInIdx], &used); + const bool shouldAssign = + canAssignPredToIndex(rt, thisIndex.multikeyPaths[posInIdx], &used); if (shouldAssign) { indexAssignment->preds.push_back(couldAssignPred); |