summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDwight <dmerriman@gmail.com>2008-06-02 22:33:42 -0400
committerDwight <dmerriman@gmail.com>2008-06-02 22:33:42 -0400
commit1c6210915469d1b4fb3e843e604f3d7ab87c1f9b (patch)
treed9c93018baa369de6565af846899ac79e00c31e5
parent9fba70e49f1ee1fb5be8c0fa02124784520d79d4 (diff)
downloadmongo-1c6210915469d1b4fb3e843e604f3d7ab87c1f9b.tar.gz
handle array case properly
-rw-r--r--db/jsobj.cpp86
-rw-r--r--db/jsobj.h5
-rw-r--r--db/testdb.js2
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() {