diff options
author | Aaron <aaron@10gen.com> | 2012-03-29 23:09:10 -0700 |
---|---|---|
committer | Aaron <aaron@10gen.com> | 2012-04-06 21:48:54 -0700 |
commit | a4cd061f60ed902ffd4e4f7aae688623565a2d78 (patch) | |
tree | a1bad9ede816cb49425ae81a0b71a8783742756e | |
parent | 6a8f01b10c055ca8a3bf3ce1eaf7893a1b92b1c6 (diff) | |
download | mongo-a4cd061f60ed902ffd4e4f7aae688623565a2d78.tar.gz |
SERVER-5450 Extract validateCurrentInterval() from FieldRangeVectorIterator::advance().
-rw-r--r-- | src/mongo/db/queryutil.cpp | 107 | ||||
-rw-r--r-- | src/mongo/db/queryutil.h | 9 | ||||
-rw-r--r-- | src/mongo/dbtests/queryutiltests.cpp | 32 |
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>(); |