summaryrefslogtreecommitdiff
path: root/src/mongo/db/matcher/expression_leaf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/matcher/expression_leaf.cpp')
-rw-r--r--src/mongo/db/matcher/expression_leaf.cpp144
1 files changed, 136 insertions, 8 deletions
diff --git a/src/mongo/db/matcher/expression_leaf.cpp b/src/mongo/db/matcher/expression_leaf.cpp
index cad5cd110f1..db78d4eaa85 100644
--- a/src/mongo/db/matcher/expression_leaf.cpp
+++ b/src/mongo/db/matcher/expression_leaf.cpp
@@ -75,15 +75,39 @@ namespace mongo {
// -------------
- Status ComparisonMatchExpression::init( const StringData& path, Type type, const BSONElement& rhs ) {
+ bool ComparisonMatchExpression::equivalent( const MatchExpression* other ) const {
+ if ( other->matchType() != matchType() )
+ return false;
+ const ComparisonMatchExpression* realOther =
+ static_cast<const ComparisonMatchExpression*>( other );
+
+ return
+ _path == realOther->_path &&
+ _rhs.valuesEqual( realOther->_rhs );
+ }
+
+
+ Status ComparisonMatchExpression::init( const StringData& path, const BSONElement& rhs ) {
_path = path;
- _type = type;
_rhs = rhs;
if ( rhs.eoo() ) {
return Status( ErrorCodes::BadValue, "need a real operand" );
}
- _allHaveToMatch = _type == NE;
+ switch ( matchType() ) {
+ case NE:
+ _allHaveToMatch = true;
+ break;
+ case LT:
+ case LTE:
+ case EQ:
+ case GT:
+ case GTE:
+ _allHaveToMatch = false;
+ break;
+ default:
+ return Status( ErrorCodes::BadValue, "bad match type for ComparisonMatchExpression" );
+ }
return Status::OK();
}
@@ -96,20 +120,20 @@ namespace mongo {
// some special cases
// jstNULL and undefined are treated the same
if ( e.canonicalType() + _rhs.canonicalType() == 5 ) {
- return _type == EQ || _type == LTE || _type == GTE;
+ return matchType() == EQ || matchType() == LTE || matchType() == GTE;
}
return _invertForNE( false );
}
if ( _rhs.type() == Array ) {
- if ( _type != EQ && _type != NE ) {
+ if ( matchType() != EQ && matchType() != NE ) {
return false;
}
}
int x = compareElementValues( e, _rhs );
- switch ( _type ) {
+ switch ( matchType() ) {
case LT:
return x < 0;
case LTE:
@@ -122,12 +146,14 @@ namespace mongo {
return x >= 0;
case NE:
return x != 0;
+ default:
+ throw 1;
}
throw 1;
}
bool ComparisonMatchExpression::_invertForNE( bool normal ) const {
- if ( _type == NE )
+ if ( matchType() == NE )
return !normal;
return normal;
}
@@ -135,13 +161,14 @@ namespace mongo {
void ComparisonMatchExpression::debugString( StringBuilder& debug, int level ) const {
_debugAddSpace( debug, level );
debug << _path << " ";
- switch ( _type ) {
+ switch ( matchType() ) {
case LT: debug << "$lt"; break;
case LTE: debug << "$lte"; break;
case EQ: debug << "=="; break;
case GT: debug << "$gt"; break;
case GTE: debug << "$gte"; break;
case NE: debug << "$ne"; break;
+ default: debug << " UNKNOWN - should be impossible"; break;
}
debug << " " << _rhs.toString( false ) << "\n";
}
@@ -166,6 +193,18 @@ namespace mongo {
return options;
}
+ bool RegexMatchExpression::equivalent( const MatchExpression* other ) const {
+ if ( matchType() != other->matchType() )
+ return false;
+
+ const RegexMatchExpression* realOther = static_cast<const RegexMatchExpression*>( other );
+ return
+ _path == realOther->_path &&
+ _regex == realOther->_regex
+ && _flags == realOther->_flags;
+ }
+
+
Status RegexMatchExpression::init( const StringData& path, const BSONElement& e ) {
if ( e.type() != RegEx )
return Status( ErrorCodes::BadValue, "regex not a regex" );
@@ -229,6 +268,17 @@ namespace mongo {
debug << _path << " mod " << _divisor << " % x == " << _remainder << "\n";
}
+ bool ModMatchExpression::equivalent( const MatchExpression* other ) const {
+ if ( matchType() != other->matchType() )
+ return false;
+
+ const ModMatchExpression* realOther = static_cast<const ModMatchExpression*>( other );
+ return
+ _path == realOther->_path &&
+ _divisor == realOther->_divisor &&
+ _remainder == realOther->_remainder;
+ }
+
// ------------------
@@ -250,6 +300,15 @@ namespace mongo {
debug << _path << " exists: " << _exists << "\n";
}
+ bool ExistsMatchExpression::equivalent( const MatchExpression* other ) const {
+ if ( matchType() != other->matchType() )
+ return false;
+
+ const ExistsMatchExpression* realOther = static_cast<const ExistsMatchExpression*>( other );
+ return _path == realOther->_path && _exists == realOther->_exists;
+ }
+
+
// ----
Status TypeMatchExpression::init( const StringData& path, int type ) {
@@ -311,6 +370,15 @@ namespace mongo {
}
+ bool TypeMatchExpression::equivalent( const MatchExpression* other ) const {
+ if ( matchType() != other->matchType() )
+ return false;
+
+ const TypeMatchExpression* realOther = static_cast<const TypeMatchExpression*>( other );
+ return _path == realOther->_path && _type == realOther->_type;
+ }
+
+
// --------
ArrayFilterEntries::ArrayFilterEntries(){
@@ -345,6 +413,27 @@ namespace mongo {
return Status::OK();
}
+ bool ArrayFilterEntries::equivalent( const ArrayFilterEntries& other ) const {
+ if ( _hasNull != other._hasNull )
+ return false;
+
+ if ( _regexes.size() != other._regexes.size() )
+ return false;
+ for ( unsigned i = 0; i < _regexes.size(); i++ )
+ if ( !_regexes[i]->equivalent( other._regexes[i] ) )
+ return false;
+
+ return _equalities == other._equalities;
+ }
+
+ void ArrayFilterEntries::copyTo( ArrayFilterEntries& toFillIn ) const {
+ toFillIn._hasNull = _hasNull;
+ toFillIn._equalities = _equalities;
+ for ( unsigned i = 0; i < _regexes.size(); i++ )
+ toFillIn._regexes.push_back( static_cast<RegexMatchExpression*>(_regexes[i]->shallowClone()) );
+ }
+
+
// -----------
void InMatchExpression::init( const StringData& path ) {
@@ -373,12 +462,35 @@ namespace mongo {
debug << _path << " $in: TODO\n";
}
+ bool InMatchExpression::equivalent( const MatchExpression* other ) const {
+ if ( matchType() != other->matchType() )
+ return false;
+ const InMatchExpression* realOther = static_cast<const InMatchExpression*>( other );
+ log() << "yo: " << _path << " " << realOther->_path << std::endl;
+ return
+ _path == realOther->_path &&
+ _arrayEntries.equivalent( realOther->_arrayEntries );
+ }
+
+ LeafMatchExpression* InMatchExpression::shallowClone() const {
+ InMatchExpression* next = new InMatchExpression();
+ copyTo( next );
+ return next;
+ }
+
+ void InMatchExpression::copyTo( InMatchExpression* toFillIn ) const {
+ toFillIn->init( _path );
+ _arrayEntries.copyTo( toFillIn->_arrayEntries );
+ }
+
+
// ----------
void NinMatchExpression::init( const StringData& path ) {
_path = path;
_allHaveToMatch = true;
+ _in.init( path );
}
@@ -392,6 +504,22 @@ namespace mongo {
debug << _path << " $nin: TODO\n";
}
+ bool NinMatchExpression::equivalent( const MatchExpression* other ) const {
+ if ( matchType() != other->matchType() )
+ return false;
+
+ return _in.equivalent( &(static_cast<const NinMatchExpression*>(other)->_in) );
+
+ }
+
+ LeafMatchExpression* NinMatchExpression::shallowClone() const {
+ NinMatchExpression* next = new NinMatchExpression();
+ next->init( _path );
+ _in.copyTo( &next->_in );
+ return next;
+ }
+
+
}