summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Boros <ian.boros@10gen.com>2018-09-13 18:08:53 -0400
committerIan Boros <ian.boros@10gen.com>2018-09-17 18:46:38 -0400
commit590fdc69d78ecbca005381781a9e520bd023a43d (patch)
treeca9f0fc4d29a9ae665c974d90bcb697680a37749
parent0780841a51470b33105ec2b0a7831531b82d0a8d (diff)
downloadmongo-590fdc69d78ecbca005381781a9e520bd023a43d.tar.gz
SERVER-36945 Tests for allPaths indexes not supporting negations
-rw-r--r--src/mongo/db/query/query_planner_all_paths_index_test.cpp35
-rw-r--r--src/mongo/db/query/query_planner_test.cpp28
2 files changed, 63 insertions, 0 deletions
diff --git a/src/mongo/db/query/query_planner_all_paths_index_test.cpp b/src/mongo/db/query/query_planner_all_paths_index_test.cpp
index 7ea870083f8..bed49a69514 100644
--- a/src/mongo/db/query/query_planner_all_paths_index_test.cpp
+++ b/src/mongo/db/query/query_planner_all_paths_index_test.cpp
@@ -767,6 +767,41 @@ TEST_F(QueryPlannerAllPathsTest, AllPathsIndexDoesNotSupplyCandidatePlanForTextS
"{fetch: {filter: {b: 10}, node: {text: {prefix: {a: 10}, search: 'banana'}}}}");
}
+TEST_F(QueryPlannerAllPathsTest, AllPathsDoesNotSupportNegationPredicate) {
+ // AllPaths indexes can't support negation queries because they are sparse, and {a: {$ne: 5}}
+ // will match documents which don't have an "a" field.
+ addAllPathsIndex(BSON("$**" << 1));
+ runQuery(fromjson("{a: {$ne: 5}}"));
+ assertHasOnlyCollscan();
+
+ runQuery(fromjson("{a: {$not: {$gt: 3, $lt: 5}}}"));
+ assertHasOnlyCollscan();
+}
+
+TEST_F(QueryPlannerAllPathsTest,
+ AllPathsDoesNotSupportNegationPredicateInsideElemMatchMultiKeyPath) {
+ // Logically, there's no reason a (sparse) allPaths index could not support a negation inside a
+ // "$elemMatch value", but it is not something we've implemented.
+ addAllPathsIndex(BSON("$**" << 1), {"a"});
+ runQuery(fromjson("{a: {$elemMatch: {$ne: 5}}}"));
+ assertHasOnlyCollscan();
+
+ runQuery(fromjson("{a: {$elemMatch: {$not: {$gt: 3, $lt: 5}}}}"));
+ assertHasOnlyCollscan();
+}
+
+TEST_F(QueryPlannerAllPathsTest, AllPathsDoesNotSupportNegationPredicateInsideElemMatch) {
+ // Test the case where we use $elemMatch on a path which isn't even multikey. In this case,
+ // we'd know up front that the results would be empty, but this is not an optimization we
+ // support.
+ addAllPathsIndex(BSON("$**" << 1));
+ runQuery(fromjson("{a: {$elemMatch: {$ne: 5}}}"));
+ assertHasOnlyCollscan();
+
+ runQuery(fromjson("{a: {$elemMatch: {$not: {$gt: 3, $lt: 5}}}}"));
+ assertHasOnlyCollscan();
+}
+
// TODO SERVER-35335: Add testing for Min/Max.
// TODO SERVER-36517: Add testing for DISTINCT_SCAN.
// TODO SERVER-35331: Add testing for hints.
diff --git a/src/mongo/db/query/query_planner_test.cpp b/src/mongo/db/query/query_planner_test.cpp
index 8acccd4da85..2fc05b9f918 100644
--- a/src/mongo/db/query/query_planner_test.cpp
+++ b/src/mongo/db/query/query_planner_test.cpp
@@ -2528,6 +2528,34 @@ TEST_F(QueryPlannerTest, ExprEqCanUseSparseIndexForEqualityToNull) {
"{a: 1}, bounds: {a: [[undefined,undefined,true,true], [null,null,true,true]]}}}}}");
}
+TEST_F(QueryPlannerTest, NegationCannotUseSparseIndex) {
+ // Sparse indexes can't support negation queries because they are sparse, and {a: {$ne: 5}}
+ // will match documents which don't have an "a" field.
+ addIndex(fromjson("{a: 1}"),
+ false, // multikey
+ true // sparse
+ );
+ runQuery(fromjson("{a: {$ne: 5}}"));
+ assertHasOnlyCollscan();
+
+ runQuery(fromjson("{a: {$not: {$gt: 3, $lt: 5}}}"));
+ assertHasOnlyCollscan();
+}
+
+TEST_F(QueryPlannerTest, NegationInElemMatchDoesNotUseSparseIndex) {
+ // Logically, there's no reason a sparse index could not support a negation inside a
+ // "$elemMatch value", but it is not something we've implemented.
+ addIndex(fromjson("{a: 1}"),
+ true, // multikey
+ true // sparse
+ );
+ runQuery(fromjson("{a: {$elemMatch: {$ne: 5}}}"));
+ assertHasOnlyCollscan();
+
+ runQuery(fromjson("{a: {$elemMatch: {$not: {$gt: 3, $lt: 5}}}}"));
+ assertHasOnlyCollscan();
+}
+
//
// Regex
//