summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron <aaron@10gen.com>2012-03-29 23:09:10 -0700
committerAaron <aaron@10gen.com>2012-04-06 21:48:54 -0700
commita4cd061f60ed902ffd4e4f7aae688623565a2d78 (patch)
treea1bad9ede816cb49425ae81a0b71a8783742756e
parent6a8f01b10c055ca8a3bf3ce1eaf7893a1b92b1c6 (diff)
downloadmongo-a4cd061f60ed902ffd4e4f7aae688623565a2d78.tar.gz
SERVER-5450 Extract validateCurrentInterval() from FieldRangeVectorIterator::advance().
-rw-r--r--src/mongo/db/queryutil.cpp107
-rw-r--r--src/mongo/db/queryutil.h9
-rw-r--r--src/mongo/dbtests/queryutiltests.cpp32
3 files changed, 102 insertions, 46 deletions
diff --git a/src/mongo/db/queryutil.cpp b/src/mongo/db/queryutil.cpp
index f329e8fcd71..dccb38f061b 100644
--- a/src/mongo/db/queryutil.cpp
+++ b/src/mongo/db/queryutil.cpp
@@ -1369,55 +1369,15 @@ namespace mongo {
// which serves as a lower/equal bound on the first iteration -
// we advance from this interval to find a matching interval
while( _i.get( i ) < (int)_v._ranges[ i ].intervals().size() ) {
- // compare to current interval's upper bound
- int x = _v._ranges[ i ].intervals()[ _i.get( i ) ]._upper._bound.woCompare( jj, false );
- if ( reverse ) {
- x = -x;
+
+ int advanceMethod = validateCurrentInterval( i, jj, reverse, first, eq );
+ if ( advanceMethod >= 0 ) {
+ return advanceMethod;
}
- if ( x == 0 && _v._ranges[ i ].intervals()[ _i.get( i ) ]._upper._inclusive ) {
- eq = true;
+ if ( advanceMethod == -1 ) {
break;
}
- // see if we're less than the upper bound
- if ( x > 0 ) {
- if ( i == 0 && first ) {
- // the value of 1st field won't go backward, so don't check lower bound
- // TODO maybe we can check first only?
- break;
- }
- // if it's an equality interval, don't need to compare separately to lower bound
- if ( !_v._ranges[ i ].intervals()[ _i.get( i ) ].equality() ) {
- // compare to current interval's lower bound
- x = _v._ranges[ i ].intervals()[ _i.get( i ) ]._lower._bound.woCompare( jj, false );
- if ( reverse ) {
- x = -x;
- }
- }
- // if we're equal to and not inclusive the lower bound, advance
- if ( ( x == 0 && !_v._ranges[ i ].intervals()[ _i.get( i ) ]._lower._inclusive ) ) {
- _i.setZeroes( i + 1 );
- // skip to curr / i + 1 / superlative
- _after = true;
- return i + 1;
- }
- // if we're less than the lower bound, advance
- if ( x > 0 ) {
- _i.setZeroes( i + 1 );
- // skip to curr / i / nextbounds
- _cmp[ i ] = &_v._ranges[ i ].intervals()[ _i.get( i ) ]._lower._bound;
- _inc[ i ] = _v._ranges[ i ].intervals()[ _i.get( i ) ]._lower._inclusive;
- for( int j = i + 1; j < _i.size(); ++j ) {
- _cmp[ j ] = &_v._ranges[ j ].intervals().front()._lower._bound;
- _inc[ j ] = _v._ranges[ j ].intervals().front()._lower._inclusive;
- }
- _after = false;
- return i;
- }
- else {
- break;
- }
- }
- // we're above the upper bound, so try next interval and reset remaining fields
+ // we're past the current interval, so try next interval and reset remaining fields
_i.inc( i );
_i.setZeroes( i + 1 );
first = false;
@@ -1447,6 +1407,61 @@ namespace mongo {
_inc[ j ] = _v._ranges[ j ].intervals().front()._lower._inclusive;
}
}
+
+ int FieldRangeVectorIterator::validateCurrentInterval( int i, const BSONElement &jj,
+ bool reverse, bool first, bool &eq ) {
+ // compare to current interval's upper bound
+ int x = _v._ranges[ i ].intervals()[ _i.get( i ) ]._upper._bound.woCompare( jj, false );
+ if ( reverse ) {
+ x = -x;
+ }
+ if ( x == 0 && _v._ranges[ i ].intervals()[ _i.get( i ) ]._upper._inclusive ) {
+ eq = true;
+ return -1;
+ }
+ // see if we're less than the upper bound
+ if ( x > 0 ) {
+ if ( i == 0 && first ) {
+ // the value of 1st field won't go backward, so don't check lower bound
+ // TODO maybe we can check first only?
+ return -1;
+ }
+ // if it's an equality interval, don't need to compare separately to lower bound
+ if ( !_v._ranges[ i ].intervals()[ _i.get( i ) ].equality() ) {
+ // compare to current interval's lower bound
+ x = _v._ranges[ i ].intervals()[ _i.get( i ) ]._lower._bound.woCompare( jj, false );
+ if ( reverse ) {
+ x = -x;
+ }
+ }
+ // if we're equal to and not inclusive the lower bound, advance
+ if ( ( x == 0 && !_v._ranges[ i ].intervals()[ _i.get( i ) ]._lower._inclusive ) ) {
+ _i.setZeroes( i + 1 );
+ // skip to curr / i + 1 / superlative
+ _after = true;
+ return i + 1;
+ }
+ // if we're less than the lower bound, advance
+ if ( x > 0 ) {
+ _i.setZeroes( i + 1 );
+ // skip to curr / i / nextbounds
+ _cmp[ i ] = &_v._ranges[ i ].intervals()[ _i.get( i ) ]._lower._bound;
+ _inc[ i ] = _v._ranges[ i ].intervals()[ _i.get( i ) ]._lower._inclusive;
+ for( int j = i + 1; j < _i.size(); ++j ) {
+ _cmp[ j ] = &_v._ranges[ j ].intervals().front()._lower._bound;
+ _inc[ j ] = _v._ranges[ j ].intervals().front()._lower._inclusive;
+ }
+ _after = false;
+ return i;
+ }
+ else {
+ return -1;
+ }
+ }
+ // we're above the upper bound
+ return -2;
+ }
+
OrRangeGenerator::OrRangeGenerator( const char *ns, const BSONObj &query , bool optimize )
: _baseSet( ns, query, optimize ), _orFound() {
diff --git a/src/mongo/db/queryutil.h b/src/mongo/db/queryutil.h
index bfc64e31f51..fac33df8e62 100644
--- a/src/mongo/db/queryutil.h
+++ b/src/mongo/db/queryutil.h
@@ -622,6 +622,15 @@ namespace mongo {
};
private:
+ /**
+ * @return values similar to advance()
+ * -2 Iteration is complete for the current interval.
+ * -1 Iteration is not complete for the current interval.
+ * >=0 Return value to be forwarded by advance().
+ */
+ int validateCurrentInterval( int i, const BSONElement &jj, bool reverse, bool first,
+ bool &eq );
+
const FieldRangeVector &_v;
CompoundRangeCounter _i;
vector<const BSONElement*> _cmp;
diff --git a/src/mongo/dbtests/queryutiltests.cpp b/src/mongo/dbtests/queryutiltests.cpp
index 1fce06e36e4..87c644d2353 100644
--- a/src/mongo/dbtests/queryutiltests.cpp
+++ b/src/mongo/dbtests/queryutiltests.cpp
@@ -1263,6 +1263,26 @@ namespace QueryUtilTests {
}
};
+ class AdvanceRange : public Base {
+ BSONObj query() { return fromjson( "{a:{$gt:2,$lt:8}}" ); }
+ BSONObj index() { return fromjson( "{a:1}" ); }
+ void check() {
+ assertAdvanceToNext( BSON( "a" << 2 ) );
+ assertAdvanceToNext( BSON( "a" << 4 ) );
+ assertAdvanceToNext( BSON( "a" << 5 ) );
+ assertDoneAdvancing( BSON( "a" << 9 ) );
+ }
+ };
+
+ class AdvanceInRange : public Base {
+ BSONObj query() { return fromjson( "{a:{$in:[0,1]},b:{$gt:2,$lt:8}}" ); }
+ BSONObj index() { return fromjson( "{a:1,b:1}" ); }
+ void check() {
+ assertAdvanceToNext( BSON( "a" << 0 << "b" << 5 ) );
+ assertAdvanceToNext( BSON( "a" << 0 << "b" << 5 ) );
+ }
+ };
+
class AdvanceRangeIn : public Base {
BSONObj query() { return fromjson( "{a:{$gt:2,$lt:8},b:{$in:[0,1]}}" ); }
BSONObj index() { return fromjson( "{a:1,b:1}" ); }
@@ -1281,6 +1301,15 @@ namespace QueryUtilTests {
}
};
+ class AdvanceRangeRangeMultiple : public Base {
+ BSONObj query() { return fromjson( "{a:{$gt:2,$lt:8},b:{$gt:1,$lt:4}}" ); }
+ BSONObj index() { return fromjson( "{a:1,b:1}" ); }
+ void check() {
+ assertAdvanceToNext( BSON( "a" << 4 << "b" << 3 ) );
+ assertAdvanceToNext( BSON( "a" << 4 << "b" << 3 ) );
+ }
+ };
+
class AdvanceRangeRangeIn : public Base {
BSONObj query() { return fromjson( "{a:{$gt:2,$lt:8},b:{$gt:1,$lt:4},c:{$in:[6,7]}}" ); }
BSONObj index() { return fromjson( "{a:1,b:1,c:1}" ); }
@@ -1481,8 +1510,11 @@ namespace QueryUtilTests {
add<FieldRangeVectorIteratorTests::AdvanceToNextIntervalIntermediateEqualityCompound>();
add<FieldRangeVectorIteratorTests::BeforeLowerBound>();
add<FieldRangeVectorIteratorTests::AdvanceToNextExclusiveIntervalCompound>();
+ add<FieldRangeVectorIteratorTests::AdvanceRange>();
+ add<FieldRangeVectorIteratorTests::AdvanceInRange>();
add<FieldRangeVectorIteratorTests::AdvanceRangeIn>();
add<FieldRangeVectorIteratorTests::AdvanceRangeRange>();
+ add<FieldRangeVectorIteratorTests::AdvanceRangeRangeMultiple>();
add<FieldRangeVectorIteratorTests::AdvanceRangeRangeIn>();
add<FieldRangeVectorIteratorTests::AdvanceRangeMixedIn>();
add<FieldRangeVectorIteratorTests::AdvanceMixedMixedIn>();