summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMisha Ivkov <misha.ivkov@10gen.com>2019-07-31 18:00:15 -0400
committerMisha Ivkov <misha.ivkov@10gen.com>2019-08-05 14:46:32 -0400
commitb1285a2acb60cbf7c268cb5499fbf5d674d490b2 (patch)
tree7ae8730bb758d378afcfe1f0eba3ad9bb6d3966f
parente3603e4ef4fec9d82fb4daf992b21925392603f6 (diff)
downloadmongo-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.js2
-rw-r--r--jstests/core/index_bounds_minkey.js2
-rw-r--r--jstests/core/min_max_key.js3
-rw-r--r--src/mongo/db/query/index_bounds_builder.cpp17
-rw-r--r--src/mongo/db/query/index_bounds_builder.h5
-rw-r--r--src/mongo/db/query/index_bounds_builder_test.cpp14
-rw-r--r--src/mongo/db/query/query_planner_wildcard_index_test.cpp2
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) {