summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorU-tellus\cwestin <cwestin@10gen.com>2012-02-14 13:49:53 -0800
committerU-tellus\cwestin <cwestin@10gen.com>2012-02-14 18:03:03 -0800
commitc4bf7b30c13a5175752f9296dd8a2bbfad6a8242 (patch)
treea0c166018220422e26bf7017229670b242e58ac2 /src/mongo/db
parent59e9b72297906e68686c1ffeb2244736ecac945b (diff)
downloadmongo-c4bf7b30c13a5175752f9296dd8a2bbfad6a8242.tar.gz
checkpoint work for SERVER-4644
Diffstat (limited to 'src/mongo/db')
-rwxr-xr-xsrc/mongo/db/matcher.cpp181
-rw-r--r--src/mongo/db/matcher.h23
-rwxr-xr-xsrc/mongo/db/pipeline/document_source.cpp3
-rwxr-xr-xsrc/mongo/db/pipeline/document_source.h2
-rwxr-xr-xsrc/mongo/db/pipeline/document_source_match.cpp6
5 files changed, 196 insertions, 19 deletions
diff --git a/src/mongo/db/matcher.cpp b/src/mongo/db/matcher.cpp
index cc00ad4b2b6..c49b5e84771 100755
--- a/src/mongo/db/matcher.cpp
+++ b/src/mongo/db/matcher.cpp
@@ -724,13 +724,13 @@ namespace mongo {
if( strcmp(z.fieldName(),fieldName) == 0 ) {
if ( compareOp == BSONObj::opEXISTS ) {
- return retExistsFound( em );
+ return retExistsFound( em );
}
if (valuesMatch(z, toMatch, compareOp, em) ) {
- // "field.<n>" array notation was used
- if ( details )
- details->_elemMatchKey = z.fieldName();
- return 1;
+ // "field.<n>" array notation was used
+ if ( details )
+ details->_elemMatchKey = z.fieldName();
+ return 1;
}
}
@@ -761,9 +761,9 @@ namespace mongo {
if ( compareOp == BSONObj::opEXISTS ) {
if( e.eoo() ) {
- return 0;
+ return 0;
} else {
- return retExistsFound( em );
+ return retExistsFound( em );
}
}
else if ( ( e.type() != Array || indexed || compareOp == BSONObj::opSIZE ) &&
@@ -807,7 +807,7 @@ namespace mongo {
return 1;
}
if ( compareOp == BSONObj::opIN && valuesMatch( e, toMatch, compareOp, em ) ) {
- return 1;
+ return 1;
}
}
else if ( e.eoo() ) {
@@ -821,6 +821,12 @@ namespace mongo {
/* See if an object matches the query.
*/
bool Matcher::matches(const BSONObj& jsobj , MatchDetails * details ) const {
+ /*
+ NB: if any modifications are made to how this operates, make sure
+ they are reflected in visitReferences(), whose implementation
+ parallels this.
+ */
+
LOG(5) << "Matcher::matches() " << jsobj.toString() << endl;
/* assuming there is usually only one thing to match. if more this
@@ -857,8 +863,8 @@ namespace mongo {
}
for (vector<RegexMatcher>::const_iterator it = _regexs.begin();
- it != _regexs.end();
- ++it) {
+ it != _regexs.end();
+ ++it) {
BSONElementSet s;
if ( !_constrainIndexKey.isEmpty() ) {
BSONElement e = jsobj.getFieldUsingIndexNames(it->_fieldName, _constrainIndexKey);
@@ -866,10 +872,10 @@ namespace mongo {
// Should only have keys nested one deep here, for geo-indices
// TODO: future indices may nest deeper?
if( e.type() == Array ){
- BSONObjIterator i( e.Obj() );
- while( i.more() ){
- s.insert( i.next() );
- }
+ BSONObjIterator i( e.Obj() );
+ while( i.more() ){
+ s.insert( i.next() );
+ }
}
else if ( !e.eoo() )
s.insert( e );
@@ -964,13 +970,152 @@ namespace mongo {
return true;
}
+#ifdef MONGO_LATER_SERVER_4644
+ void Matcher::visitReferences(FieldSink *pSink) const {
+ // check normal non-regex cases:
+ for ( unsigned i = 0; i < _basics.size(); i++ ) {
+ const ElementMatcher& bm = _basics[i];
+ const BSONElement& m = bm._toMatch;
+ // -1=mismatch. 0=missing element. 1=match
+ int cmp = matchesDotted(m.fieldName(), m, jsobj, bm._compareOp, bm , false , details );
+ if ( cmp == 0 && bm._compareOp == BSONObj::opEXISTS ) {
+ // If missing, match cmp is opposite of $exists spec.
+ cmp = -retExistsFound(bm);
+ }
+ if ( bm._isNot )
+ cmp = -cmp;
+ if ( cmp < 0 )
+ return false;
+ if ( cmp == 0 ) {
+ /* missing is ok iff we were looking for null */
+ if ( m.type() == jstNULL || m.type() == Undefined ||
+ ( ( bm._compareOp == BSONObj::opIN || bm._compareOp == BSONObj::NIN ) && bm._myset->count( staticNull.firstElement() ) > 0 ) ) {
+ if ( bm.negativeCompareOp() ^ bm._isNot ) {
+ return false;
+ }
+ }
+ else {
+ if ( !bm._isNot ) {
+ return false;
+ }
+ }
+ }
+ }
+
+ for (vector<RegexMatcher>::const_iterator it = _regexs.begin();
+ it != _regexs.end();
+ ++it) {
+ BSONElementSet s;
+ if ( !_constrainIndexKey.isEmpty() ) {
+ BSONElement e = jsobj.getFieldUsingIndexNames(it->_fieldName, _constrainIndexKey);
+
+ // Should only have keys nested one deep here, for geo-indices
+ // TODO: future indices may nest deeper?
+ if( e.type() == Array ){
+ BSONObjIterator i( e.Obj() );
+ while( i.more() ){
+ s.insert( i.next() );
+ }
+ }
+ else if ( !e.eoo() )
+ s.insert( e );
+
+ }
+ else {
+ jsobj.getFieldsDotted( it->_fieldName, s );
+ }
+ bool match = false;
+ for( BSONElementSet::const_iterator i = s.begin(); i != s.end(); ++i )
+ if ( regexMatches(*it, *i) )
+ match = true;
+ if ( !match ^ it->_isNot )
+ return false;
+ }
+
+ if ( _orDedupConstraints.size() > 0 ) {
+ for( vector< shared_ptr< FieldRangeVector > >::const_iterator i = _orDedupConstraints.begin();
+ i != _orDedupConstraints.end(); ++i ) {
+ if ( (*i)->matches( jsobj ) ) {
+ return false;
+ }
+ }
+ }
+
+ if ( _andMatchers.size() > 0 ) {
+ for( list< shared_ptr< Matcher > >::const_iterator i = _andMatchers.begin();
+ i != _andMatchers.end(); ++i ) {
+ // SERVER-3192 Track field matched using details the same as for
+ // top level fields, at least for now.
+ if ( !(*i)->matches( jsobj, details ) ) {
+ return false;
+ }
+ }
+ }
+
+ if ( _orMatchers.size() > 0 ) {
+ bool match = false;
+ for( list< shared_ptr< Matcher > >::const_iterator i = _orMatchers.begin();
+ i != _orMatchers.end(); ++i ) {
+ // SERVER-205 don't submit details - we don't want to track field
+ // matched within $or
+ if ( (*i)->matches( jsobj ) ) {
+ match = true;
+ break;
+ }
+ }
+ if ( !match ) {
+ return false;
+ }
+ }
+
+ if ( _norMatchers.size() > 0 ) {
+ for( list< shared_ptr< Matcher > >::const_iterator i = _norMatchers.begin();
+ i != _norMatchers.end(); ++i ) {
+ // SERVER-205 don't submit details - we don't want to track field
+ // matched within $nor
+ if ( (*i)->matches( jsobj ) ) {
+ return false;
+ }
+ }
+ }
+
+ if ( _where ) {
+ if ( _where->func == 0 ) {
+ u_assert( 10070 , "$where compile error", false);
+ return false; // didn't compile
+ }
+
+ if ( _where->jsScope ) {
+ _where->scope->init( _where->jsScope );
+ }
+ _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 , 0, &jsobj , 1000 * 60 , false );
+ if ( err == -3 ) { // INVOKE_ERROR
+ stringstream ss;
+ ss << "error on invocation of $where function:\n"
+ << _where->scope->getError();
+ u_assert( 10071 , ss.str(), false);
+ return false;
+ }
+ else if ( err != 0 ) { // ! INVOKE_SUCCESS
+ u_assert( 10072 , "unknown error in invocation of $where function", false);
+ return false;
+ }
+ return _where->scope->getBoolean( "return" ) != 0;
+
+ }
+ }
+#endif /* MONGO_LATER_SERVER_4644 */
+
bool Matcher::keyMatch( const Matcher &docMatcher ) const {
// Quick check certain non key match cases.
if ( docMatcher._all
- || docMatcher._haveSize
- || docMatcher._hasArray // We can't match an array to its first indexed element using keymatch
- || docMatcher._haveNeg ) {
- return false;
+ || docMatcher._haveSize
+ || docMatcher._hasArray // We can't match an array to its first indexed element using keymatch
+ || docMatcher._haveNeg ) {
+ return false;
}
// Check that all match components are available in the index matcher.
diff --git a/src/mongo/db/matcher.h b/src/mongo/db/matcher.h
index b6994a79229..0678bb696ae 100644
--- a/src/mongo/db/matcher.h
+++ b/src/mongo/db/matcher.h
@@ -148,6 +148,27 @@ namespace mongo {
bool matches(const BSONObj& j, MatchDetails * details = 0 ) const;
+#ifdef MONGO_LATER_SERVER_4644
+ class FieldSink {
+ public:
+ virtual ~FieldSink() {};
+ virtual void referenceField(const string &fieldPath) = 0;
+ };
+
+ /**
+ Visit all of the fields that are referenced by this Matcher
+ (and any descendants).
+
+ This can be used to gather a list of all the references made by
+ this matcher. The implementation of this parallels that of
+ matches() above.
+
+ @param pSink a FieldSink that the caller will use to gather or
+ process the references
+ */
+ void visitReferences(FieldSink *pSink) const;
+#endif /* MONGO_LATER_SERVER_4644 */
+
bool atomic() const { return _atomic; }
string toString() const {
@@ -176,7 +197,7 @@ namespace mongo {
// return ( ( basics.size() + nRegex ) < 2 ) && !where && !_orMatchers.size() && !_norMatchers.size();
}
- const BSONObj *getQuery() const { return &_jsobj; };
+ const BSONObj *getQuery() const { return &_jsobj; };
private:
/**
diff --git a/src/mongo/db/pipeline/document_source.cpp b/src/mongo/db/pipeline/document_source.cpp
index 89177f58767..3a496875b9d 100755
--- a/src/mongo/db/pipeline/document_source.cpp
+++ b/src/mongo/db/pipeline/document_source.cpp
@@ -48,6 +48,9 @@ namespace mongo {
void DocumentSource::manageDependencies(
const intrusive_ptr<DependencyTracker> &pTracker) {
+#ifdef MONGO_LATER_SERVER_4644
+ assert(false); // identify any sources that need this but don't have it
+#endif /* MONGO_LATER_SERVER_4644 */
}
void DocumentSource::addToBsonArray(BSONArrayBuilder *pBuilder) const {
diff --git a/src/mongo/db/pipeline/document_source.h b/src/mongo/db/pipeline/document_source.h
index 6b547032801..acca4b2f7af 100755
--- a/src/mongo/db/pipeline/document_source.h
+++ b/src/mongo/db/pipeline/document_source.h
@@ -590,6 +590,8 @@ namespace mongo {
// virtuals from DocumentSource
virtual ~DocumentSourceMatch();
virtual const char *getSourceName() const;
+ virtual void manageDependencies(
+ const intrusive_ptr<DependencyTracker> &pTracker);
/**
Create a filter.
diff --git a/src/mongo/db/pipeline/document_source_match.cpp b/src/mongo/db/pipeline/document_source_match.cpp
index c02490e92da..6fc1b0b9f52 100755
--- a/src/mongo/db/pipeline/document_source_match.cpp
+++ b/src/mongo/db/pipeline/document_source_match.cpp
@@ -82,4 +82,10 @@ namespace mongo {
matcher(query) {
}
+ void DocumentSourceMatch::manageDependencies(
+ const intrusive_ptr<DependencyTracker> &pTracker) {
+#ifdef MONGO_LATER_SERVER_4644
+ assert(false); // $$$ implement dependencies on Matcher
+#endif /* MONGO_LATER_SERVER_4644 */
+ }
}