diff options
Diffstat (limited to 'db/matcher.cpp')
-rw-r--r-- | db/matcher.cpp | 463 |
1 files changed, 237 insertions, 226 deletions
diff --git a/db/matcher.cpp b/db/matcher.cpp index 544ec27f1cf..494063f4bed 100644 --- a/db/matcher.cpp +++ b/db/matcher.cpp @@ -30,7 +30,7 @@ #include "pdfile.h" namespace { - inline pcrecpp::RE_Options flags2options(const char* flags){ + inline pcrecpp::RE_Options flags2options(const char* flags) { pcrecpp::RE_Options options; options.set_utf8(true); while ( flags && *flags ) { @@ -52,7 +52,7 @@ namespace { namespace mongo { extern BSONObj staticNull; - + class Where { public: Where() { @@ -64,22 +64,22 @@ namespace mongo { if ( scope.get() ) scope->execSetup( "_mongo.readOnly = false;" , "make not read only" ); - if ( jsScope ){ + if ( jsScope ) { delete jsScope; jsScope = 0; } func = 0; } - + auto_ptr<Scope> scope; ScriptingFunction func; BSONObj *jsScope; - + void setFunc(const char *code) { massert( 10341 , "scope has to be created first!" , scope.get() ); func = scope->createFunction( code ); } - + }; Matcher::~Matcher() { @@ -87,23 +87,23 @@ namespace mongo { where = 0; } - ElementMatcher::ElementMatcher( BSONElement _e , int _op, bool _isNot ) - : toMatch( _e ) , compareOp( _op ), isNot( _isNot ), subMatcherOnPrimitives(false){ - if ( _op == BSONObj::opMOD ){ + ElementMatcher::ElementMatcher( BSONElement _e , int _op, bool _isNot ) + : toMatch( _e ) , compareOp( _op ), isNot( _isNot ), subMatcherOnPrimitives(false) { + if ( _op == BSONObj::opMOD ) { BSONObj o = _e.embeddedObject(); mod = o["0"].numberInt(); modm = o["1"].numberInt(); - + uassert( 10073 , "mod can't be 0" , mod ); } - else if ( _op == BSONObj::opTYPE ){ + else if ( _op == BSONObj::opTYPE ) { type = (BSONType)(_e.numberInt()); } - else if ( _op == BSONObj::opELEM_MATCH ){ + else if ( _op == BSONObj::opELEM_MATCH ) { BSONElement m = _e; uassert( 12517 , "$elemMatch needs an Object" , m.type() == Object ); BSONObj x = m.embeddedObject(); - if ( x.firstElement().getGtLtOp() == 0 ){ + if ( x.firstElement().getGtLtOp() == 0 ) { subMatcher.reset( new Matcher( x ) ); subMatcherOnPrimitives = false; } @@ -115,19 +115,20 @@ namespace mongo { } } - ElementMatcher::ElementMatcher( BSONElement _e , int _op , const BSONObj& array, bool _isNot ) + ElementMatcher::ElementMatcher( BSONElement _e , int _op , const BSONObj& array, bool _isNot ) : toMatch( _e ) , compareOp( _op ), isNot( _isNot ), subMatcherOnPrimitives(false) { - + myset.reset( new set<BSONElement,element_lt>() ); - + BSONObjIterator i( array ); while ( i.more() ) { BSONElement ie = i.next(); - if ( _op == BSONObj::opALL && ie.type() == Object && ie.embeddedObject().firstElement().getGtLtOp() == BSONObj::opELEM_MATCH ){ + if ( _op == BSONObj::opALL && ie.type() == Object && ie.embeddedObject().firstElement().getGtLtOp() == BSONObj::opELEM_MATCH ) { shared_ptr<Matcher> s; s.reset( new Matcher( ie.embeddedObject().firstElement().embeddedObjectUserCheck() ) ); allMatchers.push_back( s ); - } else if ( ie.type() == RegEx ) { + } + else if ( ie.type() == RegEx ) { if ( !myregex.get() ) { myregex.reset( new vector< RegexMatcher >() ); } @@ -142,19 +143,20 @@ namespace mongo { string prefix = simpleRegex(rm.regex, rm.flags, &purePrefix); if (purePrefix) rm.prefix = prefix; - } else { + } + else { myset->insert(ie); } } - - if ( allMatchers.size() ){ + + if ( allMatchers.size() ) { uassert( 13020 , "with $all, can't mix $elemMatch and others" , myset->size() == 0 && !myregex.get()); } - + } - - - void Matcher::addRegex(const char *fieldName, const char *regex, const char *flags, bool isNot){ + + + void Matcher::addRegex(const char *fieldName, const char *regex, const char *flags, bool isNot) { if ( nRegex >= 4 ) { out() << "ERROR: too many regexes in query" << endl; @@ -168,106 +170,106 @@ namespace mongo { rm.isNot = isNot; nRegex++; - if (!isNot){ //TODO something smarter + if (!isNot) { //TODO something smarter bool purePrefix; string prefix = simpleRegex(regex, flags, &purePrefix); if (purePrefix) rm.prefix = prefix; } - } + } } - + bool Matcher::addOp( const BSONElement &e, const BSONElement &fe, bool isNot, const char *& regex, const char *&flags ) { const char *fn = fe.fieldName(); int op = fe.getGtLtOp( -1 ); - if ( op == -1 ){ - if ( !isNot && fn[1] == 'r' && fn[2] == 'e' && fn[3] == 'f' && fn[4] == 0 ){ + if ( op == -1 ) { + if ( !isNot && fn[1] == 'r' && fn[2] == 'e' && fn[3] == 'f' && fn[4] == 0 ) { return false; // { $ref : xxx } - treat as normal object } uassert( 10068 , (string)"invalid operator: " + fn , op != -1 ); } - - switch ( op ){ - case BSONObj::GT: - case BSONObj::GTE: - case BSONObj::LT: - case BSONObj::LTE:{ - shared_ptr< BSONObjBuilder > b( new BSONObjBuilder() ); - _builders.push_back( b ); - b->appendAs(fe, e.fieldName()); - addBasic(b->done().firstElement(), op, isNot); - break; - } - case BSONObj::NE:{ - haveNeg = true; - shared_ptr< BSONObjBuilder > b( new BSONObjBuilder() ); - _builders.push_back( b ); - b->appendAs(fe, e.fieldName()); - addBasic(b->done().firstElement(), BSONObj::NE, isNot); - break; - } - case BSONObj::opALL: - all = true; - case BSONObj::opIN: - uassert( 13276 , "$in needs an array" , fe.isABSONObj() ); - basics.push_back( ElementMatcher( e , op , fe.embeddedObject(), isNot ) ); - break; - case BSONObj::NIN: - uassert( 13277 , "$nin needs an array" , fe.isABSONObj() ); - haveNeg = true; - basics.push_back( ElementMatcher( e , op , fe.embeddedObject(), isNot ) ); - break; - case BSONObj::opMOD: - case BSONObj::opTYPE: - case BSONObj::opELEM_MATCH: { - shared_ptr< BSONObjBuilder > b( new BSONObjBuilder() ); - _builders.push_back( b ); - b->appendAs(fe, e.fieldName()); - // these are types where ElementMatcher has all the info - basics.push_back( ElementMatcher( b->done().firstElement() , op, isNot ) ); - break; - } - case BSONObj::opSIZE:{ - shared_ptr< BSONObjBuilder > b( new BSONObjBuilder() ); - _builders.push_back( b ); - b->appendAs(fe, e.fieldName()); - addBasic(b->done().firstElement(), BSONObj::opSIZE, isNot); - haveSize = true; - break; - } - case BSONObj::opEXISTS:{ - shared_ptr< BSONObjBuilder > b( new BSONObjBuilder() ); - _builders.push_back( b ); - b->appendAs(fe, e.fieldName()); - addBasic(b->done().firstElement(), BSONObj::opEXISTS, isNot); - break; - } - case BSONObj::opREGEX:{ - uassert( 13032, "can't use $not with $regex, use BSON regex type instead", !isNot ); - if ( fe.type() == RegEx ){ - regex = fe.regex(); - flags = fe.regexFlags(); - } - else { - regex = fe.valuestrsafe(); - } - break; - } - case BSONObj::opOPTIONS:{ - uassert( 13029, "can't use $not with $options, use BSON regex type instead", !isNot ); - flags = fe.valuestrsafe(); - break; - } - case BSONObj::opNEAR: - case BSONObj::opWITHIN: - case BSONObj::opMAX_DISTANCE: - break; - default: - uassert( 10069 , (string)"BUG - can't operator for: " + fn , 0 ); - } + + switch ( op ) { + case BSONObj::GT: + case BSONObj::GTE: + case BSONObj::LT: + case BSONObj::LTE: { + shared_ptr< BSONObjBuilder > b( new BSONObjBuilder() ); + _builders.push_back( b ); + b->appendAs(fe, e.fieldName()); + addBasic(b->done().firstElement(), op, isNot); + break; + } + case BSONObj::NE: { + haveNeg = true; + shared_ptr< BSONObjBuilder > b( new BSONObjBuilder() ); + _builders.push_back( b ); + b->appendAs(fe, e.fieldName()); + addBasic(b->done().firstElement(), BSONObj::NE, isNot); + break; + } + case BSONObj::opALL: + all = true; + case BSONObj::opIN: + uassert( 13276 , "$in needs an array" , fe.isABSONObj() ); + basics.push_back( ElementMatcher( e , op , fe.embeddedObject(), isNot ) ); + break; + case BSONObj::NIN: + uassert( 13277 , "$nin needs an array" , fe.isABSONObj() ); + haveNeg = true; + basics.push_back( ElementMatcher( e , op , fe.embeddedObject(), isNot ) ); + break; + case BSONObj::opMOD: + case BSONObj::opTYPE: + case BSONObj::opELEM_MATCH: { + shared_ptr< BSONObjBuilder > b( new BSONObjBuilder() ); + _builders.push_back( b ); + b->appendAs(fe, e.fieldName()); + // these are types where ElementMatcher has all the info + basics.push_back( ElementMatcher( b->done().firstElement() , op, isNot ) ); + break; + } + case BSONObj::opSIZE: { + shared_ptr< BSONObjBuilder > b( new BSONObjBuilder() ); + _builders.push_back( b ); + b->appendAs(fe, e.fieldName()); + addBasic(b->done().firstElement(), BSONObj::opSIZE, isNot); + haveSize = true; + break; + } + case BSONObj::opEXISTS: { + shared_ptr< BSONObjBuilder > b( new BSONObjBuilder() ); + _builders.push_back( b ); + b->appendAs(fe, e.fieldName()); + addBasic(b->done().firstElement(), BSONObj::opEXISTS, isNot); + break; + } + case BSONObj::opREGEX: { + uassert( 13032, "can't use $not with $regex, use BSON regex type instead", !isNot ); + if ( fe.type() == RegEx ) { + regex = fe.regex(); + flags = fe.regexFlags(); + } + else { + regex = fe.valuestrsafe(); + } + break; + } + case BSONObj::opOPTIONS: { + uassert( 13029, "can't use $not with $options, use BSON regex type instead", !isNot ); + flags = fe.valuestrsafe(); + break; + } + case BSONObj::opNEAR: + case BSONObj::opWITHIN: + case BSONObj::opMAX_DISTANCE: + break; + default: + uassert( 10069 , (string)"BUG - can't operator for: " + fn , 0 ); + } return true; } - + void Matcher::parseOr( const BSONElement &e, bool subMatcher, list< shared_ptr< Matcher > > &matchers ) { uassert( 13090, "nested $or/$nor not allowed", !subMatcher ); uassert( 13086, "$or/$nor must be a nonempty array", e.type() == Array && e.embeddedObject().nFields() > 0 ); @@ -286,14 +288,16 @@ namespace mongo { return false; if ( ef[ 1 ] == 'o' && ef[ 2 ] == 'r' && ef[ 3 ] == 0 ) { parseOr( e, subMatcher, _orMatchers ); - } else if ( ef[ 1 ] == 'n' && ef[ 2 ] == 'o' && ef[ 3 ] == 'r' && ef[ 4 ] == 0 ) { + } + else if ( ef[ 1 ] == 'n' && ef[ 2 ] == 'o' && ef[ 3 ] == 'r' && ef[ 4 ] == 0 ) { parseOr( e, subMatcher, _norMatchers ); - } else { + } + else { return false; } return true; } - + /* _jsobj - the query pattern */ Matcher::Matcher(const BSONObj &_jsobj, bool subMatcher) : @@ -302,7 +306,7 @@ namespace mongo { BSONObjIterator i(jsobj); while ( i.more() ) { BSONElement e = i.next(); - + if ( parseOrNor( e, subMatcher ) ) { continue; } @@ -311,7 +315,7 @@ namespace mongo { // $where: function()... uassert( 10066 , "$where occurs twice?", where == 0 ); uassert( 10067 , "$where query, but no script engine", globalScriptEngine ); - massert( 13089 , "no current client needed for $where" , haveClient() ); + massert( 13089 , "no current client needed for $where" , haveClient() ); where = new Where(); where->scope = globalScriptEngine->getPooledScope( cc().ns() ); where->scope->localConnect( cc().database()->name.c_str() ); @@ -324,7 +328,7 @@ namespace mongo { const char *code = e.valuestr(); where->setFunc(code); } - + where->scope->execSetup( "_mongo.readOnly = true;" , "make read only" ); continue; @@ -334,7 +338,7 @@ namespace mongo { addRegex( e.fieldName(), e.regex(), e.regexFlags() ); continue; } - + // greater than / less than... // e.g., e == { a : { $gt : 3 } } // or @@ -343,35 +347,36 @@ namespace mongo { // support {$regex:"a|b", $options:"imx"} const char* regex = NULL; const char* flags = ""; - + // e.g., fe == { $gt : 3 } BSONObjIterator j(e.embeddedObject()); bool isOperator = false; while ( j.more() ) { BSONElement fe = j.next(); const char *fn = fe.fieldName(); - + if ( fn[0] == '$' && fn[1] ) { isOperator = true; - + if ( fn[1] == 'n' && fn[2] == 'o' && fn[3] == 't' && fn[4] == 0 ) { haveNeg = true; switch( fe.type() ) { - case Object: { - BSONObjIterator k( fe.embeddedObject() ); - uassert( 13030, "$not cannot be empty", k.more() ); - while( k.more() ) { - addOp( e, k.next(), true, regex, flags ); - } - break; + case Object: { + BSONObjIterator k( fe.embeddedObject() ); + uassert( 13030, "$not cannot be empty", k.more() ); + while( k.more() ) { + addOp( e, k.next(), true, regex, flags ); } - case RegEx: - addRegex( e.fieldName(), fe.regex(), fe.regexFlags(), true ); - break; - default: - uassert( 13031, "invalid use of $not", false ); + break; + } + case RegEx: + addRegex( e.fieldName(), fe.regex(), fe.regexFlags(), true ); + break; + default: + uassert( 13031, "invalid use of $not", false ); } - } else { + } + else { if ( !addOp( e, fe, false, regex, flags ) ) { isOperator = false; break; @@ -383,43 +388,43 @@ namespace mongo { break; } } - if (regex){ + if (regex) { addRegex(e.fieldName(), regex, flags); } if ( isOperator ) continue; } - if ( e.type() == Array ){ + if ( e.type() == Array ) { hasArray = true; } else if( strcmp(e.fieldName(), "$atomic") == 0 ) { _atomic = e.trueValue(); continue; } - + // normal, simple case e.g. { a : "foo" } addBasic(e, BSONObj::Equality, false); } } - + Matcher::Matcher( const Matcher &other, const BSONObj &key ) : - where(0), constrainIndexKey_( key ), haveSize(), all(), hasArray(0), haveNeg(), _atomic(false), nRegex(0) { + where(0), constrainIndexKey_( key ), haveSize(), all(), hasArray(0), haveNeg(), _atomic(false), nRegex(0) { // do not include fields which would make keyMatch() false for( vector< ElementMatcher >::const_iterator i = other.basics.begin(); i != other.basics.end(); ++i ) { if ( key.hasField( i->toMatch.fieldName() ) ) { switch( i->compareOp ) { - case BSONObj::opSIZE: - case BSONObj::opALL: - case BSONObj::NE: - case BSONObj::NIN: - break; - default: { - if ( !i->isNot && i->toMatch.type() != Array ) { - basics.push_back( *i ); - } + case BSONObj::opSIZE: + case BSONObj::opALL: + case BSONObj::NE: + case BSONObj::NIN: + break; + default: { + if ( !i->isNot && i->toMatch.type() != Array ) { + basics.push_back( *i ); } } + } } } for( int i = 0; i < other.nRegex; ++i ) { @@ -431,29 +436,29 @@ namespace mongo { _orMatchers.push_back( shared_ptr< Matcher >( new Matcher( **i, key ) ) ); } } - + inline bool regexMatches(const RegexMatcher& rm, const BSONElement& e) { - switch (e.type()){ - case String: - case Symbol: - if (rm.prefix.empty()) - return rm.re->PartialMatch(e.valuestr()); - else - return !strncmp(e.valuestr(), rm.prefix.c_str(), rm.prefix.size()); - case RegEx: - return !strcmp(rm.regex, e.regex()) && !strcmp(rm.flags, e.regexFlags()); - default: - return false; + switch (e.type()) { + case String: + case Symbol: + if (rm.prefix.empty()) + return rm.re->PartialMatch(e.valuestr()); + else + return !strncmp(e.valuestr(), rm.prefix.c_str(), rm.prefix.size()); + case RegEx: + return !strcmp(rm.regex, e.regex()) && !strcmp(rm.flags, e.regexFlags()); + default: + return false; } } - + inline int Matcher::valuesMatch(const BSONElement& l, const BSONElement& r, int op, const ElementMatcher& bm) { assert( op != BSONObj::NE && op != BSONObj::NIN ); - + if ( op == BSONObj::Equality ) { return l.valuesEqual(r); } - + if ( op == BSONObj::opIN ) { // { $in : [1,2,3] } int count = bm.myset->count(l); @@ -481,15 +486,15 @@ namespace mongo { } return count == r.number(); } - - if ( op == BSONObj::opMOD ){ + + if ( op == BSONObj::opMOD ) { if ( ! l.isNumber() ) return false; - + return l.numberLong() % bm.mod == bm.modm; } - - if ( op == BSONObj::opTYPE ){ + + if ( op == BSONObj::opTYPE ) { return bm.type == l.type(); } @@ -516,7 +521,7 @@ namespace mongo { return 0; return bm.toMatch.boolean() ? -1 : 1; } - + /* Check if a particular field matches. fieldName - field to match "a.b" if we are reaching into an embedded object. @@ -529,8 +534,8 @@ namespace mongo { { "a.b" : 3 } means obj.a.b == 3 { a : { $lt : 3 } } means obj.a < 3 - { a : { $in : [1,2] } } means [1,2].contains(obj.a) - + { a : { $in : [1,2] } } means [1,2].contains(obj.a) + return value -1 mismatch 0 missing element @@ -539,20 +544,20 @@ namespace mongo { int Matcher::matchesDotted(const char *fieldName, const BSONElement& toMatch, const BSONObj& obj, int compareOp, const ElementMatcher& em , bool isArr, MatchDetails * details ) { DEBUGMATCHER( "\t matchesDotted : " << fieldName << " hasDetails: " << ( details ? "yes" : "no" ) ); if ( compareOp == BSONObj::opALL ) { - - if ( em.allMatchers.size() ){ + + if ( em.allMatchers.size() ) { BSONElement e = obj.getFieldDotted( fieldName ); uassert( 13021 , "$all/$elemMatch needs to be applied to array" , e.type() == Array ); - - for ( unsigned i=0; i<em.allMatchers.size(); i++ ){ + + for ( unsigned i=0; i<em.allMatchers.size(); i++ ) { bool found = false; BSONObjIterator x( e.embeddedObject() ); - while ( x.more() ){ + while ( x.more() ) { BSONElement f = x.next(); if ( f.type() != Object ) continue; - if ( em.allMatchers[i]->matches( f.embeddedObject() ) ){ + if ( em.allMatchers[i]->matches( f.embeddedObject() ) ) { found = true; break; } @@ -561,28 +566,28 @@ namespace mongo { if ( ! found ) return -1; } - + return 1; } - + if ( em.myset->size() == 0 && !em.myregex.get() ) return -1; // is this desired? - + BSONElementSet myValues; obj.getFieldsDotted( fieldName , myValues ); - + for( set< BSONElement, element_lt >::const_iterator i = em.myset->begin(); i != em.myset->end(); ++i ) { // ignore nulls if ( i->type() == jstNULL ) continue; - + if ( myValues.count( *i ) == 0 ) return -1; - } + } if ( !em.myregex.get() ) return 1; - + for( vector< RegexMatcher >::const_iterator i = em.myregex->begin(); i != em.myregex->end(); ++i ) { bool match = false; for( BSONElementSet::const_iterator j = myValues.begin(); j != myValues.end(); ++j ) { @@ -594,10 +599,10 @@ namespace mongo { if ( !match ) return -1; } - + return 1; } // end opALL - + if ( compareOp == BSONObj::NE ) return matchesNe( fieldName, toMatch, obj, em , details ); if ( compareOp == BSONObj::NIN ) { @@ -619,18 +624,19 @@ namespace mongo { } return 1; } - + BSONElement e; bool indexed = !constrainIndexKey_.isEmpty(); if ( indexed ) { e = obj.getFieldUsingIndexNames(fieldName, constrainIndexKey_); - if( e.eoo() ){ + if( e.eoo() ) { cout << "obj: " << obj << endl; cout << "fieldName: " << fieldName << endl; cout << "constrainIndexKey_: " << constrainIndexKey_ << endl; assert( !e.eoo() ); } - } else { + } + else { const char *p = strchr(fieldName, '.'); if ( p ) { @@ -668,7 +674,7 @@ namespace mongo { if ( details ) details->elemMatchKey = z.fieldName(); return 1; - } + } else if ( cmp < 0 ) { found = true; } @@ -677,7 +683,7 @@ namespace mongo { return found ? -1 : retMissing( em ); } - if( p ) { + if( p ) { return retMissing( em ); } else { @@ -687,25 +693,27 @@ namespace mongo { if ( compareOp == BSONObj::opEXISTS ) { return ( e.eoo() ^ ( toMatch.boolean() ^ em.isNot ) ) ? 1 : -1; - } else if ( ( e.type() != Array || indexed || compareOp == BSONObj::opSIZE ) && - valuesMatch(e, toMatch, compareOp, em ) ) { + } + else if ( ( e.type() != Array || indexed || compareOp == BSONObj::opSIZE ) && + valuesMatch(e, toMatch, compareOp, em ) ) { return 1; - } else if ( e.type() == Array && compareOp != BSONObj::opSIZE ) { + } + else if ( e.type() == Array && compareOp != BSONObj::opSIZE ) { BSONObjIterator ai(e.embeddedObject()); while ( ai.moreWithEOO() ) { BSONElement z = ai.next(); - - if ( compareOp == BSONObj::opELEM_MATCH ){ - if ( z.type() == Object ){ - if ( em.subMatcher->matches( z.embeddedObject() ) ){ + + if ( compareOp == BSONObj::opELEM_MATCH ) { + if ( z.type() == Object ) { + if ( em.subMatcher->matches( z.embeddedObject() ) ) { if ( details ) details->elemMatchKey = z.fieldName(); return 1; } } - else if ( em.subMatcherOnPrimitives ){ - if ( z.type() && em.subMatcher->matches( z.wrap( "" ) ) ){ + else if ( em.subMatcherOnPrimitives ) { + if ( z.type() && em.subMatcher->matches( z.wrap( "" ) ) ) { if ( details ) details->elemMatchKey = z.fieldName(); return 1; @@ -721,12 +729,12 @@ namespace mongo { } } - - if ( compareOp == BSONObj::Equality && e.woCompare( toMatch , false ) == 0 ){ + + if ( compareOp == BSONObj::Equality && e.woCompare( toMatch , false ) == 0 ) { // match an entire array to itself return 1; } - + } else if ( e.eoo() ) { // 0 indicates "missing element" @@ -759,7 +767,8 @@ namespace mongo { if ( ( bm.compareOp == BSONObj::NE ) ^ bm.isNot ) { return false; } - } else { + } + else { if ( !bm.isNot ) { return false; } @@ -774,7 +783,8 @@ namespace mongo { BSONElement e = jsobj.getFieldUsingIndexNames(rm.fieldName, constrainIndexKey_); if ( !e.eoo() ) s.insert( e ); - } else { + } + else { jsobj.getFieldsDotted( rm.fieldName, s ); } bool match = false; @@ -784,11 +794,11 @@ namespace mongo { if ( !match ^ rm.isNot ) return false; } - + if ( _orMatchers.size() > 0 ) { bool match = false; for( list< shared_ptr< Matcher > >::const_iterator i = _orMatchers.begin(); - i != _orMatchers.end(); ++i ) { + i != _orMatchers.end(); ++i ) { // SERVER-205 don't submit details - we don't want to track field // matched within $or, and at this point we've already loaded the // whole document @@ -801,55 +811,56 @@ namespace mongo { return false; } } - + if ( _norMatchers.size() > 0 ) { for( list< shared_ptr< Matcher > >::const_iterator i = _norMatchers.begin(); - i != _norMatchers.end(); ++i ) { + i != _norMatchers.end(); ++i ) { // SERVER-205 don't submit details - we don't want to track field // matched within $nor, and at this point we've already loaded the // whole document if ( (*i)->matches( jsobj ) ) { return false; } - } + } } - + for( vector< shared_ptr< FieldRangeVector > >::const_iterator i = _orConstraints.begin(); - i != _orConstraints.end(); ++i ) { + i != _orConstraints.end(); ++i ) { if ( (*i)->matches( jsobj ) ) { return false; } } - + if ( where ) { if ( where->func == 0 ) { uassert( 10070 , "$where compile error", false); return false; // didn't compile } - - if ( where->jsScope ){ + + if ( where->jsScope ) { where->scope->init( where->jsScope ); } where->scope->setThis( const_cast< BSONObj * >( &jsobj ) ); where->scope->setObject( "obj", const_cast< BSONObj & >( jsobj ) ); where->scope->setBoolean( "fullObject" , true ); // this is a hack b/c fullObject used to be relevant - + int err = where->scope->invoke( where->func , BSONObj() , 1000 * 60 , false ); where->scope->setThis( 0 ); if ( err == -3 ) { // INVOKE_ERROR stringstream ss; - ss << "error on invocation of $where function:\n" + ss << "error on invocation of $where function:\n" << where->scope->getError(); uassert( 10071 , ss.str(), false); return false; - } else if ( err != 0 ) { // ! INVOKE_SUCCESS + } + else if ( err != 0 ) { // ! INVOKE_SUCCESS uassert( 10072 , "unknown error in invocation of $where function", false); - return false; + return false; } return where->scope->getBoolean( "return" ) != 0; } - + return true; } @@ -894,9 +905,9 @@ namespace mongo { } } return true; - } - - + } + + /*- just for testing -- */ #pragma pack(1) struct JSObj1 { @@ -960,7 +971,7 @@ namespace mongo { assert( !n.matches(j2) ); BSONObj j0 = BSONObj(); -// BSONObj j0((const char *) &js0); +// BSONObj j0((const char *) &js0); Matcher p(j0); assert( p.matches(j1) ); assert( p.matches(j2) ); @@ -973,7 +984,7 @@ namespace mongo { RXTest() { } - + void run() { /* static const boost::regex e("(\\d{4}[- ]){3}\\d{4}"); @@ -983,7 +994,7 @@ namespace mongo { */ int ret = 0; - + pcre_config( PCRE_CONFIG_UTF8 , &ret ); massert( 10342 , "pcre not compiled with utf8 support" , ret ); @@ -1001,7 +1012,7 @@ namespace mongo { pcre_config( PCRE_CONFIG_UNICODE_PROPERTIES , &ret ); if ( ! ret ) cout << "warning: some regex utf8 things will not work. pcre build doesn't have --enable-unicode-properties" << endl; - + } } rxtest; |