From f5e4fe8cd62fbd65927112e8e6cfa98af2520bd7 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 2 Mar 2009 16:03:48 -0500 Subject: [PATCH] Key match checkpoint --- db/jsobj.cpp | 24 +++++++++++++++++++ db/jsobj.h | 2 ++ db/matcher.cpp | 52 ++++++++++-------------------------------- db/matcher.h | 1 + dbtests/querytests.cpp | 12 ++++++++++ 5 files changed, 51 insertions(+), 40 deletions(-) diff --git a/db/jsobj.cpp b/db/jsobj.cpp index 892d09577b9..d891d18eb73 100644 --- a/db/jsobj.cpp +++ b/db/jsobj.cpp @@ -836,6 +836,30 @@ namespace mongo { return b.obj(); } + BSONElement BSONObj::getFieldUsingIndexNames(const char *fieldName, const BSONObj &indexKey) const { + BSONObjIterator i( indexKey ); + int j = 0; + while( i.more() ) { + BSONElement f = i.next(); + if ( f.eoo() ) + return BSONElement(); + if ( strcmp( f.fieldName(), fieldName ) == 0 ) + break; + ++j; + } + BSONObjIterator k( *this ); + while( k.more() ) { + BSONElement g = k.next(); + if ( g.eoo() ) + return BSONElement(); + if ( j == 0 ) { + return g; + } + --j; + } + return BSONElement(); + } + int BSONObj::getIntField(const char *name) const { BSONElement e = getField(name); return e.isNumber() ? (int) e.number() : INT_MIN; diff --git a/db/jsobj.h b/db/jsobj.h index 9173bd85144..be3b175b1c9 100644 --- a/db/jsobj.h +++ b/db/jsobj.h @@ -599,6 +599,8 @@ namespace mongo { BSONObj filterFieldsUndotted(const BSONObj &filter, bool inFilter) const; + BSONElement getFieldUsingIndexNames(const char *fieldName, const BSONObj &indexKey) const; + /** @return the raw data of the object */ const char *objdata() const { return details->_objdata; diff --git a/db/matcher.cpp b/db/matcher.cpp index a245e2a4c98..dc6cf5d0595 100644 --- a/db/matcher.cpp +++ b/db/matcher.cpp @@ -120,15 +120,11 @@ namespace mongo { } bool KeyValJSMatcher::matches(const BSONObj &key, const DiskLoc &recLoc, bool *deep) { -// out() << "key: " << key << ", rec: " << BSONObj( recLoc.rec() ) << endl; -// out() << "keyMatch: " << keyMatcher_.matches( key ) << endl; -// out() << "recordMatch: " << recordMatcher_.matches( recLoc.rec() ) << endl; - bool ret = //return - keyMatcher_.matches(key, deep) ? - recordMatcher_.matches(recLoc.rec(), deep) : - false; -// out() << "ret: " << ret << endl; - return ret; + if ( !keyMatcher_.matches(key, deep) ) + return false; + if ( recordMatcher_.trivial() ) + return true; + return recordMatcher_.matches(recLoc.rec(), deep); } @@ -327,34 +323,9 @@ namespace mongo { */ int JSMatcher::matchesDotted(const char *fieldName, const BSONElement& toMatch, const BSONObj& obj, int compareOp, bool *deep, bool isArr) { BSONElement e; -// out() << "fieldName: " << fieldName << endl; -// out() << "constrain: " << constrainIndexKey_ << endl; -// out() << "obj: " << obj << endl; if ( !constrainIndexKey_.isEmpty() ) { - assert( e.eoo() ); - BSONObjIterator i( constrainIndexKey_ ); - int j = 0; - while( i.more() ) { - BSONElement f = i.next(); - if ( f.eoo() ) - break; - if ( strcmp( f.fieldName(), fieldName ) == 0 ) - break; - ++j; - } - BSONObjIterator k( obj ); - while( k.more() ) { - BSONElement g = k.next(); - if ( g.eoo() ) - break; - if ( j == 0 ) { - e = g; - break; - } - --j; - } + e = obj.getFieldUsingIndexNames(fieldName, constrainIndexKey_); assert( !e.eoo() ); -// out() << "idx e: " << e << endl; } else { const char *p = strchr(fieldName, '.'); if ( p ) { @@ -370,10 +341,8 @@ namespace mongo { return matchesDotted(p+1, toMatch, eo, compareOp, deep, e.type() == Array); } else { e = obj.getField(fieldName); -// out() << "getField: " << e << endl; } } -// out() << "e: " << e << endl; if ( valuesMatch(e, toMatch, compareOp) ) { return 1; @@ -460,9 +429,7 @@ namespace mongo { for ( int i = 0; i < n; i++ ) { BasicMatcher& bm = basics[i]; BSONElement& m = bm.toMatch; -// out() << "m: " << m << endl; // -1=mismatch. 0=missing element. 1=match -// out() << "m.fieldName: " << m.fieldName() << endl; int cmp = matchesDotted(m.fieldName(), m, jsobj, bm.compareOp, deep); if ( cmp < 0 ) return false; @@ -480,7 +447,12 @@ namespace mongo { for ( int r = 0; r < nRegex; r++ ) { RegexMatcher& rm = regexs[r]; - BSONElement e = jsobj.getFieldDotted(rm.fieldName); + out() << "matching regex" << endl; + BSONElement e; + if ( !constrainIndexKey_.isEmpty() ) + e = jsobj.getFieldUsingIndexNames(rm.fieldName, constrainIndexKey_); + else + e = jsobj.getFieldDotted(rm.fieldName); if ( e.eoo() ) return false; if ( !regexMatches(rm, e, deep) ) diff --git a/db/matcher.h b/db/matcher.h index 2dc4b210f86..450eb0de83e 100644 --- a/db/matcher.h +++ b/db/matcher.h @@ -107,6 +107,7 @@ namespace mongo { return n; } + bool trivial() const { return n == 0 && nRegex == 0 && where == 0; } private: void addBasic(BSONElement e, int c) { // TODO May want to selectively ignore these element types based on op type. diff --git a/dbtests/querytests.cpp b/dbtests/querytests.cpp index d5687326b2f..fc3d3b25ee1 100644 --- a/dbtests/querytests.cpp +++ b/dbtests/querytests.cpp @@ -114,6 +114,17 @@ namespace QueryTests { } }; + class CountIndexedRegex : public Base { + public: + void run() { + insert( "{\"a\":\"b\"}" ); + insert( "{\"a\":\"c\"}" ); + BSONObj cmd = fromjson( "{\"query\":{\"a\":/^b/}}" ); + string err; + ASSERT_EQUALS( 1, runCount( ns(), cmd, err ) ); + } + }; + class ClientBase { public: // NOTE: Not bothering to backup the old error record. @@ -213,6 +224,7 @@ namespace QueryTests { add< CountQuery >(); add< CountFields >(); add< CountQueryFields >(); + add< CountIndexedRegex >(); add< ModId >(); add< ModNonmodMix >(); add< InvalidMod >();