mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 09:32:32 +01:00
Merge branch 'master' of git@github.com:mongodb/mongo
This commit is contained in:
commit
98d67c5b0e
@ -224,10 +224,14 @@ namespace mongo {
|
||||
if ( !index_ )
|
||||
return theDataFileMgr.findAll( fbs_.ns() );
|
||||
else
|
||||
return auto_ptr< Cursor >( new BtreeCursor( *const_cast< IndexDetails* >( index_ ), startKey_, endKey_, direction_ ) );
|
||||
return auto_ptr< Cursor >( new BtreeCursor( *const_cast< IndexDetails* >( index_ ), startKey_, endKey_, direction_ >= 0 ? 1 : -1 ) );
|
||||
//TODO This constructor should really take a const ref to the index details.
|
||||
}
|
||||
|
||||
BSONObj QueryPlan::indexKey() const {
|
||||
return index_->keyPattern();
|
||||
}
|
||||
|
||||
QueryPlanSet::QueryPlanSet( const char *ns, const BSONObj &query, const BSONObj &order, const BSONElement *hint ) :
|
||||
fbs_( ns, query ) {
|
||||
NamespaceDetails *d = nsdetails( ns );
|
||||
@ -298,7 +302,6 @@ namespace mongo {
|
||||
threads.create_thread( r );
|
||||
}
|
||||
threads.join_all();
|
||||
cout << "really done" << endl;
|
||||
for( int i = 0; i < plans_.nPlans(); ++i )
|
||||
if ( ops[ i ]->done() )
|
||||
return ops[ i ];
|
||||
@ -308,21 +311,74 @@ namespace mongo {
|
||||
|
||||
class CountOp : public QueryOp {
|
||||
public:
|
||||
CountOp( const BSONObj &spec ) : spec_( spec ), count_() {}
|
||||
virtual void run( const QueryPlan &qp, QueryAborter &qa ) {
|
||||
for( int i = 0; i < 100000; ++i )
|
||||
BSONObj query = spec_.getObjectField("query");
|
||||
set< string > fields;
|
||||
spec_.getObjectField("fields").getFieldNames( fields );
|
||||
|
||||
auto_ptr<Cursor> c = qp.newCursor();
|
||||
|
||||
// TODO We could check if all fields in the key are in 'fields'
|
||||
if ( qp.exactKeyMatch() && fields.empty() ) {
|
||||
/* Here we only look at the btree keys to determine if a match, instead of looking
|
||||
into the records, which would be much slower.
|
||||
*/
|
||||
BtreeCursor *bc = dynamic_cast<BtreeCursor *>(c.get());
|
||||
if ( c->ok() && !query.woCompare( bc->currKeyNode().key, BSONObj(), false ) ) {
|
||||
BSONObj firstMatch = bc->currKeyNode().key;
|
||||
count_++;
|
||||
while ( c->advance() ) {
|
||||
qa.mayAbort();
|
||||
if ( !firstMatch.woEqual( bc->currKeyNode().key ) )
|
||||
break;
|
||||
count_++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto_ptr<JSMatcher> matcher(new JSMatcher(query, c->indexKeyPattern()));
|
||||
while ( c->ok() ) {
|
||||
qa.mayAbort();
|
||||
cout << "done" << endl;
|
||||
BSONObj js = c->current();
|
||||
bool deep;
|
||||
if ( !matcher->matches(js, &deep) ) {
|
||||
}
|
||||
else if ( !deep || !c->getsetdup(c->currLoc()) ) { // i.e., check for dups on deep items only
|
||||
bool match = true;
|
||||
for( set< string >::iterator i = fields.begin(); i != fields.end(); ++i ) {
|
||||
if ( js.getFieldDotted( i->c_str() ).eoo() ) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( match )
|
||||
++count_;
|
||||
}
|
||||
c->advance();
|
||||
}
|
||||
}
|
||||
virtual QueryOp *clone() const {
|
||||
return new CountOp( *this );
|
||||
}
|
||||
int count() const { return 1; }
|
||||
int count() const { return count_; }
|
||||
private:
|
||||
BSONObj spec_;
|
||||
int count_;
|
||||
};
|
||||
|
||||
int doCount( const char *ns, const BSONObj &cmd, string &err ) {
|
||||
BSONObj query = cmd.getObjectField("query");
|
||||
BSONObj fields = cmd.getObjectField("fields");
|
||||
// count of all objects
|
||||
if ( query.isEmpty() && fields.isEmpty() ) {
|
||||
NamespaceDetails *d = nsdetails( ns );
|
||||
massert( "ns missing", d );
|
||||
return d->nrecords;
|
||||
}
|
||||
QueryPlanSet qps( ns, query, emptyObj );
|
||||
auto_ptr< QueryOp > original( new CountOp () );
|
||||
auto_ptr< QueryOp > original( new CountOp( cmd ) );
|
||||
auto_ptr< QueryOp > o = qps.runOp( *original );
|
||||
return dynamic_cast< CountOp* >( o.get() )->count();
|
||||
}
|
||||
|
@ -93,6 +93,8 @@ namespace mongo {
|
||||
BSONObj startKey() const { return startKey_; }
|
||||
BSONObj endKey() const { return endKey_; }
|
||||
auto_ptr< Cursor > newCursor() const;
|
||||
BSONObj indexKey() const;
|
||||
const char *ns() const { return fbs_.ns(); }
|
||||
private:
|
||||
const FieldBoundSet &fbs_;
|
||||
const BSONObj &order_;
|
||||
@ -122,7 +124,7 @@ namespace mongo {
|
||||
|
||||
class QueryOp {
|
||||
public:
|
||||
QueryOp() : done_( false ) {}
|
||||
QueryOp() : done_() {}
|
||||
virtual ~QueryOp() {}
|
||||
virtual void run( const QueryPlan &qp, QueryAborter &qa ) = 0;
|
||||
virtual QueryOp *clone() const = 0;
|
||||
|
@ -506,7 +506,17 @@ namespace QueryOptimizerTests {
|
||||
Helpers::ensureIndex( ns(), BSON( "a" << 1 ), "a_1" );
|
||||
Helpers::ensureIndex( ns(), BSON( "b" << 1 ), "b_1" );
|
||||
string err;
|
||||
doCount( ns(), BSON( "query" << BSON( "a" << 4 ) ), err );
|
||||
ASSERT_EQUALS( 0, doCount( ns(), BSON( "query" << BSON( "a" << 4 ) ), err ) );
|
||||
BSONObj one = BSON( "a" << 1 );
|
||||
BSONObj four = BSON( "a" << 4 );
|
||||
theDataFileMgr.insert( ns(), one );
|
||||
ASSERT_EQUALS( 0, doCount( ns(), BSON( "query" << BSON( "a" << 4 ) ), err ) );
|
||||
theDataFileMgr.insert( ns(), four );
|
||||
ASSERT_EQUALS( 1, doCount( ns(), BSON( "query" << BSON( "a" << 4 ) ), err ) );
|
||||
theDataFileMgr.insert( ns(), four );
|
||||
ASSERT_EQUALS( 2, doCount( ns(), BSON( "query" << BSON( "a" << 4 ) ), err ) );
|
||||
ASSERT_EQUALS( 3, doCount( ns(), BSON( "query" << emptyObj ), err ) );
|
||||
ASSERT_EQUALS( 3, doCount( ns(), BSON( "query" << BSON( "a" << GT << 0 ) ), err ) );
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user