mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 09:32:32 +01:00
FieldBoundSet handles inclusive / exclusive bounds
This commit is contained in:
parent
81a684ee5f
commit
4487004dac
@ -48,7 +48,9 @@ namespace mongo {
|
||||
|
||||
FieldBound::FieldBound( const BSONElement &e ) :
|
||||
lower_( minKey.firstElement() ),
|
||||
upper_( maxKey.firstElement() ) {
|
||||
lowerInclusive_( true ),
|
||||
upper_( maxKey.firstElement() ),
|
||||
upperInclusive_( true ) {
|
||||
if ( e.eoo() )
|
||||
return;
|
||||
if ( e.type() == RegEx ) {
|
||||
@ -62,13 +64,15 @@ namespace mongo {
|
||||
switch( e.getGtLtOp() ) {
|
||||
case JSMatcher::Equality:
|
||||
lower_ = e;
|
||||
upper_ = e;
|
||||
upper_ = e;
|
||||
break;
|
||||
case JSMatcher::LT:
|
||||
upperInclusive_ = false;
|
||||
case JSMatcher::LTE:
|
||||
upper_ = e;
|
||||
break;
|
||||
case JSMatcher::GT:
|
||||
lowerInclusive_ = false;
|
||||
case JSMatcher::GTE:
|
||||
lower_ = e;
|
||||
break;
|
||||
@ -95,10 +99,23 @@ namespace mongo {
|
||||
}
|
||||
|
||||
const FieldBound &FieldBound::operator&=( const FieldBound &other ) {
|
||||
if ( other.upper_.woCompare( upper_, false ) < 0 )
|
||||
int cmp;
|
||||
cmp = other.upper_.woCompare( upper_, false );
|
||||
if ( cmp == 0 )
|
||||
if ( !other.upperInclusive_ )
|
||||
upperInclusive_ = false;
|
||||
if ( cmp < 0 ) {
|
||||
upper_ = other.upper_;
|
||||
if ( other.lower_.woCompare( lower_, false ) > 0 )
|
||||
upperInclusive_ = other.upperInclusive_;
|
||||
}
|
||||
cmp = other.lower_.woCompare( lower_, false );
|
||||
if ( cmp == 0 )
|
||||
if ( !other.lowerInclusive_ )
|
||||
lowerInclusive_ = false;
|
||||
if ( cmp > 0 ) {
|
||||
lower_ = other.lower_;
|
||||
lowerInclusive_ = other.lowerInclusive_;
|
||||
}
|
||||
for( vector< BSONObj >::const_iterator i = other.objData_.begin(); i != other.objData_.end(); ++i )
|
||||
objData_.push_back( *i );
|
||||
return *this;
|
||||
@ -154,9 +171,9 @@ namespace mongo {
|
||||
else if ( i->second.nontrivial() ) {
|
||||
BSONObjBuilder c;
|
||||
if ( i->second.lower().type() != MinKey )
|
||||
c.appendAs( i->second.lower(), "$gte" );
|
||||
c.appendAs( i->second.lower(), i->second.lowerInclusive() ? "$gte" : "$gt" );
|
||||
if ( i->second.upper().type() != MaxKey )
|
||||
c.appendAs( i->second.upper(), "$lte" );
|
||||
c.appendAs( i->second.upper(), i->second.upperInclusive() ? "$lte" : "$lt" );
|
||||
b.append( i->first.c_str(), c.done() );
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,14 @@ namespace mongo {
|
||||
const FieldBound &operator&=( const FieldBound &other );
|
||||
BSONElement lower() const { return lower_; }
|
||||
BSONElement upper() const { return upper_; }
|
||||
bool equality() const { return lower_.woCompare( upper_, false ) == 0; }
|
||||
bool lowerInclusive() const { return lowerInclusive_; }
|
||||
bool upperInclusive() const { return upperInclusive_; }
|
||||
bool equality() const {
|
||||
return
|
||||
lower_.woCompare( upper_, false ) == 0 &&
|
||||
upperInclusive_ &&
|
||||
lowerInclusive_;
|
||||
}
|
||||
bool nontrivial() const {
|
||||
return
|
||||
minKey.firstElement().woCompare( lower_, false ) != 0 ||
|
||||
@ -45,7 +52,9 @@ namespace mongo {
|
||||
BSONObj addObj( const BSONObj &o );
|
||||
string simpleRegexEnd( string regex );
|
||||
BSONElement lower_;
|
||||
bool lowerInclusive_;
|
||||
BSONElement upper_;
|
||||
bool upperInclusive_;
|
||||
vector< BSONObj > objData_;
|
||||
};
|
||||
|
||||
|
@ -156,15 +156,34 @@ namespace QueryOptimizerTests {
|
||||
BSONObj o1_, o2_;
|
||||
};
|
||||
|
||||
class Equality {
|
||||
public:
|
||||
void run() {
|
||||
FieldBoundSet s( "ns", BSON( "a" << 1 ) );
|
||||
ASSERT( s.bound( "a" ).equality() );
|
||||
FieldBoundSet s2( "ns", BSON( "a" << GTE << 1 << LTE << 1 ) );
|
||||
ASSERT( s2.bound( "a" ).equality() );
|
||||
FieldBoundSet s3( "ns", BSON( "a" << GT << 1 << LTE << 1 ) );
|
||||
ASSERT( !s3.bound( "a" ).equality() );
|
||||
FieldBoundSet s4( "ns", BSON( "a" << GTE << 1 << LT << 1 ) );
|
||||
ASSERT( !s4.bound( "a" ).equality() );
|
||||
FieldBoundSet s5( "ns", BSON( "a" << GTE << 1 << LTE << 1 << GT << 1 ) );
|
||||
ASSERT( !s5.bound( "a" ).equality() );
|
||||
FieldBoundSet s6( "ns", BSON( "a" << GTE << 1 << LTE << 1 << LT << 1 ) );
|
||||
ASSERT( !s6.bound( "a" ).equality() );
|
||||
}
|
||||
};
|
||||
|
||||
class SimplifiedQuery {
|
||||
public:
|
||||
void run() {
|
||||
FieldBoundSet fbs( "ns", BSON( "a" << GT << 1 << GT << 5 << LT << 10 << "b" << 4 << "c" << LT << 4 << LT << 6 << "d" << GTE << 0 ) );
|
||||
FieldBoundSet fbs( "ns", BSON( "a" << GT << 1 << GT << 5 << LT << 10 << "b" << 4 << "c" << LT << 4 << LT << 6 << "d" << GTE << 0 << GT << 0 << "e" << GTE << 0 << LTE << 10 ) );
|
||||
BSONObj simple = fbs.simplifiedQuery();
|
||||
ASSERT( !simple.getObjectField( "a" ).woCompare( fromjson( "{$gte:5,$lte:10}" ) ) );
|
||||
ASSERT( !simple.getObjectField( "a" ).woCompare( fromjson( "{$gt:5,$lt:10}" ) ) );
|
||||
ASSERT_EQUALS( 4, simple.getIntField( "b" ) );
|
||||
ASSERT( !simple.getObjectField( "c" ).woCompare( fromjson( "{$lte:4}" ) ) );
|
||||
ASSERT( !simple.getObjectField( "d" ).woCompare( fromjson( "{$gte:0}" ) ) );
|
||||
ASSERT( !simple.getObjectField( "c" ).woCompare( fromjson( "{$lt:4}" ) ) );
|
||||
ASSERT( !simple.getObjectField( "d" ).woCompare( fromjson( "{$gt:0}" ) ) );
|
||||
ASSERT( !simple.getObjectField( "e" ).woCompare( fromjson( "{$gte:0,$lte:10}" ) ) );
|
||||
}
|
||||
};
|
||||
|
||||
@ -933,6 +952,7 @@ namespace QueryOptimizerTests {
|
||||
add< FieldBoundTests::Regex >();
|
||||
add< FieldBoundTests::UnhelpfulRegex >();
|
||||
add< FieldBoundTests::In >();
|
||||
add< FieldBoundTests::Equality >();
|
||||
add< FieldBoundTests::SimplifiedQuery >();
|
||||
add< FieldBoundTests::QueryPatternTest >();
|
||||
add< FieldBoundTests::NoWhere >();
|
||||
|
Loading…
Reference in New Issue
Block a user