mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 09:32:32 +01:00
SERVER-2977 assert rather than crash on invalid cursor access
This commit is contained in:
parent
f3a9c31c5c
commit
217b88af17
@ -478,8 +478,9 @@ namespace mongo {
|
||||
* @return a cursor interface to the query optimizer. The implementation may
|
||||
* utilize a single query plan or interleave results from multiple query
|
||||
* plans before settling on a single query plan. Note that the schema of
|
||||
* currKey() documents may change over the course of iteration.
|
||||
*
|
||||
* currKey() documents, the matcher(), and the isMultiKey() nature of the
|
||||
* cursor may change over the course of iteration.
|
||||
*
|
||||
* This is a work in progress. Partial list of features not yet implemented:
|
||||
* - ordered/sorted document iteration
|
||||
* - yielding
|
||||
|
@ -97,16 +97,17 @@ namespace mongo {
|
||||
}
|
||||
|
||||
virtual bool ok() { return !currLoc().isNull(); }
|
||||
virtual Record* _current() { return currLoc().rec(); }
|
||||
virtual BSONObj current() { return currLoc().obj(); }
|
||||
virtual DiskLoc currLoc() {
|
||||
virtual Record* _current() { assertOk(); return currLoc().rec(); }
|
||||
virtual BSONObj current() { assertOk(); return currLoc().obj(); }
|
||||
virtual DiskLoc currLoc() { return _currLoc(); }
|
||||
DiskLoc _currLoc() const {
|
||||
if ( _takeover ) {
|
||||
return _takeover->currLoc();
|
||||
return _takeover->currLoc();
|
||||
}
|
||||
if ( _currOp ) {
|
||||
return _currOp->currLoc();
|
||||
}
|
||||
return DiskLoc();
|
||||
return DiskLoc();
|
||||
}
|
||||
virtual bool advance() {
|
||||
if ( _takeover ) {
|
||||
@ -131,7 +132,10 @@ namespace mongo {
|
||||
|
||||
return ok();
|
||||
}
|
||||
virtual BSONObj currKey() const { return _takeover ? _takeover->currKey() : _currOp->currKey(); }
|
||||
virtual BSONObj currKey() const {
|
||||
assertOk();
|
||||
return _takeover ? _takeover->currKey() : _currOp->currKey();
|
||||
}
|
||||
|
||||
virtual DiskLoc refLoc() { return DiskLoc(); }
|
||||
|
||||
@ -141,6 +145,7 @@ namespace mongo {
|
||||
virtual string toString() { return "QueryOptimizerCursor"; }
|
||||
|
||||
virtual bool getsetdup(DiskLoc loc) {
|
||||
assertOk();
|
||||
if ( !_takeover ) {
|
||||
return getsetdupInternal( loc );
|
||||
}
|
||||
@ -150,18 +155,28 @@ namespace mongo {
|
||||
return _takeover->getsetdup( loc );
|
||||
}
|
||||
|
||||
virtual bool isMultiKey() const { return _takeover ? _takeover->isMultiKey() : _currOp->cursor()->isMultiKey(); }
|
||||
virtual bool isMultiKey() const {
|
||||
assertOk();
|
||||
return _takeover ? _takeover->isMultiKey() : _currOp->cursor()->isMultiKey();
|
||||
}
|
||||
|
||||
virtual bool modifiedKeys() const { return true; }
|
||||
|
||||
virtual long long nscanned() { return -1; }
|
||||
|
||||
virtual CoveredIndexMatcher *matcher() const { return _takeover ? _takeover->matcher() : _currOp->matcher().get(); }
|
||||
virtual CoveredIndexMatcher *matcher() const {
|
||||
assertOk();
|
||||
return _takeover ? _takeover->matcher() : _currOp->matcher().get();
|
||||
}
|
||||
|
||||
private:
|
||||
void assertOk() const {
|
||||
massert( 14809, "Invalid access for cursor that is not ok()", !_currLoc().isNull() );
|
||||
}
|
||||
|
||||
bool getsetdupInternal(const DiskLoc &loc) {
|
||||
pair<set<DiskLoc>::iterator, bool> p = _dups.insert(loc);
|
||||
return !p.second;
|
||||
return !p.second;
|
||||
}
|
||||
|
||||
bool getdupInternal(const DiskLoc &loc) {
|
||||
|
@ -996,6 +996,25 @@ namespace QueryOptimizerTests {
|
||||
shared_ptr<Cursor> _c;
|
||||
};
|
||||
|
||||
/** No results for empty collection. */
|
||||
class Empty : public Base {
|
||||
public:
|
||||
void run() {
|
||||
dblock lk;
|
||||
Client::Context ctx( ns() );
|
||||
shared_ptr<Cursor> c = newQueryOptimizerCursor( ns(), BSONObj() );
|
||||
ASSERT( !c->ok() );
|
||||
ASSERT_EXCEPTION( c->_current(), AssertionException );
|
||||
ASSERT_EXCEPTION( c->current(), AssertionException );
|
||||
ASSERT( c->currLoc().isNull() );
|
||||
ASSERT( !c->advance() );
|
||||
ASSERT_EXCEPTION( c->currKey(), AssertionException );
|
||||
ASSERT_EXCEPTION( c->getsetdup( DiskLoc() ), AssertionException );
|
||||
ASSERT_EXCEPTION( c->isMultiKey(), AssertionException );
|
||||
ASSERT_EXCEPTION( c->matcher(), AssertionException );
|
||||
}
|
||||
};
|
||||
|
||||
/** Basic test with two indexes and deduping requirement. */
|
||||
class Basic : public Base {
|
||||
public:
|
||||
@ -1642,6 +1661,7 @@ namespace QueryOptimizerTests {
|
||||
add<QueryPlanSetTests::EqualityThenIn>();
|
||||
add<QueryPlanSetTests::NotEqualityThenIn>();
|
||||
add<BestGuess>();
|
||||
add<QueryOptimizerCursorTests::Empty>();
|
||||
add<QueryOptimizerCursorTests::Basic>();
|
||||
add<QueryOptimizerCursorTests::NoMatch>();
|
||||
add<QueryOptimizerCursorTests::Interleaved>();
|
||||
|
Loading…
Reference in New Issue
Block a user