diff options
author | Misha Ivkov <misha.ivkov@10gen.com> | 2019-07-31 18:00:15 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-08-14 19:00:24 +0000 |
commit | d3470d48166e9897e9d9817340db9f11f70a55e4 (patch) | |
tree | 6f1fd2f866466df018961eda6b8603457fee8367 | |
parent | d5e2742489c6502f68324c5e40d4ea78c01a3dad (diff) | |
download | mongo-d3470d48166e9897e9d9817340db9f11f70a55e4.tar.gz |
SERVER-35921 Make IXSCAN use the proper MinKey/MaxKey bounds on LT and GT
(cherry picked from commit b1285a2acb60cbf7c268cb5499fbf5d674d490b2)
(cherry picked from commit b315dcfc8145c6b898b21916bef4bec18e95ac54)
-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 |
6 files changed, 28 insertions, 15 deletions
diff --git a/jstests/core/index_bounds_maxkey.js b/jstests/core/index_bounds_maxkey.js index b22af082b13..ab152230904 100644 --- a/jstests/core/index_bounds_maxkey.js +++ b/jstests/core/index_bounds_maxkey.js @@ -18,7 +18,7 @@ assertCoveredQueryAndCount( {collection: coll, query: {a: {$gte: MaxKey}}, project: proj, count: 1}); assertCoveredQueryAndCount( - {collection: coll, query: {a: {$lt: MaxKey}}, project: proj, count: 1}); + {collection: coll, query: {a: {$lt: MaxKey}}, project: proj, count: 0}); assertCoveredQueryAndCount( {collection: coll, query: {a: {$lte: MaxKey}}, project: proj, count: 1}); diff --git a/jstests/core/index_bounds_minkey.js b/jstests/core/index_bounds_minkey.js index 6fa9d4f0d1e..25fc4f56fc7 100644 --- a/jstests/core/index_bounds_minkey.js +++ b/jstests/core/index_bounds_minkey.js @@ -14,7 +14,7 @@ // Test that queries involving comparison operators with MinKey are covered. const proj = {a: 1, _id: 0}; assertCoveredQueryAndCount( - {collection: coll, query: {a: {$gt: MinKey}}, project: proj, count: 1}); + {collection: coll, query: {a: {$gt: MinKey}}, project: proj, count: 0}); assertCoveredQueryAndCount( {collection: coll, query: {a: {$gte: MinKey}}, project: proj, count: 1}); assertCoveredQueryAndCount( diff --git a/jstests/core/min_max_key.js b/jstests/core/min_max_key.js index d65d68292fa..744bdff2b49 100644 --- a/jstests/core/min_max_key.js +++ b/jstests/core/min_max_key.js @@ -89,9 +89,6 @@ 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 503ee1f8b9d..48ee291b288 100644 --- a/src/mongo/db/query/index_bounds_builder.cpp +++ b/src/mongo/db/query/index_bounds_builder.cpp @@ -250,6 +250,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(""); @@ -479,9 +486,10 @@ void IndexBoundsBuilder::translate(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; @@ -517,9 +525,10 @@ void IndexBoundsBuilder::translate(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 52e33853b8b..9f396bd144e 100644 --- a/src/mongo/db/query/index_bounds_builder.h +++ b/src/mongo/db/query/index_bounds_builder.h @@ -166,6 +166,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 392204f548c..75062d44c4f 100644 --- a/src/mongo/db/query/index_bounds_builder_test.cpp +++ b/src/mongo/db/query/index_bounds_builder_test.cpp @@ -439,9 +439,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); } @@ -583,8 +583,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); } @@ -2485,7 +2485,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); } @@ -2525,7 +2526,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); } |