summaryrefslogtreecommitdiff
path: root/src/mongo/dbtests/queryutiltests.cpp
diff options
context:
space:
mode:
authorAaron <aaron@10gen.com>2012-10-11 11:44:38 -0700
committerAaron <aaron@10gen.com>2012-10-23 16:36:53 -0700
commitc0355ccbf0a3e242fe2db1427989bcd22311ac4c (patch)
tree38406b16373a8fd09b989c6a121f7acf37ad374d /src/mongo/dbtests/queryutiltests.cpp
parent40020f6e56381b1fc6533aa3e85cf01f568ccaea (diff)
downloadmongo-c0355ccbf0a3e242fe2db1427989bcd22311ac4c.tar.gz
SERVER-1752 Improve performance of simple counts by avoiding use of a matcher when an optimal btree cursor can filter results internally.
Diffstat (limited to 'src/mongo/dbtests/queryutiltests.cpp')
-rw-r--r--src/mongo/dbtests/queryutiltests.cpp90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/mongo/dbtests/queryutiltests.cpp b/src/mongo/dbtests/queryutiltests.cpp
index 236ffe38f1d..7ebe68e1763 100644
--- a/src/mongo/dbtests/queryutiltests.cpp
+++ b/src/mongo/dbtests/queryutiltests.cpp
@@ -129,6 +129,29 @@ namespace QueryUtilTests {
virtual bool mustBeExactMatchRepresentation() { return true; }
};
+ class LtDate : public Base {
+ public:
+ LtDate() :
+ _o( BSON( "" << Date_t( 5000 ) ) ),
+ _o2( BSON( "" << true ) ) {
+ }
+ virtual BSONObj query() { return BSON( "a" << LT << _o.firstElement() ); }
+ virtual BSONElement lower() {
+ // $lt:date is bounded from below by 'true', the highest value of the next lowest
+ // canonical type.
+ return _o2.firstElement();
+ }
+ virtual bool lowerInclusive() {
+ // 'true' should not match $lt:date, so the bound is exclusive.
+ return false;
+ }
+ virtual BSONElement upper() { return _o.firstElement(); }
+ virtual bool upperInclusive() { return false; }
+ virtual bool mustBeExactMatchRepresentation() { return true; }
+ private:
+ BSONObj _o, _o2;
+ };
+
class Gt : public NumericBase {
public:
Gt() : o_( BSON( "-" << 1 ) ) {}
@@ -145,6 +168,29 @@ namespace QueryUtilTests {
virtual bool lowerInclusive() { return true; }
};
+ class GtString : public Base {
+ public:
+ GtString() :
+ _o( BSON( "" << "abc" ) ),
+ _o2( BSON( "" << BSONObj() ) ) {
+ }
+ virtual BSONObj query() { return BSON( "a" << GT << _o.firstElement() ); }
+ virtual BSONElement lower() { return _o.firstElement(); }
+ virtual bool lowerInclusive() { return false; }
+ virtual BSONElement upper() {
+ // $gt:string is bounded from above by '{}', the lowest value of the next highest
+ // canonical type.
+ return _o2.firstElement();
+ }
+ virtual bool upperInclusive() {
+ // '{}' should not match $gt:string, so the bound is exclusive.
+ return false;
+ }
+ virtual bool mustBeExactMatchRepresentation() { return true; }
+ private:
+ BSONObj _o, _o2;
+ };
+
class TwoLt : public Lt {
virtual BSONObj query() { return BSON( "a" << LT << 1 << LT << 5 ); }
};
@@ -1707,6 +1753,7 @@ namespace QueryUtilTests {
} // namespace FieldRangeSetPairTests
namespace FieldRangeVectorTests {
+
class ToString {
public:
void run() {
@@ -1717,6 +1764,46 @@ namespace QueryUtilTests {
fieldRangeVector.toString(); // Just test that we don't crash.
}
};
+
+ /**
+ * Check FieldRangeVector::hasAllIndexedRanges(), indicating when all indexed field ranges
+ * in a field range set are represented in a field range vector (and none are excluded due
+ * to multikey index field name conflicts).
+ */
+ class HasAllIndexedRanges {
+ public:
+ void run() {
+ // Single key index.
+ ASSERT( rangesRepresented( BSON( "a" << 1 ), true, BSON( "a" << 1 ) ) );
+ // Multikey index, but no unrepresented ranges.
+ ASSERT( rangesRepresented( BSON( "a" << 1 ), false, BSON( "a" << 1 ) ) );
+ // Multikey index, but no unrepresented ranges in the index.
+ ASSERT( rangesRepresented( BSON( "a" << 1 ), false,
+ BSON( "a" << 1 << "b" << 2 ) ) );
+ // Compound multikey index with no unrepresented ranges.
+ ASSERT( rangesRepresented( BSON( "a" << 1 << "b" << 1 ), false,
+ BSON( "a" << 2 << "b" << 3 ) ) );
+ // Compound multikey index with range 'a.c' unrepresented because of a conflict
+ // with range 'a.b', hence 'false' expected.
+ ASSERT( !rangesRepresented( BSON( "a.b" << 1 << "a.c" << 1 ), false,
+ BSON( "a.b" << 2 << "a.c" << 3 ) ) );
+ // Compound multikey index without conflicts due to use of the $elemMatch operator.
+ ASSERT( rangesRepresented( BSON( "a.b" << 1 << "a.c" << 1 ), false,
+ BSON( "a" << BSON( "$elemMatch" <<
+ BSON( "b" << 2 << "c" << 3 ) ) ) ) );
+ // Single key index.
+ ASSERT( rangesRepresented( BSON( "a.b" << 1 << "a.c" << 1 ), true,
+ BSON( "a.b" << 2 << "a.c" << 3 ) ) );
+ }
+ private:
+ bool rangesRepresented( const BSONObj& index, bool singleKey, const BSONObj& query ) {
+ FieldRangeSet fieldRangeSet( "", query, singleKey, true );
+ IndexSpec indexSpec( index );
+ FieldRangeVector fieldRangeVector( fieldRangeSet, indexSpec, 1 );
+ return fieldRangeVector.hasAllIndexedRanges();
+ }
+ };
+
} // namespace FieldRangeVectorTests
// These are currently descriptive, not normative tests. SERVER-5450
@@ -2533,8 +2620,10 @@ namespace QueryUtilTests {
add<FieldRangeTests::DupEq>();
add<FieldRangeTests::Lt>();
add<FieldRangeTests::Lte>();
+ add<FieldRangeTests::LtDate>();
add<FieldRangeTests::Gt>();
add<FieldRangeTests::Gte>();
+ add<FieldRangeTests::GtString>();
add<FieldRangeTests::TwoLt>();
add<FieldRangeTests::TwoGt>();
add<FieldRangeTests::EqGte>();
@@ -2685,6 +2774,7 @@ namespace QueryUtilTests {
add<FieldRangeSetPairTests::ClearIndexesForPatterns>();
add<FieldRangeSetPairTests::BestIndexForPatterns>();
add<FieldRangeVectorTests::ToString>();
+ add<FieldRangeVectorTests::HasAllIndexedRanges>();
add<FieldRangeVectorIteratorTests::AdvanceToNextIntervalEquality>();
add<FieldRangeVectorIteratorTests::AdvanceToNextIntervalExclusiveInequality>();
add<FieldRangeVectorIteratorTests::AdvanceToNextIntervalEqualityReverse>();