diff options
author | Dwight <dmerriman@gmail.com> | 2008-06-02 22:33:42 -0400 |
---|---|---|
committer | Dwight <dmerriman@gmail.com> | 2008-06-02 22:33:42 -0400 |
commit | 1c6210915469d1b4fb3e843e604f3d7ab87c1f9b (patch) | |
tree | d9c93018baa369de6565af846899ac79e00c31e5 | |
parent | 9fba70e49f1ee1fb5be8c0fa02124784520d79d4 (diff) | |
download | mongo-1c6210915469d1b4fb3e843e604f3d7ab87c1f9b.tar.gz |
handle array case properly
-rw-r--r-- | db/jsobj.cpp | 86 | ||||
-rw-r--r-- | db/jsobj.h | 5 | ||||
-rw-r--r-- | db/testdb.js | 2 |
3 files changed, 84 insertions, 9 deletions
diff --git a/db/jsobj.cpp b/db/jsobj.cpp index a45d0eb4570..56cd9aa8722 100644 --- a/db/jsobj.cpp +++ b/db/jsobj.cpp @@ -399,6 +399,62 @@ inline int JSMatcher::valuesMatch(Element& l, Element& r, int op) { return (op & z);
}
+/* return value
+ -1 mismatch
+ 0 missing element
+ 1 match
+*/
+int JSMatcher::matchesDotted(const char *fieldName, Element& toMatch, JSObj& obj, int compareOp, bool *deep, bool isArr = false) {
+ {
+ const char *p = strchr(fieldName, '.');
+ if( p ) {
+ string left(fieldName, p-fieldName);
+
+ Element e = obj.getField(left.c_str());
+ if( e.eoo() )
+ return 0;
+ if( e.type() != Object && e.type() != Array )
+ return -1;
+
+ return matchesDotted(p+1, toMatch, e.embeddedObject(), compareOp, deep, e.type() == Array);
+ }
+ }
+
+ Element e = obj.getField(fieldName);
+
+ if( valuesMatch(e, toMatch, compareOp) ) {
+ return 1;
+ }
+ else if( e.type() == Array ) {
+ JSElemIter ai(e.embeddedObject());
+ while( ai.more() ) {
+ Element z = ai.next();
+ if( valuesMatch( z, toMatch, compareOp) ) {
+ if( deep )
+ *deep = true;
+ return 1;
+ }
+ }
+ }
+ else if( isArr ) {
+ JSElemIter ai(obj);
+ while( ai.more() ) {
+ Element z = ai.next();
+ if( z.type() == Object ) {
+ int cmp = matchesDotted(fieldName, toMatch, z.embeddedObject(), compareOp, deep);
+ if( cmp > 0 ) {
+ if( deep ) *deep = true;
+ return 1;
+ }
+ }
+ }
+ }
+ else if( e.eoo() ) {
+ return 0;
+ }
+ return -1;
+}
+
/* deep means we looked into arrays for a match */
bool JSMatcher::matches(JSObj& jsobj, bool *deep) {
if( deep )
@@ -435,8 +491,18 @@ bool JSMatcher::matches(JSObj& jsobj, bool *deep) { // check normal non-regex cases:
for( int i = 0; i < n; i++ ) {
Element& m = toMatch[i];
+
+ int cmp = matchesDotted(toMatch[i].fieldName(), toMatch[i], jsobj, compareOp[i], deep);
+
+ /* missing is ok iff we were looking for null */
+ if( cmp < 0 )
+ return false;
+ if( cmp == 0 && (m.type() != jstNULL && m.type() != Undefined ) )
+ return false;
+ }
- Element e = jsobj.getFieldDotted(m.fieldName());
+/*
+ Element e = jsobj.getFieldDotted(m.fieldName(), arrayElName);
if( !e.eoo() ) {
if( valuesMatch(e, m, compareOp[i]) ) {
goto ok;
@@ -454,15 +520,16 @@ bool JSMatcher::matches(JSObj& jsobj, bool *deep) { }
return false;
}
+*/
/* missing. that is ok iff we were looking for null */
- if( m.type() == jstNULL || m.type() == Undefined )
- ;
- else
- return false;
-ok:
- ;
- }
+// if( m.type() == jstNULL || m.type() == Undefined )
+// ;
+////// else
+// return false;
+//ok:
+// ;
+// }
if( where ) {
if( where->func == 0 )
@@ -601,7 +668,8 @@ const char * JSObj::getStringField(const char *name) { JSObj JSObj::getObjectField(const char *name) {
Element e = getField(name);
- return e.type() == Object ? e.embeddedObject() : JSObj();
+ JSType t = e.type();
+ return t == Object || t == Array ? e.embeddedObject() : JSObj();
}
int JSObj::getFieldNames(set<string>& fields) {
diff --git a/db/jsobj.h b/db/jsobj.h index cd00b0387d3..cf19609e995 100644 --- a/db/jsobj.h +++ b/db/jsobj.h @@ -399,6 +399,11 @@ class Where; */
class JSMatcher {
+ int matchesDotted(
+ const char *fieldName,
+ Element& toMatch, JSObj& obj,
+ int compareOp, bool *deep, bool isArr);
+
public:
enum {
Equality = 0,
diff --git a/db/testdb.js b/db/testdb.js index 3b7709c5650..46fe05b72ea 100644 --- a/db/testdb.js +++ b/db/testdb.js @@ -34,6 +34,7 @@ function noresult(c) { function testdots() { t.dots.remove({}); t.dots.save( { a: 3, b: { y: 4, z : 5 } } ); + t.dots.save( { a: 9, b: [ { y:88, z:0 } ] } ); oneresult( t.dots.find( { a:3 } ) ); oneresult( t.dots.find( { b: { y:4,z:5} } ) ); oneresult( t.dots.find( { a:3, b: { y:4,z:5} } ) ); @@ -41,6 +42,7 @@ function testdots() { oneresult( t.dots.find( { "b.y":4 } ) ); oneresult( t.dots.find( { "b.z":5 } ) ); noresult( t.dots.find( { "b.z":55 } ) ); + oneresult( t.dots.find( { "b.y":88 } ) ); } function testkeys() { |