summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2015-03-03 15:07:06 -0500
committerDavid Storch <david.storch@10gen.com>2015-03-05 12:31:06 -0500
commit5f889dfec4c625af3413348cdc9b409998d33238 (patch)
treebd68a36c3e89e77099695e1a597e5ef6bf1a1b9a /src
parentff64c70f6994520827dceeaf4c82c7061ff10b8c (diff)
downloadmongo-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.cpp16
-rw-r--r--src/mongo/db/query/plan_enumerator.h5
-rw-r--r--src/mongo/db/query/query_planner_test.cpp13
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"));