diff options
author | David Storch <david.storch@10gen.com> | 2015-03-03 15:07:06 -0500 |
---|---|---|
committer | David Storch <david.storch@10gen.com> | 2015-03-05 12:31:06 -0500 |
commit | 5f889dfec4c625af3413348cdc9b409998d33238 (patch) | |
tree | bd68a36c3e89e77099695e1a597e5ef6bf1a1b9a /src | |
parent | ff64c70f6994520827dceeaf4c82c7061ff10b8c (diff) | |
download | mongo-5f889dfec4c625af3413348cdc9b409998d33238.tar.gz |
SERVER-14723 fix crash in plan enumerator affecting some geo near queries
(cherry picked from commit 965cbef869f8b864caaf3bf7705f8bd82c2b81ba)
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/query/plan_enumerator.cpp | 16 | ||||
-rw-r--r-- | src/mongo/db/query/plan_enumerator.h | 5 | ||||
-rw-r--r-- | src/mongo/db/query/query_planner_test.cpp | 13 |
3 files changed, 29 insertions, 5 deletions
diff --git a/src/mongo/db/query/plan_enumerator.cpp b/src/mongo/db/query/plan_enumerator.cpp index 8ffc11c0ce0..ec8c8dac4a0 100644 --- a/src/mongo/db/query/plan_enumerator.cpp +++ b/src/mongo/db/query/plan_enumerator.cpp @@ -408,9 +408,8 @@ namespace mongo { if (NULL != mandatoryPred) { // We must have at least one index which can be used to answer 'mandatoryPred'. invariant(!mandatoryIndices.empty()); - enumerateMandatoryIndex(idxToFirst, idxToNotFirst, mandatoryPred, - mandatoryIndices, andAssignment); - return true; + return enumerateMandatoryIndex(idxToFirst, idxToNotFirst, mandatoryPred, + mandatoryIndices, andAssignment); } enumerateOneIndex(idxToFirst, idxToNotFirst, subnodes, andAssignment); @@ -426,7 +425,7 @@ namespace mongo { return false; } - void PlanEnumerator::enumerateMandatoryIndex(const IndexToPredMap& idxToFirst, + bool PlanEnumerator::enumerateMandatoryIndex(const IndexToPredMap& idxToFirst, const IndexToPredMap& idxToNotFirst, MatchExpression* mandatoryPred, const set<IndexID>& mandatoryIndices, @@ -453,6 +452,13 @@ namespace mongo { indexAssign.index = *indexIt; IndexToPredMap::const_iterator it = idxToFirst.find(*indexIt); + if (idxToFirst.end() == it) { + // We don't have any predicate to assign to the leading field of this index. + // This means that we cannot generate a solution using this index, so we + // just move on to the next index. + continue; + } + const vector<MatchExpression*>& predsOverLeadingField = it->second; if (thisIndex.multikey) { @@ -540,6 +546,8 @@ namespace mongo { state.assignments.push_back(indexAssign); andAssignment->choices.push_back(state); } + + return andAssignment->choices.size() > 0; } void PlanEnumerator::enumerateOneIndex(const IndexToPredMap& idxToFirst, diff --git a/src/mongo/db/query/plan_enumerator.h b/src/mongo/db/query/plan_enumerator.h index 8cccbab61c8..bd3f9c0a534 100644 --- a/src/mongo/db/query/plan_enumerator.h +++ b/src/mongo/db/query/plan_enumerator.h @@ -388,8 +388,11 @@ namespace mongo { * Generate single-index assignments for queries which contain mandatory * predicates (TEXT and GEO_NEAR, which are required to use a compatible index). * Outputs these assignments into 'andAssignment'. + * + * Returns true if it generated at least one assignment, and false if no assignment + * of 'mandatoryPred' is possible. */ - void enumerateMandatoryIndex(const IndexToPredMap& idxToFirst, + bool enumerateMandatoryIndex(const IndexToPredMap& idxToFirst, const IndexToPredMap& idxToNotFirst, MatchExpression* mandatoryPred, const set<IndexID>& mandatoryIndices, diff --git a/src/mongo/db/query/query_planner_test.cpp b/src/mongo/db/query/query_planner_test.cpp index 808b1aba7cf..c98ea321d66 100644 --- a/src/mongo/db/query/query_planner_test.cpp +++ b/src/mongo/db/query/query_planner_test.cpp @@ -1908,6 +1908,19 @@ namespace { assertSolutionExists("{fetch: {node: {ixscan: {pattern: {x: 1, a: '2dsphere'}}}}}"); } + // SERVER-14723 + TEST_F(QueryPlannerTest, GeoNearMultipleRelevantIndicesButOnlyOneCompatible) { + addIndex(BSON("a" << "2dsphere")); + addIndex(BSON("b" << 1 << "a" << "2dsphere")); + + runQuery(fromjson("{a: {$nearSphere: {$geometry: {type: 'Point', coordinates: [0,0]}}}," + " b: {$exists: false}}")); + + assertNumSolutions(1U); + assertSolutionExists("{fetch: {filter: {b: {$exists: false}}, node: " + "{geoNear2dsphere: {a: '2dsphere'}}}}"); + } + // SERVER-3984, $or 2d index TEST_F(QueryPlannerTest, Or2DNonNear) { addIndex(BSON("a" << "2d")); |