diff options
author | David Storch <david.storch@10gen.com> | 2014-03-31 15:50:42 -0400 |
---|---|---|
committer | David Storch <david.storch@10gen.com> | 2014-03-31 18:19:20 -0400 |
commit | 67ec5c5b2926b682db1e21c22b1878043438827c (patch) | |
tree | 21add8df20c0f7503dff363094be3b9700987779 | |
parent | 7ac1d212730ad3b1d03b4f10f18e52fa42914c64 (diff) | |
download | mongo-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.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/query/query_planner_test.cpp | 32 |
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 // |