0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00
mongodb/db/query.cpp

283 lines
6.9 KiB
C++
Raw Normal View History

2007-10-20 01:35:48 +02:00
// query.cpp
#include "stdafx.h"
#include "query.h"
#include "pdfile.h"
#include "jsobj.h"
#include "../util/builder.h"
2007-11-04 22:17:44 +01:00
#include <time.h>
2007-11-05 02:47:12 +01:00
#include "introspect.h"
2007-11-10 22:46:30 +01:00
#include "btree.h"
2007-10-20 01:35:48 +02:00
int nextCursorId = 1;
2007-11-11 20:21:02 +01:00
/* todo: _ cache query plans
_ use index on partial match with the query
*/
auto_ptr<Cursor> getIndexCursor(const char *ns, JSObj& query, JSObj& order) {
NamespaceDetails *d = namespaceIndex.details(ns);
if( d == 0 ) return auto_ptr<Cursor>();
set<string> queryFields;
query.getFieldNames(queryFields);
if( !order.isEmpty() ) {
set<string> orderFields;
order.getFieldNames(orderFields);
// order by
for(int i = 0; i < d->nIndexes; i++ ) {
JSObj idxInfo = d->indexes[i].info.obj();
assert( strcmp(ns, idxInfo.getStringField("ns")) == 0 );
JSObj idxKey = idxInfo.getObjectField("key");
set<string> keyFields;
idxKey.getFieldNames(keyFields);
if( keyFields == orderFields ) {
2007-11-13 01:22:33 +01:00
bool reverse =
order.firstElement().type() == Number &&
order.firstElement().number() < 0;
2007-11-11 20:21:02 +01:00
JSObjBuilder b;
2007-11-13 01:22:33 +01:00
return auto_ptr<Cursor>(new BtreeCursor(d->indexes[i].head, reverse ? maxKey : JSObj(), reverse ? -1 : 1, false));
2007-11-11 20:21:02 +01:00
}
}
}
// where/query
for(int i = 0; i < d->nIndexes; i++ ) {
JSObj idxInfo = d->indexes[i].info.obj();
JSObj idxKey = idxInfo.getObjectField("key");
set<string> keyFields;
idxKey.getFieldNames(keyFields);
if( keyFields == queryFields ) {
JSObjBuilder b;
return auto_ptr<Cursor>(
2007-11-13 01:22:33 +01:00
new BtreeCursor(d->indexes[i].head, query.extractFields(idxKey, b), 1, true));
2007-11-11 20:21:02 +01:00
}
}
return auto_ptr<Cursor>();
}
2007-10-30 10:50:14 +01:00
void deleteObjects(const char *ns, JSObj pattern, bool justOne) {
cout << "delete ns:" << ns << " queryobjsize:" <<
pattern.objsize() << endl;
2007-11-03 02:30:40 +01:00
if( strncmp(ns, "system.", 7) == 0 ) {
cout << "ERROR: attempt to delete in system namespace " << ns << endl;
return;
}
2007-10-30 10:50:14 +01:00
JSMatcher matcher(pattern);
2007-11-11 20:21:02 +01:00
JSObj order;
auto_ptr<Cursor> c = getIndexCursor(ns, pattern, order);
if( c.get() == 0 )
c = theDataFileMgr.findAll(ns);
2007-11-02 03:34:44 +01:00
while( c->ok() ) {
Record *r = c->_current();
DiskLoc rloc = c->currLoc();
c->advance(); // must advance before deleting as the next ptr will die
2007-10-30 10:50:14 +01:00
JSObj js(r);
2007-11-11 20:21:02 +01:00
if( !matcher.matches(js) ) {
if( c->tempStopOnMiss() )
break;
}
else {
2007-10-30 10:50:14 +01:00
cout << " found match to delete" << endl;
2007-11-11 20:21:02 +01:00
if( !justOne )
c->noteLocation();
2007-10-30 10:50:14 +01:00
theDataFileMgr.deleteRecord(ns, r, rloc);
if( justOne )
return;
2007-11-11 20:21:02 +01:00
c->checkLocation();
2007-10-30 10:50:14 +01:00
}
}
}
void updateObjects(const char *ns, JSObj updateobj, JSObj pattern, bool upsert) {
cout << "update ns:" << ns << " objsize:" << updateobj.objsize() << " queryobjsize:" <<
2007-11-13 22:44:01 +01:00
pattern.objsize();
2007-10-30 10:50:14 +01:00
2007-11-03 02:30:40 +01:00
if( strncmp(ns, "system.", 7) == 0 ) {
2007-11-13 22:44:01 +01:00
cout << "\nERROR: attempt to update in system namespace " << ns << endl;
2007-11-03 02:30:40 +01:00
return;
}
2007-11-12 00:28:33 +01:00
{
JSMatcher matcher(pattern);
JSObj order;
auto_ptr<Cursor> c = getIndexCursor(ns, pattern, order);
if( c.get() == 0 )
c = theDataFileMgr.findAll(ns);
while( c->ok() ) {
Record *r = c->_current();
JSObj js(r);
if( !matcher.matches(js) ) {
if( c->tempStopOnMiss() )
break;
}
else {
2007-11-13 22:44:01 +01:00
cout << " found match to update" << endl;
2007-11-12 00:28:33 +01:00
theDataFileMgr.update(ns, r, c->currLoc(), updateobj.objdata(), updateobj.objsize());
return;
}
c->advance();
2007-10-30 10:50:14 +01:00
}
}
2007-11-13 22:44:01 +01:00
cout << " no match ";
2007-10-30 10:50:14 +01:00
if( upsert )
2007-11-13 22:44:01 +01:00
cout << "- upsert.";
2007-10-30 10:50:14 +01:00
cout << endl;
if( upsert )
theDataFileMgr.insert(ns, (void*) updateobj.objdata(), updateobj.objsize());
}
2007-11-05 04:34:37 +01:00
QueryResult* runQuery(const char *ns, int ntoreturn, JSObj jsobj, auto_ptr< set<string> > filter) {
2007-10-28 21:38:06 +01:00
cout << "runQuery ns:" << ns << " ntoreturn:" << ntoreturn << " queryobjsize:" <<
2007-11-13 22:44:01 +01:00
jsobj.objsize();
2007-10-20 01:35:48 +02:00
BufBuilder b;
2007-11-04 22:17:44 +01:00
2007-11-10 22:46:30 +01:00
JSObj query = jsobj.getObjectField("query");
JSObj order = jsobj.getObjectField("orderby");
if( query.isEmpty() && order.isEmpty() )
query = jsobj;
auto_ptr<JSMatcher> matcher(new JSMatcher(query));
2007-10-20 01:35:48 +02:00
QueryResult *qr = 0;
2007-10-28 21:38:06 +01:00
b.skip(sizeof(QueryResult));
2007-10-20 01:35:48 +02:00
int n = 0;
2007-11-05 02:47:12 +01:00
auto_ptr<Cursor> c = getSpecialCursor(ns);
2007-11-10 22:46:30 +01:00
if( c.get() == 0 )
c = getIndexCursor(ns, query, order);
2007-11-05 02:47:12 +01:00
if( c.get() == 0 )
2007-11-05 04:34:37 +01:00
c = theDataFileMgr.findAll(ns);
2007-11-02 03:34:44 +01:00
2007-11-04 22:17:44 +01:00
long long cursorid = 0;
2007-11-02 03:34:44 +01:00
while( c->ok() ) {
JSObj js = c->current();
2007-11-10 22:46:30 +01:00
if( !matcher->matches(js) ) {
if( c->tempStopOnMiss() )
break;
}
else {
2007-11-05 04:34:37 +01:00
bool ok = true;
if( filter.get() ) {
JSObj x;
ok = x.addFields(js, *filter) > 0;
if( ok )
b.append((void*) x.objdata(), x.objsize());
}
else {
b.append((void*) js.objdata(), js.objsize());
}
if( ok ) {
n++;
2007-11-05 17:55:03 +01:00
if( (ntoreturn>0 && (n >= ntoreturn || b.len() > 16*1024*1024)) ||
(ntoreturn==0 && b.len()>1*1024*1024) ) {
2007-11-05 04:34:37 +01:00
// more...so save a cursor
ClientCursor *cc = new ClientCursor();
cc->c = c;
cursorid = allocCursorId();
cc->cursorid = cursorid;
cc->matcher = matcher;
cc->ns = ns;
cc->pos = n;
2007-11-11 20:21:02 +01:00
ClientCursor::add(cc);
2007-11-05 04:34:37 +01:00
cc->updateLocation();
cc->filter = filter;
break;
}
2007-11-04 22:17:44 +01:00
}
2007-10-29 03:20:57 +01:00
}
2007-11-02 03:34:44 +01:00
c->advance();
2007-10-20 01:35:48 +02:00
}
qr = (QueryResult *) b.buf();
qr->len = b.len();
2007-11-18 03:10:00 +01:00
// qr->channel = 0;
2007-10-20 01:35:48 +02:00
qr->operation = opReply;
2007-11-04 22:17:44 +01:00
qr->cursorId = cursorid;
2007-10-28 19:42:59 +01:00
qr->startingFrom = 0;
2007-10-20 01:35:48 +02:00
qr->nReturned = n;
b.decouple();
2007-11-13 22:44:01 +01:00
cout << " nReturned:" << n << endl;
2007-10-20 01:35:48 +02:00
return qr;
}
2007-11-04 22:17:44 +01:00
QueryResult* getMore(const char *ns, int ntoreturn, long long cursorid) {
cout << "getMore ns:" << ns << " ntoreturn:" << ntoreturn << " cursorid:" <<
cursorid << endl;
BufBuilder b;
ClientCursor *cc = 0;
CCMap::iterator it = clientCursors.find(cursorid);
if( it == clientCursors.end() ) {
cout << "Cursor not found in map. cursorid: " << cursorid << endl;
}
else {
cc = it->second;
}
b.skip(sizeof(QueryResult));
int start = 0;
int n = 0;
if( cc ) {
start = cc->pos;
Cursor *c = cc->c.get();
while( 1 ) {
if( !c->ok() ) {
2007-11-10 22:46:30 +01:00
done:
2007-11-04 22:17:44 +01:00
// done! kill cursor.
cursorid = 0;
clientCursors.erase(it);
delete cc;
cc = 0;
break;
}
JSObj js = c->current();
2007-11-10 22:46:30 +01:00
if( !cc->matcher->matches(js) ) {
if( c->tempStopOnMiss() )
goto done;
}
else {
2007-11-05 04:34:37 +01:00
bool ok = true;
if( cc->filter.get() ) {
JSObj x;
ok = x.addFields(js, *cc->filter) > 0;
if( ok )
b.append((void*) x.objdata(), x.objsize());
}
else {
b.append((void*) js.objdata(), js.objsize());
}
if( ok ) {
n++;
2007-11-05 17:55:03 +01:00
if( (ntoreturn>0 && (n >= ntoreturn || b.len() > 16*1024*1024)) ||
(ntoreturn==0 && b.len()>1*1024*1024) ) {
2007-11-05 04:34:37 +01:00
cc->pos += n;
cc->updateLocation();
break;
}
2007-11-04 22:17:44 +01:00
}
}
}
c->advance();
}
QueryResult *qr = (QueryResult *) b.buf();
qr->cursorId = cursorid;
qr->startingFrom = start;
qr->len = b.len();
2007-11-18 03:10:00 +01:00
// qr->reserved = 0;
2007-11-04 22:17:44 +01:00
qr->operation = opReply;
qr->nReturned = n;
b.decouple();
return qr;
}