Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

SERVER-3373 query optimizer optimizations, primarily for non or queries

  • Loading branch information...
commit d58c4c23f6f2ff45f9cec2f3761becfaba13cbba 1 parent 53a69ce
@astaple astaple authored
View
80 db/queryoptimizer.cpp
@@ -52,7 +52,7 @@ namespace mongo {
QueryPlan::QueryPlan(
NamespaceDetails *d, int idxNo,
- const FieldRangeSetPair &frsp, const FieldRangeSetPair &originalFrsp, const BSONObj &originalQuery, const BSONObj &order, const BSONObj &startKey, const BSONObj &endKey , string special ) :
+ const FieldRangeSetPair &frsp, const FieldRangeSetPair *originalFrsp, const BSONObj &originalQuery, const BSONObj &order, const BSONObj &startKey, const BSONObj &endKey , string special ) :
_d(d), _idxNo(idxNo),
_frs( frsp.frsForIndex( _d, _idxNo ) ),
_frsMulti( frsp.frsForIndex( _d, -1 ) ),
@@ -166,12 +166,17 @@ namespace mongo {
_optimal = true;
if ( exactIndexedQueryCount == _frs.nNontrivialRanges() &&
orderFieldsUnindexed.size() == 0 &&
- exactIndexedQueryCount == _index->keyPattern().nFields() &&
+ exactIndexedQueryCount == idxKey.nFields() &&
exactIndexedQueryCount == _originalQuery.nFields() ) {
_exactKeyMatch = true;
}
_frv.reset( new FieldRangeVector( _frs, idxSpec, _direction ) );
- _originalFrv.reset( new FieldRangeVector( originalFrsp.frsForIndex( _d, _idxNo ), idxSpec, _direction ) );
+ if ( originalFrsp ) {
+ _originalFrv.reset( new FieldRangeVector( originalFrsp->frsForIndex( _d, _idxNo ), idxSpec, _direction ) );
+ }
+ else {
+ _originalFrv = _frv;
+ }
if ( _startOrEndSpec ) {
BSONObj newStart, newEnd;
if ( !startKey.isEmpty() )
@@ -328,7 +333,7 @@ namespace mongo {
massert( 10365 , errmsg, indexDetailsForRange( _frsp->ns(), errmsg, _min, _max, keyPattern ) );
}
NamespaceDetails *d = nsdetails(_ns);
- _plans.push_back( QueryPlanPtr( new QueryPlan( d, d->idxNo(id), *_frsp, *_originalFrsp, _originalQuery, _order, _min, _max ) ) );
+ _plans.push_back( QueryPlanPtr( new QueryPlan( d, d->idxNo(id), *_frsp, _originalFrsp.get(), _originalQuery, _order, _min, _max ) ) );
}
// returns an IndexDetails * for a hint, 0 if hint is $natural.
@@ -374,7 +379,7 @@ namespace mongo {
NamespaceDetails *d = nsdetails( ns );
if ( !d || !_frsp->matchPossible() ) {
// Table scan plan, when no matches are possible
- _plans.push_back( QueryPlanPtr( new QueryPlan( d, -1, *_frsp, *_originalFrsp, _originalQuery, _order ) ) );
+ _plans.push_back( QueryPlanPtr( new QueryPlan( d, -1, *_frsp, _originalFrsp.get(), _originalQuery, _order ) ) );
return;
}
@@ -388,7 +393,7 @@ namespace mongo {
else {
massert( 10366 , "natural order cannot be specified with $min/$max", _min.isEmpty() && _max.isEmpty() );
// Table scan plan
- _plans.push_back( QueryPlanPtr( new QueryPlan( d, -1, *_frsp, *_originalFrsp, _originalQuery, _order ) ) );
+ _plans.push_back( QueryPlanPtr( new QueryPlan( d, -1, *_frsp, _originalFrsp.get(), _originalQuery, _order ) ) );
}
return;
}
@@ -398,7 +403,7 @@ namespace mongo {
BSONObj keyPattern;
IndexDetails *idx = indexDetailsForRange( ns, errmsg, _min, _max, keyPattern );
massert( 10367 , errmsg, idx );
- _plans.push_back( QueryPlanPtr( new QueryPlan( d, d->idxNo(*idx), *_frsp, *_originalFrsp, _originalQuery, _order, _min, _max ) ) );
+ _plans.push_back( QueryPlanPtr( new QueryPlan( d, d->idxNo(*idx), *_frsp, _originalFrsp.get(), _originalQuery, _order, _min, _max ) ) );
return;
}
@@ -407,13 +412,13 @@ namespace mongo {
if ( idx >= 0 ) {
_usingPrerecordedPlan = true;
_mayRecordPlan = false;
- _plans.push_back( QueryPlanPtr( new QueryPlan( d , idx , *_frsp , *_originalFrsp , _originalQuery, _order ) ) );
+ _plans.push_back( QueryPlanPtr( new QueryPlan( d , idx , *_frsp , _originalFrsp.get() , _originalQuery, _order ) ) );
return;
}
}
if ( _originalQuery.isEmpty() && _order.isEmpty() ) {
- _plans.push_back( QueryPlanPtr( new QueryPlan( d, -1, *_frsp, *_originalFrsp, _originalQuery, _order ) ) );
+ _plans.push_back( QueryPlanPtr( new QueryPlan( d, -1, *_frsp, _originalFrsp.get(), _originalQuery, _order ) ) );
return;
}
@@ -428,7 +433,7 @@ namespace mongo {
if ( spec.getTypeName() == _special && spec.suitability( _originalQuery , _order ) ) {
_usingPrerecordedPlan = true;
_mayRecordPlan = false;
- _plans.push_back( QueryPlanPtr( new QueryPlan( d , j , *_frsp , *_originalFrsp , _originalQuery, _order ,
+ _plans.push_back( QueryPlanPtr( new QueryPlan( d , j , *_frsp , _originalFrsp.get() , _originalQuery, _order ,
BSONObj() , BSONObj() , _special ) ) );
return;
}
@@ -445,7 +450,7 @@ namespace mongo {
_oldNScanned = oldNScanned;
if ( !strcmp( bestIndex.firstElementFieldName(), "$natural" ) ) {
// Table scan plan
- p.reset( new QueryPlan( d, -1, *_frsp, *_originalFrsp, _originalQuery, _order ) );
+ p.reset( new QueryPlan( d, -1, *_frsp, _originalFrsp.get(), _originalQuery, _order ) );
}
NamespaceDetails::IndexIterator i = d->ii();
@@ -453,7 +458,7 @@ namespace mongo {
int j = i.pos();
IndexDetails& ii = i.next();
if( ii.keyPattern().woCompare(bestIndex) == 0 ) {
- p.reset( new QueryPlan( d, j, *_frsp, *_originalFrsp, _originalQuery, _order ) );
+ p.reset( new QueryPlan( d, j, *_frsp, _originalFrsp.get(), _originalQuery, _order ) );
}
}
@@ -480,7 +485,7 @@ namespace mongo {
if ( !_frsp->matchPossible() || ( _frsp->noNontrivialRanges() && _order.isEmpty() ) ||
( !_order.isEmpty() && !strcmp( _order.firstElementFieldName(), "$natural" ) ) ) {
// Table scan plan
- addPlan( QueryPlanPtr( new QueryPlan( d, -1, *_frsp, *_originalFrsp, _originalQuery, _order ) ), checkFirst );
+ addPlan( QueryPlanPtr( new QueryPlan( d, -1, *_frsp, _originalFrsp.get(), _originalQuery, _order ) ), checkFirst );
return;
}
@@ -490,10 +495,11 @@ namespace mongo {
QueryPlanPtr optimalPlan;
for( int i = 0; i < d->nIndexes; ++i ) {
if ( normalQuery ) {
- if ( !_frsp->matchPossibleForIndex( d, i, d->idx( i ).keyPattern() ) ) {
+ BSONObj keyPattern = d->idx( i ).keyPattern();
+ if ( !_frsp->matchPossibleForIndex( d, i, keyPattern ) ) {
// If no match is possible, only generate a trival plan that won't
// scan any documents.
- QueryPlanPtr p( new QueryPlan( d, i, *_frsp, *_originalFrsp, _originalQuery, _order ) );
+ QueryPlanPtr p( new QueryPlan( d, i, *_frsp, _originalFrsp.get(), _originalQuery, _order ) );
addPlan( p, checkFirst );
return;
}
@@ -502,7 +508,7 @@ namespace mongo {
}
}
- QueryPlanPtr p( new QueryPlan( d, i, *_frsp, *_originalFrsp, _originalQuery, _order ) );
+ QueryPlanPtr p( new QueryPlan( d, i, *_frsp, _originalFrsp.get(), _originalQuery, _order ) );
if ( p->optimal() ) {
if ( !optimalPlan.get() ) {
optimalPlan = p;
@@ -520,7 +526,7 @@ namespace mongo {
addPlan( *i, checkFirst );
// Table scan plan
- addPlan( QueryPlanPtr( new QueryPlan( d, -1, *_frsp, *_originalFrsp, _originalQuery, _order ) ), checkFirst );
+ addPlan( QueryPlanPtr( new QueryPlan( d, -1, *_frsp, _originalFrsp.get(), _originalQuery, _order ) ), checkFirst );
}
shared_ptr<QueryOp> QueryPlanSet::runOp( QueryOp &op ) {
@@ -815,24 +821,29 @@ namespace mongo {
_ns( ns ),
_or( !query.getField( "$or" ).eoo() ),
_query( query.getOwned() ),
- _org( ns, _query ),
_i(),
_honorRecordedPlan( honorRecordedPlan ),
_bestGuessOnly( bestGuessOnly ),
_hint( ( hint && !hint->eoo() ) ? hint->wrap() : BSONObj() ),
_mayYield( mayYield ),
_tableScanned() {
- if ( !order.isEmpty() || !min.isEmpty() || !max.isEmpty() || !_org.getSpecial().empty() ) {
+ if ( !order.isEmpty() || !min.isEmpty() || !max.isEmpty() ) {
_or = false;
}
- if ( _or && uselessOr( _hint.firstElement() ) ) {
- _or = false;
+ if ( _or ) {
+ // Only construct an OrRangeGenerator if we may handle $or clauses.
+ _org.reset( new OrRangeGenerator( ns, _query ) );
+ if ( !_org->getSpecial().empty() ) {
+ _or = false;
+ }
+ if ( uselessOr( _hint.firstElement() ) ) {
+ _or = false;
+ }
}
// if _or == false, don't use or clauses for index selection
if ( !_or ) {
auto_ptr<FieldRangeSetPair> frsp( new FieldRangeSetPair( ns, _query, true ) );
- auto_ptr<FieldRangeSetPair> oldFrsp( new FieldRangeSetPair( *frsp ) );
- _currentQps.reset( new QueryPlanSet( ns, frsp, oldFrsp, _query, order, hint, honorRecordedPlan, min, max, _bestGuessOnly, _mayYield ) );
+ _currentQps.reset( new QueryPlanSet( ns, frsp, auto_ptr<FieldRangeSetPair>(), _query, order, hint, honorRecordedPlan, min, max, _bestGuessOnly, _mayYield ) );
}
else {
BSONElement e = _query.getField( "$or" );
@@ -847,8 +858,8 @@ namespace mongo {
return _currentQps->runOp( op );
}
++_i;
- auto_ptr<FieldRangeSetPair> frsp( _org.topFrsp() );
- auto_ptr<FieldRangeSetPair> originalFrsp( _org.topFrspOriginal() );
+ auto_ptr<FieldRangeSetPair> frsp( _org->topFrsp() );
+ auto_ptr<FieldRangeSetPair> originalFrsp( _org->topFrspOriginal() );
BSONElement hintElt = _hint.firstElement();
_currentQps.reset( new QueryPlanSet( _ns, frsp, originalFrsp, _query, BSONObj(), &hintElt, _honorRecordedPlan, BSONObj(), BSONObj(), _bestGuessOnly, _mayYield ) );
shared_ptr<QueryOp> ret( _currentQps->runOp( op ) );
@@ -856,7 +867,7 @@ namespace mongo {
_tableScanned = true;
} else {
// If the full table was scanned, don't bother popping the last or clause.
- _org.popOrClause( ret->qp().nsd(), ret->qp().idxNo(), ret->qp().indexed() ? ret->qp().indexKey() : BSONObj() );
+ _org->popOrClause( ret->qp().nsd(), ret->qp().idxNo(), ret->qp().indexed() ? ret->qp().indexKey() : BSONObj() );
}
return ret;
}
@@ -877,7 +888,7 @@ namespace mongo {
if ( op->qp().willScanTable() ) {
_tableScanned = true;
} else {
- _org.popOrClause( op->qp().nsd(), op->qp().idxNo(), op->qp().indexed() ? op->qp().indexKey() : BSONObj() );
+ _org->popOrClause( op->qp().nsd(), op->qp().idxNo(), op->qp().indexed() ? op->qp().indexKey() : BSONObj() );
}
return op;
}
@@ -887,8 +898,8 @@ namespace mongo {
shared_ptr<QueryOp> op;
while( mayRunMore() ) {
++_i;
- auto_ptr<FieldRangeSetPair> frsp( _org.topFrsp() );
- auto_ptr<FieldRangeSetPair> originalFrsp( _org.topFrspOriginal() );
+ auto_ptr<FieldRangeSetPair> frsp( _org->topFrsp() );
+ auto_ptr<FieldRangeSetPair> originalFrsp( _org->topFrspOriginal() );
BSONElement hintElt = _hint.firstElement();
_currentQps.reset( new QueryPlanSet( _ns, frsp, originalFrsp, _query, BSONObj(), &hintElt, _honorRecordedPlan, BSONObj(), BSONObj(), _bestGuessOnly, _mayYield ) );
op = nextOpHandleEndOfClause();
@@ -954,9 +965,9 @@ namespace mongo {
if ( !id ) {
return true;
}
- return QueryUtilIndexed::uselessOr( _org, nsd, nsd->idxNo( *id ) );
+ return QueryUtilIndexed::uselessOr( *_org, nsd, nsd->idxNo( *id ) );
}
- return QueryUtilIndexed::uselessOr( _org, nsd, -1 );
+ return QueryUtilIndexed::uselessOr( *_org, nsd, -1 );
}
MultiCursor::MultiCursor( const char *ns, const BSONObj &pattern, const BSONObj &order, shared_ptr<CursorOp> op, bool mayYield )
@@ -1199,12 +1210,13 @@ namespace mongo {
}
bool QueryUtilIndexed::indexUseful( const FieldRangeSetPair &frsp, NamespaceDetails *d, int idxNo, const BSONObj &order ) {
- frsp.assertValidIndex( d, idxNo );
- if ( !frsp.matchPossibleForIndex( d, idxNo, d->idx( idxNo ).keyPattern() ) ) {
+ DEV frsp.assertValidIndex( d, idxNo );
+ BSONObj keyPattern = d->idx( idxNo ).keyPattern();
+ if ( !frsp.matchPossibleForIndex( d, idxNo, keyPattern ) ) {
// No matches are possible in the index so the index may be useful.
return true;
}
- return d->idx( idxNo ).getSpec().suitability( frsp.simplifiedQueryForIndex( d, idxNo, d->idx( idxNo ).keyPattern() ), order ) != USELESS;
+ return d->idx( idxNo ).getSpec().suitability( frsp.simplifiedQueryForIndex( d, idxNo, keyPattern ), order ) != USELESS;
}
void QueryUtilIndexed::clearIndexesForPatterns( const FieldRangeSetPair &frsp, const BSONObj &order ) {
View
14 db/queryoptimizer.h
@@ -35,10 +35,13 @@ namespace mongo {
class QueryPlan : boost::noncopyable {
public:
+ /**
+ * @param originalFrsp - original constraints for this query clause. If null, frsp will be used instead.
+ */
QueryPlan(NamespaceDetails *d,
int idxNo, // -1 = no index
const FieldRangeSetPair &frsp,
- const FieldRangeSetPair &originalFrsp,
+ const FieldRangeSetPair *originalFrsp,
const BSONObj &originalQuery,
const BSONObj &order,
const BSONObj &startKey = BSONObj(),
@@ -245,6 +248,9 @@ namespace mongo {
typedef boost::shared_ptr<QueryPlan> QueryPlanPtr;
typedef vector<QueryPlanPtr> PlanSet;
+ /**
+ * @param originalFrsp - original constraints for this query clause; if null, frsp will be used.
+ */
QueryPlanSet( const char *ns,
auto_ptr<FieldRangeSetPair> frsp,
auto_ptr<FieldRangeSetPair> originalFrsp,
@@ -290,7 +296,7 @@ namespace mongo {
//for testing
const FieldRangeSetPair &frsp() const { return *_frsp; }
- const FieldRangeSetPair &originalFrsp() const { return *_originalFrsp; }
+ const FieldRangeSetPair *originalFrsp() const { return _originalFrsp.get(); }
bool modifiedKeys() const;
bool hasMultiKey() const;
@@ -420,7 +426,7 @@ namespace mongo {
shared_ptr<Cursor> singleCursor() const;
/** @return true iff more $or clauses need to be scanned. */
- bool mayRunMore() const { return _or ? ( !_tableScanned && !_org.orFinished() ) : _i == 0; }
+ bool mayRunMore() const { return _or ? ( !_tableScanned && !_org->orFinished() ) : _i == 0; }
/** @return non-$or version of explain output. */
BSONObj oldExplain() const { assertNotOr(); return _currentQps->explain(); }
/** @return true iff this is not a $or query and a plan is selected based on previous success of this plan. */
@@ -445,7 +451,7 @@ namespace mongo {
const char * _ns;
bool _or;
BSONObj _query;
- OrRangeGenerator _org;
+ shared_ptr<OrRangeGenerator> _org; // May be null in certain non $or query cases.
auto_ptr<QueryPlanSet> _currentQps;
int _i;
bool _honorRecordedPlan;
View
19 db/queryutil-inl.h
@@ -130,5 +130,24 @@ namespace mongo {
}
return ret;
}
+
+ inline bool FieldRangeSetPair::matchPossibleForIndex( NamespaceDetails *d, int idxNo, const BSONObj &keyPattern ) const {
+ assertValidIndexOrNoIndex( d, idxNo );
+ if ( !matchPossible() ) {
+ return false;
+ }
+ if ( idxNo < 0 ) {
+ // multi key matchPossible() is true, so return true.
+ return true;
+ }
+ return frsForIndex( d, idxNo ).matchPossibleForIndex( keyPattern );
+ }
+ inline void FieldRangeSetPair::assertValidIndexOrNoIndex( const NamespaceDetails *d, int idxNo ) const {
+ massert( 14049, "FieldRangeSetPair invalid index specified", idxNo >= -1 );
+ if ( idxNo >= 0 ) {
+ assertValidIndex( d, idxNo );
+ }
+ }
+
} // namespace mongo
View
95 db/queryutil.cpp
@@ -158,8 +158,10 @@ namespace mongo {
FieldRange::FieldRange( const BSONElement &e, bool singleKey, bool isNot, bool optimize )
: _singleKey( singleKey ) {
+ int op = e.getGtLtOp();
+
// NOTE with $not, we could potentially form a complementary set of intervals.
- if ( !isNot && !e.eoo() && e.type() != RegEx && e.getGtLtOp() == BSONObj::opIN ) {
+ if ( !isNot && !e.eoo() && e.type() != RegEx && op == BSONObj::opIN ) {
set<BSONElement,element_lt> vals;
vector<FieldRange> regexes;
uassert( 12580 , "invalid query" , e.isABSONObj() );
@@ -196,7 +198,7 @@ namespace mongo {
// A document array may be indexed by its first element, by undefined
// if it is empty, or as a full array if it is embedded within another
// array.
- if ( e.type() == Array && e.getGtLtOp() == BSONObj::Equality ) {
+ if ( e.type() == Array && op == BSONObj::Equality ) {
_intervals.push_back( FieldInterval(e) );
BSONElement temp = e.embeddedObject().firstElement();
@@ -227,8 +229,6 @@ namespace mongo {
if ( e.eoo() )
return;
- int op = e.getGtLtOp();
-
bool existsSpec = false;
if ( op == BSONObj::opEXISTS ) {
existsSpec = e.trueValue();
@@ -785,30 +785,32 @@ namespace mongo {
}
void FieldRangeSet::processQueryField( const BSONElement &e, bool optimize ) {
- if ( strcmp( e.fieldName(), "$and" ) == 0 ) {
- uassert( 14816 , "$and expression must be a nonempty array" , e.type() == Array && e.embeddedObject().nFields() > 0 );
- BSONObjIterator i( e.embeddedObject() );
- while( i.more() ) {
- BSONElement e = i.next();
- uassert( 14817 , "$and elements must be objects" , e.type() == Object );
- BSONObjIterator j( e.embeddedObject() );
- while( j.more() ) {
- processQueryField( j.next(), optimize );
- }
- }
- }
+ if ( e.fieldName()[ 0 ] == '$' ) {
+ if ( strcmp( e.fieldName(), "$and" ) == 0 ) {
+ uassert( 14816 , "$and expression must be a nonempty array" , e.type() == Array && e.embeddedObject().nFields() > 0 );
+ BSONObjIterator i( e.embeddedObject() );
+ while( i.more() ) {
+ BSONElement e = i.next();
+ uassert( 14817 , "$and elements must be objects" , e.type() == Object );
+ BSONObjIterator j( e.embeddedObject() );
+ while( j.more() ) {
+ processQueryField( j.next(), optimize );
+ }
+ }
+ }
- if ( strcmp( e.fieldName(), "$where" ) == 0 ) {
- return;
- }
+ if ( strcmp( e.fieldName(), "$where" ) == 0 ) {
+ return;
+ }
- if ( strcmp( e.fieldName(), "$or" ) == 0 ) {
- return;
- }
+ if ( strcmp( e.fieldName(), "$or" ) == 0 ) {
+ return;
+ }
- if ( strcmp( e.fieldName(), "$nor" ) == 0 ) {
- return;
- }
+ if ( strcmp( e.fieldName(), "$nor" ) == 0 ) {
+ return;
+ }
+ }
bool equality = ( getGtLtOp( e ) == BSONObj::Equality );
if ( equality && e.type() == Object ) {
@@ -1067,32 +1069,11 @@ namespace mongo {
return ret;
}
- const FieldRangeSet &FieldRangeSetPair::frsForIndex( const NamespaceDetails* nsd, int idxNo ) const {
- assertValidIndexOrNoIndex( nsd, idxNo );
- if ( idxNo < 0 ) {
- // An unindexed cursor cannot have a "single key" constraint.
- return _multiKey;
- }
- return nsd->isMultikey( idxNo ) ? _multiKey : _singleKey;
- }
-
bool FieldRangeSetPair::noNontrivialRanges() const {
return _singleKey.matchPossible() && _singleKey.nNontrivialRanges() == 0 &&
_multiKey.matchPossible() && _multiKey.nNontrivialRanges() == 0;
}
- bool FieldRangeSetPair::matchPossibleForIndex( NamespaceDetails *d, int idxNo, const BSONObj &keyPattern ) const {
- assertValidIndexOrNoIndex( d, idxNo );
- if ( !matchPossible() ) {
- return false;
- }
- if ( idxNo < 0 ) {
- // multi key matchPossible() is true, so return true.
- return true;
- }
- return frsForIndex( d, idxNo ).matchPossibleForIndex( keyPattern );
- }
-
FieldRangeSetPair &FieldRangeSetPair::operator&=( const FieldRangeSetPair &other ) {
_singleKey &= other._singleKey;
_multiKey &= other._multiKey;
@@ -1105,21 +1086,23 @@ namespace mongo {
return *this;
}
+ BSONObj FieldRangeSetPair::simplifiedQueryForIndex( NamespaceDetails *d, int idxNo, const BSONObj &keyPattern ) const {
+ return frsForIndex( d, idxNo ).simplifiedQuery( keyPattern );
+ }
+
void FieldRangeSetPair::assertValidIndex( const NamespaceDetails *d, int idxNo ) const {
massert( 14048, "FieldRangeSetPair invalid index specified", idxNo >= 0 && idxNo < d->nIndexes );
}
-
- void FieldRangeSetPair::assertValidIndexOrNoIndex( const NamespaceDetails *d, int idxNo ) const {
- massert( 14049, "FieldRangeSetPair invalid index specified", idxNo >= -1 );
- if ( idxNo >= 0 ) {
- assertValidIndex( d, idxNo );
+
+ const FieldRangeSet &FieldRangeSetPair::frsForIndex( const NamespaceDetails* nsd, int idxNo ) const {
+ assertValidIndexOrNoIndex( nsd, idxNo );
+ if ( idxNo < 0 ) {
+ // An unindexed cursor cannot have a "single key" constraint.
+ return _multiKey;
}
+ return nsd->isMultikey( idxNo ) ? _multiKey : _singleKey;
}
-
- BSONObj FieldRangeSetPair::simplifiedQueryForIndex( NamespaceDetails *d, int idxNo, const BSONObj &keyPattern ) const {
- return frsForIndex( d, idxNo ).simplifiedQuery( keyPattern );
- }
-
+
bool FieldRangeVector::matchesElement( const BSONElement &e, int i, bool forward ) const {
bool eq;
int l = matchingLowElement( e, i, forward, eq );
View
6 dbtests/queryoptimizertests.cpp
@@ -104,7 +104,7 @@ namespace QueryOptimizerTests {
auto_ptr< FieldRangeSetPair > FieldRangeSetPair_GLOBAL;
#define FRSP(x) ( FieldRangeSetPair_GLOBAL.reset( new FieldRangeSetPair( ns(), x ) ), *FieldRangeSetPair_GLOBAL )
auto_ptr< FieldRangeSetPair > FieldRangeSetPair_GLOBAL2;
-#define FRSP2(x) ( FieldRangeSetPair_GLOBAL2.reset( new FieldRangeSetPair( ns(), x ) ), *FieldRangeSetPair_GLOBAL2 )
+#define FRSP2(x) ( FieldRangeSetPair_GLOBAL2.reset( new FieldRangeSetPair( ns(), x ) ), FieldRangeSetPair_GLOBAL2.get() )
class NoIndex : public Base {
public:
@@ -886,7 +886,7 @@ namespace QueryOptimizerTests {
}
BSONObj hint = fromjson( "{$hint:{a:1,b:1}}" );
auto_ptr< FieldRangeSetPair > frsp( new FieldRangeSetPair( ns(), fromjson( "{a:5,b:{$in:[2,3,6,9,11]}}" ) ) );
- QueryPlan qp( nsd(), 1, *frsp, *frsp, fromjson( "{a:5,b:{$in:[2,3,6,9,11]}}" ), BSONObj() );
+ QueryPlan qp( nsd(), 1, *frsp, frsp.get(), fromjson( "{a:5,b:{$in:[2,3,6,9,11]}}" ), BSONObj() );
boost::shared_ptr<Cursor> c = qp.newCursor();
double expected[] = { 2, 3, 6, 9 };
ASSERT( c->ok() );
@@ -908,7 +908,7 @@ namespace QueryOptimizerTests {
}
BSONObj hint = fromjson( "{$hint:{a:1,b:1}}" );
auto_ptr< FieldRangeSetPair > frsp( new FieldRangeSetPair( ns(), fromjson( "{a:{$gte:5},b:{$in:[2,3,6,9,11]}}" ) ) );
- QueryPlan qp( nsd(), 1, *frsp, *frsp, fromjson( "{a:{$gte:5},b:{$in:[2,3,6,9,11]}}" ), BSONObj() );
+ QueryPlan qp( nsd(), 1, *frsp, frsp.get(), fromjson( "{a:{$gte:5},b:{$in:[2,3,6,9,11]}}" ), BSONObj() );
boost::shared_ptr<Cursor> c = qp.newCursor();
int matches[] = { 2, 3, 6, 9 };
for( int i = 0; i < 4; ++i, c->advance() ) {
View
2  dbtests/repltests.cpp
@@ -1069,7 +1069,7 @@ namespace ReplTests {
BSONObj query = BSON( "ts" << b.obj() );
FieldRangeSetPair frsp( cllNS(), query );
BSONObj order = BSON( "$natural" << 1 );
- QueryPlan qp( nsd, -1, frsp, frsp, query, order );
+ QueryPlan qp( nsd, -1, frsp, &frsp, query, order );
FindingStartCursor fsc( qp );
ASSERT( fsc.done() );
ASSERT_EQUALS( 0, fsc.cursor()->current()[ "o" ].Obj()[ "_id" ].Int() );
Please sign in to comment.
Something went wrong with that request. Please try again.