diff options
author | Misha Ivkov <misha.ivkov@10gen.com> | 2019-07-31 18:00:15 -0400 |
---|---|---|
committer | Misha Ivkov <misha.ivkov@10gen.com> | 2019-08-05 14:46:32 -0400 |
commit | b1285a2acb60cbf7c268cb5499fbf5d674d490b2 (patch) | |
tree | 7ae8730bb758d378afcfe1f0eba3ad9bb6d3966f | |
parent | e3603e4ef4fec9d82fb4daf992b21925392603f6 (diff) | |
download | mongo-b1285a2acb60cbf7c268cb5499fbf5d674d490b2.tar.gz |
SERVER-35921 Make IXSCAN use the proper MinKey/MaxKey bounds on LT and GT
-rw-r--r-- | jstests/core/index_bounds_maxkey.js | 2 | ||||
-rw-r--r-- | jstests/core/index_bounds_minkey.js | 2 | ||||
-rw-r--r-- | jstests/core/min_max_key.js | 3 | ||||
-rw-r--r-- | src/mongo/db/query/index_bounds_builder.cpp | 17 | ||||
-rw-r--r-- | src/mongo/db/query/index_bounds_builder.h | 5 | ||||
-rw-r--r-- | src/mongo/db/query/index_bounds_builder_test.cpp | 14 | ||||
-rw-r--r-- | src/mongo/db/query/query_planner_wildcard_index_test.cpp | 2 |
7 files changed, 29 insertions, 16 deletions
diff --git a/jstests/core/index_bounds_maxkey.js b/jstests/core/index_bounds_maxkey.js index f7cd1eb2e66..c581375e616 100644 --- a/jstests/core/index_bounds_maxkey.js +++ b/jstests/core/index_bounds_maxkey.js @@ -18,7 +18,7 @@ const proj = { }; assertCoveredQueryAndCount({collection: coll, query: {a: {$gt: MaxKey}}, project: proj, count: 0}); assertCoveredQueryAndCount({collection: coll, query: {a: {$gte: MaxKey}}, project: proj, count: 1}); -assertCoveredQueryAndCount({collection: coll, query: {a: {$lt: MaxKey}}, project: proj, count: 1}); +assertCoveredQueryAndCount({collection: coll, query: {a: {$lt: MaxKey}}, project: proj, count: 0}); assertCoveredQueryAndCount({collection: coll, query: {a: {$lte: MaxKey}}, project: proj, count: 1}); // Test that all documents are considered less than MaxKey, regardless of the presence of diff --git a/jstests/core/index_bounds_minkey.js b/jstests/core/index_bounds_minkey.js index 31d38a2115e..b1d244db0b7 100644 --- a/jstests/core/index_bounds_minkey.js +++ b/jstests/core/index_bounds_minkey.js @@ -16,7 +16,7 @@ const proj = { a: 1, _id: 0 }; -assertCoveredQueryAndCount({collection: coll, query: {a: {$gt: MinKey}}, project: proj, count: 1}); +assertCoveredQueryAndCount({collection: coll, query: {a: {$gt: MinKey}}, project: proj, count: 0}); assertCoveredQueryAndCount({collection: coll, query: {a: {$gte: MinKey}}, project: proj, count: 1}); assertCoveredQueryAndCount({collection: coll, query: {a: {$lt: MinKey}}, project: proj, count: 0}); assertCoveredQueryAndCount({collection: coll, query: {a: {$lte: MinKey}}, project: proj, count: 1}); diff --git a/jstests/core/min_max_key.js b/jstests/core/min_max_key.js index e14a7ba4fda..5314e8d3436 100644 --- a/jstests/core/min_max_key.js +++ b/jstests/core/min_max_key.js @@ -89,9 +89,6 @@ testQueriesWithMinOrMaxKey(); testTypeBracketedQueries(); assert.commandWorked(coll.createIndex({a: 1})); -// TODO: SERVER-35921 The results of the queries above should not change based on the -// presence of an index -assert.commandWorked(coll.dropIndexes()); testQueriesWithMinOrMaxKey(); testTypeBracketedQueries(); diff --git a/src/mongo/db/query/index_bounds_builder.cpp b/src/mongo/db/query/index_bounds_builder.cpp index 3afc1f82587..ac40e38f9d0 100644 --- a/src/mongo/db/query/index_bounds_builder.cpp +++ b/src/mongo/db/query/index_bounds_builder.cpp @@ -277,6 +277,13 @@ void IndexBoundsBuilder::allValuesForField(const BSONElement& elt, OrderedInterv makeRangeInterval(bob.obj(), BoundInclusion::kIncludeBothStartAndEndKeys)); } +Interval IndexBoundsBuilder::allValuesRespectingInclusion(BoundInclusion bi) { + BSONObjBuilder bob; + bob.appendMinKey(""); + bob.appendMaxKey(""); + return makeRangeInterval(bob.obj(), bi); +} + Interval IndexBoundsBuilder::allValues() { BSONObjBuilder bob; bob.appendMinKey(""); @@ -526,9 +533,10 @@ void IndexBoundsBuilder::_translatePredicate(const MatchExpression* expr, const LTMatchExpression* node = static_cast<const LTMatchExpression*>(expr); BSONElement dataElt = node->getData(); - // Everything is <= MaxKey. + // Everything is < MaxKey, except for MaxKey. if (MaxKey == dataElt.type()) { - oilOut->intervals.push_back(allValues()); + oilOut->intervals.push_back(allValuesRespectingInclusion( + IndexBounds::makeBoundInclusionFromBoundBools(true, false))); *tightnessOut = index.collator ? IndexBoundsBuilder::INEXACT_FETCH : IndexBoundsBuilder::EXACT; return; @@ -564,9 +572,10 @@ void IndexBoundsBuilder::_translatePredicate(const MatchExpression* expr, const GTMatchExpression* node = static_cast<const GTMatchExpression*>(expr); BSONElement dataElt = node->getData(); - // Everything is > MinKey. + // Everything is > MinKey, except MinKey. if (MinKey == dataElt.type()) { - oilOut->intervals.push_back(allValues()); + oilOut->intervals.push_back(allValuesRespectingInclusion( + IndexBounds::makeBoundInclusionFromBoundBools(false, true))); *tightnessOut = index.collator ? IndexBoundsBuilder::INEXACT_FETCH : IndexBoundsBuilder::EXACT; return; diff --git a/src/mongo/db/query/index_bounds_builder.h b/src/mongo/db/query/index_bounds_builder.h index e5099bbb816..0453df842cb 100644 --- a/src/mongo/db/query/index_bounds_builder.h +++ b/src/mongo/db/query/index_bounds_builder.h @@ -165,6 +165,11 @@ public: */ static Interval allValues(); + /** + * Returns an Interval from minKey to maxKey, preserving the specified inclusion. + */ + static Interval allValuesRespectingInclusion(BoundInclusion bi); + static void translateRegex(const RegexMatchExpression* rme, const IndexEntry& index, OrderedIntervalList* oil, diff --git a/src/mongo/db/query/index_bounds_builder_test.cpp b/src/mongo/db/query/index_bounds_builder_test.cpp index c6aae09515f..c9ee85f24fa 100644 --- a/src/mongo/db/query/index_bounds_builder_test.cpp +++ b/src/mongo/db/query/index_bounds_builder_test.cpp @@ -451,9 +451,9 @@ TEST(IndexBoundsBuilderTest, TranslateLtMaxKey) { IndexBoundsBuilder::translate(expr.get(), elt, testIndex, &oil, &tightness); ASSERT_EQUALS(oil.name, "a"); ASSERT_EQUALS(oil.intervals.size(), 1U); - ASSERT_EQUALS(oil.intervals[0].toString(), "[MinKey, MaxKey]"); + ASSERT_EQUALS(oil.intervals[0].toString(), "[MinKey, MaxKey)"); ASSERT_TRUE(oil.intervals[0].startInclusive); - ASSERT_TRUE(oil.intervals[0].endInclusive); + ASSERT_FALSE(oil.intervals[0].endInclusive); ASSERT_EQUALS(tightness, IndexBoundsBuilder::EXACT); } @@ -595,8 +595,8 @@ TEST(IndexBoundsBuilderTest, TranslateGtMinKey) { IndexBoundsBuilder::translate(expr.get(), elt, testIndex, &oil, &tightness); ASSERT_EQUALS(oil.name, "a"); ASSERT_EQUALS(oil.intervals.size(), 1U); - ASSERT_EQUALS(oil.intervals[0].toString(), "[MinKey, MaxKey]"); - ASSERT_TRUE(oil.intervals[0].startInclusive); + ASSERT_EQUALS(oil.intervals[0].toString(), "(MinKey, MaxKey]"); + ASSERT_FALSE(oil.intervals[0].startInclusive); ASSERT_TRUE(oil.intervals[0].endInclusive); ASSERT_EQUALS(tightness, IndexBoundsBuilder::EXACT); } @@ -2770,7 +2770,8 @@ TEST(IndexBoundsBuilderTest, LTMaxKeyWithCollator) { ASSERT_EQUALS(oil.name, "a"); ASSERT_EQUALS(oil.intervals.size(), 1U); ASSERT_EQUALS(Interval::INTERVAL_EQUALS, - oil.intervals[0].compare(IndexBoundsBuilder::allValues())); + oil.intervals[0].compare(IndexBoundsBuilder::allValuesRespectingInclusion( + BoundInclusion::kIncludeStartKeyOnly))); ASSERT_EQUALS(tightness, IndexBoundsBuilder::INEXACT_FETCH); } @@ -2810,7 +2811,8 @@ TEST(IndexBoundsBuilderTest, GTMinKeyWithCollator) { ASSERT_EQUALS(oil.name, "a"); ASSERT_EQUALS(oil.intervals.size(), 1U); ASSERT_EQUALS(Interval::INTERVAL_EQUALS, - oil.intervals[0].compare(IndexBoundsBuilder::allValues())); + oil.intervals[0].compare(IndexBoundsBuilder::allValuesRespectingInclusion( + BoundInclusion::kIncludeEndKeyOnly))); ASSERT_EQUALS(tightness, IndexBoundsBuilder::INEXACT_FETCH); } diff --git a/src/mongo/db/query/query_planner_wildcard_index_test.cpp b/src/mongo/db/query/query_planner_wildcard_index_test.cpp index eba458736af..ba901fd4577 100644 --- a/src/mongo/db/query/query_planner_wildcard_index_test.cpp +++ b/src/mongo/db/query/query_planner_wildcard_index_test.cpp @@ -381,7 +381,7 @@ TEST_F(QueryPlannerWildcardTest, RangeIndexScanMinKeyMaxKey) { "{fetch: {filter: null, node: " "{ixscan: {filter: null, pattern: {'$_path': 1, a: 1}," "bounds: {'$_path': [['a','a',true,true], ['a.', 'a/', true, false]], 'a': [['MinKey', " - "'MaxKey', true, true]]}}}}}"); + "'MaxKey', false, false]]}}}}}"); } TEST_F(QueryPlannerWildcardTest, RangeIndexScanNestedField) { |