Permalink
Browse files

compound $lt $gt statements now work, but query optimizer needs to be…

… smarter
  • Loading branch information...
1 parent f0eb45a commit 258be59a7963ca172094a4c672032d7d3a03d690 @dwight dwight committed Jul 17, 2008
Showing with 60 additions and 30 deletions.
  1. +44 −30 db/jsobj.cpp
  2. +16 −0 db/query.cpp
View
@@ -363,45 +363,59 @@ JSMatcher::JSMatcher(JSObj &_jsobj) :
// { a : { $in : [1,2,3] } }
if( e.type() == Object ) {
// e.g., fe == { $gt : 3 }
- Element fe = e.embeddedObject().firstElement();
- const char *fn = fe.fieldName();
- if( fn[0] == '$' && fn[1] ) {
- if( fn[2] == 't' ) {
- int op = Equality;
- if( fn[1] == 'g' ) {
- if( fn[3] == 0 ) op = GT;
- else if( fn[3] == 'e' && fn[4] == 0 ) op = GTE;
- }
- else if( fn[1] == 'l' ) {
- if( fn[3] == 0 ) op = LT;
- else if( fn[3] == 'e' && fn[4] == 0 ) op = LTE;
+ JSElemIter j(e.embeddedObject());
+ bool ok = false;
+ while( j.more() ) {
+ Element fe = j.next();
+ if( fe.eoo() )
+ break;
+ // Element fe = e.embeddedObject().firstElement();
+ const char *fn = fe.fieldName();
+ if( fn[0] == '$' && fn[1] ) {
+ if( fn[2] == 't' ) {
+ int op = Equality;
+ if( fn[1] == 'g' ) {
+ if( fn[3] == 0 ) op = GT;
+ else if( fn[3] == 'e' && fn[4] == 0 ) op = GTE;
+ }
+ else if( fn[1] == 'l' ) {
+ if( fn[3] == 0 ) op = LT;
+ else if( fn[3] == 'e' && fn[4] == 0 ) op = LTE;
+ }
+ if( op && nBuilders < 8) {
+ JSObjBuilder *b = new JSObjBuilder();
+ builders[nBuilders++] = b;
+ b->appendAs(fe, e.fieldName());
+ toMatch.push_back( b->done().firstElement() );
+ compareOp.push_back(op);
+ n++;
+ ok = true;
+ }
}
- if( op && nBuilders < 8) {
- JSObjBuilder *b = new JSObjBuilder();
- builders[nBuilders++] = b;
- b->appendAs(fe, e.fieldName());
- toMatch.push_back( b->done().firstElement() );
- compareOp.push_back(op);
+ else if( fn[1] == 'i' && fn[2] == 'n' && fn[3] == 0 && fe.type() == Array ) {
+ // $in
+ assert( in == 0 ); // only one per query supported so far. finish...
+ in = new set<Element,element_lt>();
+ JSElemIter i(fe.embeddedObject());
+ while( i.more() )
+ in->insert(i.next());
+ toMatch.push_back(e); // not actually used at the moment
+ compareOp.push_back(opIN);
n++;
- continue;
+ ok = true;
}
}
- else if( fn[1] == 'i' && fn[2] == 'n' && fn[3] == 0 && fe.type() == Array ) {
- // $in
- assert( in == 0 ); // only one per query supported so far. finish...
- in = new set<Element,element_lt>();
- JSElemIter i(fe.embeddedObject());
- while( i.more() )
- in->insert(i.next());
- toMatch.push_back(e); // not actually used at the moment
- compareOp.push_back(opIN);
- n++;
- continue;
+ else {
+ ok = false;
+ break;
}
}
+ if( ok )
+ continue;
}
{
+ // normal, simple case e.g. { a : "foo" }
toMatch.push_back(e);
compareOp.push_back(Equality);
n++;
View
@@ -110,6 +110,22 @@ auto_ptr<Cursor> getIndexCursor(const char *ns, JSObj& query, JSObj& order, bool
// $in does not use an index (at least yet, should when # of elems is tiny)
goto fail;
}
+
+ {
+ JSElemIter k(e.embeddedObject());
+ k.next();
+ if( !k.next().eoo() ) {
+ /* compound query like { $lt : 9, $gt : 2 }
+ for those our method below won't work.
+ need more work on "stopOnMiss" in general -- may
+ be issues with it. so fix this to use index after
+ that is fixed.
+ */
+ OCCASIONALLY cout << "finish query optimizer for lt gt compound\n";
+ goto fail;
+ }
+ }
+
int direction = - JSMatcher::opDirection(op);
return auto_ptr<Cursor>( new BtreeCursor(
d->indexes[i].head,

0 comments on commit 258be59

Please sign in to comment.