diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/query/planner_analysis.cpp | 12 | ||||
-rw-r--r-- | src/mongo/db/query/query_planner_test.cpp | 31 |
2 files changed, 42 insertions, 1 deletions
diff --git a/src/mongo/db/query/planner_analysis.cpp b/src/mongo/db/query/planner_analysis.cpp index 23a45b3942d..24441a7a811 100644 --- a/src/mongo/db/query/planner_analysis.cpp +++ b/src/mongo/db/query/planner_analysis.cpp @@ -300,7 +300,17 @@ namespace mongo { // See if it's the order we're looking for. BSONObj possibleSort = resultingSortBob.obj(); if (!desiredSort.isPrefixOf(possibleSort)) { - return false; + // We can't get the sort order from the index scan. See if we can + // get the sort by reversing the scan. + BSONObj reversePossibleSort = QueryPlannerCommon::reverseSortObj(possibleSort); + if (!desiredSort.isPrefixOf(reversePossibleSort)) { + // Can't get the sort order from the reversed index scan either. Give up. + return false; + } + else { + // We can get the sort order we need if we reverse the scan. + QueryPlannerCommon::reverseScans(isn); + } } // Do some bookkeeping to see how many ixscans we'll create total. diff --git a/src/mongo/db/query/query_planner_test.cpp b/src/mongo/db/query/query_planner_test.cpp index 692dcdf6ff6..eab24dec88d 100644 --- a/src/mongo/db/query/query_planner_test.cpp +++ b/src/mongo/db/query/query_planner_test.cpp @@ -1650,6 +1650,37 @@ namespace { "{fetch: {node: {ixscan: {pattern: {a: 1, b: 1, c:1, d:1}}}}}}}"); } + // SERVER-13618: test that exploding scans for sort works even + // if we must reverse the scan direction. + TEST_F(QueryPlannerTest, ExplodeMustReverseScans) { + addIndex(BSON("a" << 1 << "b" << 1 << "c" << 1 << "d" << 1)); + runQuerySortProj(fromjson("{a: {$in: [1, 2]}, b: {$in: [3, 4]}}"), + BSON("c" << -1), BSONObj()); + + assertNumSolutions(2U); + assertSolutionExists("{sort: {pattern: {c: -1}, limit: 0, node: {cscan: {dir: 1}}}}"); + assertSolutionExists("{fetch: {node: {mergeSort: {nodes: " + "[{ixscan: {pattern: {a:1, b:1, c:1, d:1}}}," + "{ixscan: {pattern: {a:1, b:1, c:1, d:1}}}," + "{ixscan: {pattern: {a:1, b:1, c:1, d:1}}}," + "{ixscan: {pattern: {a:1, b:1, c:1, d:1}}}]}}}}"); + } + + // SERVER-13618 + TEST_F(QueryPlannerTest, ExplodeMustReverseScans2) { + addIndex(BSON("a" << 1 << "b" << 1 << "c" << -1)); + runQuerySortProj(fromjson("{a: {$in: [1, 2]}, b: {$in: [3, 4]}}"), + BSON("c" << 1), BSONObj()); + + assertNumSolutions(2U); + assertSolutionExists("{sort: {pattern: {c: 1}, limit: 0, node: {cscan: {dir: 1}}}}"); + assertSolutionExists("{fetch: {node: {mergeSort: {nodes: " + "[{ixscan: {pattern: {a:1, b:1, c:-1}}}," + "{ixscan: {pattern: {a:1, b:1, c:-1}}}," + "{ixscan: {pattern: {a:1, b:1, c:-1}}}," + "{ixscan: {pattern: {a:1, b:1, c:-1}}}]}}}}"); + } + TEST_F(QueryPlannerTest, InWithSortAndLimitTrailingField) { addIndex(BSON("a" << 1 << "b" << -1 << "c" << 1)); runQuerySortProjSkipLimit(fromjson("{a: {$in: [1, 2]}, b: {$gte: 0}}"), |