summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2014-05-09 13:55:49 -0400
committerDan Pasette <dan@mongodb.com>2014-05-15 20:21:08 -0400
commitf076d57d427e7fde945303aaec32ba594de5872c (patch)
tree0b8b21b69a69c0d2950956fbc486e8bd5abe43db
parent2cebdd054c5f1686179e5a2db1ea46adf6670f37 (diff)
downloadmongo-f076d57d427e7fde945303aaec32ba594de5872c.tar.gz
SERVER-13890 index bounds builder should not pass already-constructed intervals to translate()
(cherry picked from commit d19801d6209d6635e4fb9c42245723f1f1869bf0)
-rw-r--r--src/mongo/db/query/index_bounds_builder.cpp12
-rw-r--r--src/mongo/db/query/index_bounds_builder_test.cpp15
-rw-r--r--src/mongo/db/query/query_planner_test.cpp12
3 files changed, 38 insertions, 1 deletions
diff --git a/src/mongo/db/query/index_bounds_builder.cpp b/src/mongo/db/query/index_bounds_builder.cpp
index 71367e21488..0aff65e317b 100644
--- a/src/mongo/db/query/index_bounds_builder.cpp
+++ b/src/mongo/db/query/index_bounds_builder.cpp
@@ -197,7 +197,14 @@ namespace mongo {
const IndexEntry& index,
OrderedIntervalList* oilOut,
BoundsTightness* tightnessOut) {
- translate(expr, elt, index, oilOut, tightnessOut);
+ OrderedIntervalList arg;
+ translate(expr, elt, index, &arg, tightnessOut);
+
+ // Append the new intervals to oilOut.
+ oilOut->intervals.insert(oilOut->intervals.end(), arg.intervals.begin(),
+ arg.intervals.end());
+
+ // Union the appended intervals with the existing ones.
unionize(oilOut);
}
@@ -216,6 +223,9 @@ namespace mongo {
const IndexEntry& index,
OrderedIntervalList* oilOut,
BoundsTightness* tightnessOut) {
+ // We expect that the OIL we are constructing starts out empty.
+ invariant(oilOut->intervals.empty());
+
oilOut->name = elt.fieldName();
bool isHashed = false;
diff --git a/src/mongo/db/query/index_bounds_builder_test.cpp b/src/mongo/db/query/index_bounds_builder_test.cpp
index 1420e48b69c..0a89cef23fb 100644
--- a/src/mongo/db/query/index_bounds_builder_test.cpp
+++ b/src/mongo/db/query/index_bounds_builder_test.cpp
@@ -1104,4 +1104,19 @@ namespace {
ASSERT_EQUALS(tightness, IndexBoundsBuilder::EXACT);
}
+ TEST(IndexBoundsBuilderTest, UnionizeWithNE) {
+ IndexEntry testIndex = IndexEntry(BSONObj());
+ vector<BSONObj> toUnionize;
+ toUnionize.push_back(fromjson("{a: {$ne: 3}}"));
+ toUnionize.push_back(fromjson("{a: {$ne: 4}}}"));
+ OrderedIntervalList oil;
+ IndexBoundsBuilder::BoundsTightness tightness;
+ testTranslateAndUnion(toUnionize, &oil, &tightness);
+ ASSERT_EQUALS(oil.name, "a");
+ ASSERT_EQUALS(oil.intervals.size(), 1U);
+ ASSERT_EQUALS(Interval::INTERVAL_EQUALS, oil.intervals[0].compare(
+ IndexBoundsBuilder::allValues()));
+ ASSERT_EQUALS(tightness, IndexBoundsBuilder::EXACT);
+ }
+
} // namespace
diff --git a/src/mongo/db/query/query_planner_test.cpp b/src/mongo/db/query/query_planner_test.cpp
index acb8fb09b98..8e465a40287 100644
--- a/src/mongo/db/query/query_planner_test.cpp
+++ b/src/mongo/db/query/query_planner_test.cpp
@@ -3156,6 +3156,18 @@ namespace {
"c: [[1,10,false,false]]}}}}}");
}
+ // Test that planner properly unionizes the index bounds for two negation
+ // predicates (SERVER-13890).
+ TEST_F(QueryPlannerTest, IndexBoundsOrOfNegations) {
+ addIndex(BSON("a" << 1));
+ runQuery(fromjson("{$or: [{a: {$ne: 3}}, {a: {$ne: 4}}]}"));
+
+ assertNumSolutions(2U);
+ assertSolutionExists("{cscan: {dir: 1}}");
+ assertSolutionExists("{fetch: {filter: null, node: {ixscan: {pattern: {a:1}, "
+ "bounds: {a: [['MinKey','MaxKey',true,true]]}}}}}");
+ }
+
//
// Tests related to building index bounds for multikey
// indices, combined with compound and $elemMatch