summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYunhe (John) Wang <yunhe.wang@mongodb.com>2015-09-17 16:41:27 -0400
committerDavid Storch <david.storch@10gen.com>2015-12-21 16:06:55 -0500
commit6d5a1ddf9333de4520a1303a02b2f1377e7fd622 (patch)
treed67b8946f78ae476608a03b303a29686b4a1cd10
parent3c60e3a9c1dfface8d0ceb3ca29ea34dd7411902 (diff)
downloadmongo-6d5a1ddf9333de4520a1303a02b2f1377e7fd622.tar.gz
SERVER-19996 Keep Mutations no longer added on ntoreturn hack
(cherry picked from commit e07a93a7ea6756434e0d3df38cdd1e6f5d5fd010) Conflicts: src/mongo/db/query/planner_analysis.cpp
-rw-r--r--src/mongo/db/query/planner_analysis.cpp13
-rw-r--r--src/mongo/db/query/query_planner_test.cpp15
2 files changed, 24 insertions, 4 deletions
diff --git a/src/mongo/db/query/planner_analysis.cpp b/src/mongo/db/query/planner_analysis.cpp
index 24a4e446b01..f21d8c79ca3 100644
--- a/src/mongo/db/query/planner_analysis.cpp
+++ b/src/mongo/db/query/planner_analysis.cpp
@@ -583,19 +583,24 @@ QuerySolution* QueryPlannerAnalysis::analyzeDataAccess(const CanonicalQuery& que
//
// 3. There is an index-provided sort. Ditto above comment about merging.
//
+ // 4. There is a SORT that is not at the root of solution tree. Ditto above comment about
+ // merging.
+ //
// TODO: do we want some kind of pre-planning step where we look for certain nodes and cache
// them? We do lookups in the tree a few times. This may not matter as most trees are
// shallow in terms of query nodes.
- bool cannotKeepFlagged = hasNode(solnRoot, STAGE_TEXT) ||
+ const bool hasNotRootSort = hasSortStage && STAGE_SORT != solnRoot->getType();
+
+ const bool cannotKeepFlagged = hasNode(solnRoot, STAGE_TEXT) ||
hasNode(solnRoot, STAGE_GEO_NEAR_2D) || hasNode(solnRoot, STAGE_GEO_NEAR_2DSPHERE) ||
- (!query.getParsed().getSort().isEmpty() && !hasSortStage);
+ (!query.getParsed().getSort().isEmpty() && !hasSortStage) || hasNotRootSort;
// Only these stages can produce flagged results. A stage has to hold state past one call
// to work(...) in order to possibly flag a result.
- bool couldProduceFlagged =
+ const bool couldProduceFlagged =
hasAndHashStage || hasNode(solnRoot, STAGE_AND_SORTED) || hasNode(solnRoot, STAGE_FETCH);
- bool shouldAddMutation = !cannotKeepFlagged && couldProduceFlagged;
+ const bool shouldAddMutation = !cannotKeepFlagged && couldProduceFlagged;
if (shouldAddMutation && (params.options & QueryPlannerParams::KEEP_MUTATIONS)) {
KeepMutationsNode* keep = new KeepMutationsNode();
diff --git a/src/mongo/db/query/query_planner_test.cpp b/src/mongo/db/query/query_planner_test.cpp
index d3378221acc..ee4b511f4e4 100644
--- a/src/mongo/db/query/query_planner_test.cpp
+++ b/src/mongo/db/query/query_planner_test.cpp
@@ -5423,6 +5423,21 @@ TEST_F(QueryPlannerTest, NoKeepWithIndexedSort) {
"[{ixscan: {pattern: {a: 1, b: 1}}}, {ixscan: {pattern: {a: 1, b: 1}}}]}}}}");
}
+// No KeepMutations when we have a sort that is not root, like the ntoreturn hack.
+TEST_F(QueryPlannerTest, NoKeepWithNToReturn) {
+ params.options = QueryPlannerParams::KEEP_MUTATIONS;
+ params.options |= QueryPlannerParams::SPLIT_LIMITED_SORT;
+ addIndex(BSON("a" << 1));
+ runQuerySortProjSkipLimit(fromjson("{a: 1}"), fromjson("{b: 1}"), BSONObj(), 0, 3);
+
+ assertSolutionExists(
+ "{or: {nodes: ["
+ "{sort: {pattern: {b: 1}, limit: 3, node: "
+ "{fetch: {node: {ixscan: {pattern: {a: 1}}}}}}}, "
+ "{sort: {pattern: {b: 1}, limit: 0, node: "
+ "{fetch: {node: {ixscan: {pattern: {a: 1}}}}}}}]}}");
+}
+
// Make sure a top-level $or hits the limiting number
// of solutions that we are willing to consider.
TEST_F(QueryPlannerTest, OrEnumerationLimit) {