summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2014-03-31 15:50:42 -0400
committerDavid Storch <david.storch@10gen.com>2014-03-31 18:19:20 -0400
commit67ec5c5b2926b682db1e21c22b1878043438827c (patch)
tree21add8df20c0f7503dff363094be3b9700987779
parent7ac1d212730ad3b1d03b4f10f18e52fa42914c64 (diff)
downloadmongo-67ec5c5b2926b682db1e21c22b1878043438827c.tar.gz
SERVER-13422 fix planning bug for elemMatch object index intersection
(cherry picked from commit 58f603c00d7ef8372c4f412755e43dee7d7f5ac9)
-rw-r--r--src/mongo/db/query/planner_access.cpp6
-rw-r--r--src/mongo/db/query/query_planner_test.cpp32
2 files changed, 35 insertions, 3 deletions
diff --git a/src/mongo/db/query/planner_access.cpp b/src/mongo/db/query/planner_access.cpp
index 84082d0fcb8..5f9a06d5a8c 100644
--- a/src/mongo/db/query/planner_access.cpp
+++ b/src/mongo/db/query/planner_access.cpp
@@ -567,12 +567,12 @@ namespace mongo {
invariant(NULL != emChild->getTag());
IndexTag* innerTag = static_cast<IndexTag*>(emChild->getTag());
- if (NULL != currentScan.get() && (currentIndexNumber == ixtag->index) &&
+ if (NULL != currentScan.get() && (currentIndexNumber == innerTag->index) &&
shouldMergeWithLeaf(emChild, indices[currentIndexNumber], innerTag->pos,
currentScan.get(), root->matchType())) {
// The child uses the same index we're currently building a scan for. Merge
// the bounds and filters.
- verify(currentIndexNumber == ixtag->index);
+ verify(currentIndexNumber == innerTag->index);
IndexBoundsBuilder::BoundsTightness tightness = IndexBoundsBuilder::INEXACT_FETCH;
mergeWithLeafNode(emChild, indices[currentIndexNumber], innerTag->pos, &tightness,
@@ -597,7 +597,7 @@ namespace mongo {
verify(IndexTag::kNoIndex == currentIndexNumber);
}
- currentIndexNumber = ixtag->index;
+ currentIndexNumber = innerTag->index;
IndexBoundsBuilder::BoundsTightness tightness = IndexBoundsBuilder::INEXACT_FETCH;
currentScan.reset(makeLeafNode(query, indices[currentIndexNumber], innerTag->pos,
diff --git a/src/mongo/db/query/query_planner_test.cpp b/src/mongo/db/query/query_planner_test.cpp
index 1132e2bb533..ba5a4565977 100644
--- a/src/mongo/db/query/query_planner_test.cpp
+++ b/src/mongo/db/query/query_planner_test.cpp
@@ -2893,6 +2893,38 @@ namespace {
" 'a.e.d':[['MinKey','MaxKey',true,true]]}}}}}");
}
+ // SERVER-13422: check that we plan $elemMatch object correctly with
+ // index intersection.
+ TEST_F(QueryPlannerTest, ElemMatchIndexIntersection) {
+ params.options = QueryPlannerParams::NO_TABLE_SCAN | QueryPlannerParams::INDEX_INTERSECTION;
+ addIndex(BSON("shortId" << 1));
+ // true means multikey
+ addIndex(BSON("a.b.startDate" << 1), true);
+ addIndex(BSON("a.b.endDate" << 1), true);
+
+ runQuery(fromjson("{shortId: 3, 'a.b': {$elemMatch: {startDate: {$lte: 3},"
+ "endDate: {$gt: 6}}}}"));
+
+ assertNumSolutions(6U);
+
+ // 3 single index solutions.
+ assertSolutionExists("{fetch: {node: {ixscan: {pattern: {shortId: 1}}}}}");
+ assertSolutionExists("{fetch: {node: {ixscan: {pattern: {'a.b.startDate': 1}}}}}");
+ assertSolutionExists("{fetch: {node: {ixscan: {pattern: {'a.b.endDate': 1}}}}}");
+
+ // 3 index intersection solutions. The last one has to intersect two
+ // predicates within the $elemMatch object.
+ assertSolutionExists("{fetch: {node: {andHash: {nodes: ["
+ "{ixscan: {pattern: {shortId: 1}}},"
+ "{ixscan: {pattern: {'a.b.startDate': 1}}}]}}}}");
+ assertSolutionExists("{fetch: {node: {andHash: {nodes: ["
+ "{ixscan: {pattern: {shortId: 1}}},"
+ "{ixscan: {pattern: {'a.b.endDate': 1}}}]}}}}");
+ assertSolutionExists("{fetch: {node: {andHash: {nodes: ["
+ "{ixscan: {pattern: {'a.b.startDate': 1}}},"
+ "{ixscan: {pattern: {'a.b.endDate': 1}}}]}}}}");
+ }
+
//
// QueryPlannerParams option tests
//