summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2014-04-17 10:19:46 -0400
committerDan Pasette <dan@mongodb.com>2014-04-17 13:26:47 -0400
commiteeef3c3ded2d8d55345af8b11041bafae8783958 (patch)
tree9007f5f8988e8accd56718c7d1cf55eac143fbb4
parenta093bfa703c4a63fb26b1bc16c0f6ae13261486e (diff)
downloadmongo-eeef3c3ded2d8d55345af8b11041bafae8783958.tar.gz
SERVER-13618 explode for sort tries reversing index scan direction
(cherry picked from commit ce52f313ca52759d606886641f44541bd7baf5bd)
-rw-r--r--src/mongo/db/query/planner_analysis.cpp12
-rw-r--r--src/mongo/db/query/query_planner_test.cpp31
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}}"),