Exemplo n.º 1
0
    void QueryPlanSet::init() {
        DEBUGQO( "QueryPlanSet::init " << ns << "\t" << _originalQuery );
        _plans.clear();
        _mayRecordPlan = true;
        _usingPrerecordedPlan = false;

        const char *ns = _frsp->ns();
        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 ) ) );
            return;
        }

        BSONElement hint = _hint.firstElement();
        if ( !hint.eoo() ) {
            _mayRecordPlan = false;
            IndexDetails *id = parseHint( hint, d );
            if ( id ) {
                addHint( *id );
            }
            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 ) ) );
            }
            return;
        }

        if ( !_min.isEmpty() || !_max.isEmpty() ) {
            string errmsg;
            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 ) ) );
            return;
        }

        if ( isSimpleIdQuery( _originalQuery ) ) {
            int idx = d->findIdIndex();
            if ( idx >= 0 ) {
                _usingPrerecordedPlan = true;
                _mayRecordPlan = false;
                _plans.push_back( QueryPlanPtr( new QueryPlan( d , idx , *_frsp , *_originalFrsp , _originalQuery, _order ) ) );
                return;
            }
        }

        if ( _originalQuery.isEmpty() && _order.isEmpty() ) {
            _plans.push_back( QueryPlanPtr( new QueryPlan( d, -1, *_frsp, *_originalFrsp, _originalQuery, _order ) ) );
            return;
        }

        DEBUGQO( "\t special : " << _frsp->getSpecial() );
        if ( _frsp->getSpecial().size() ) {
            _special = _frsp->getSpecial();
            NamespaceDetails::IndexIterator i = d->ii();
            while( i.more() ) {
                int j = i.pos();
                IndexDetails& ii = i.next();
                const IndexSpec& spec = ii.getSpec();
                if ( spec.getTypeName() == _special && spec.suitability( _originalQuery , _order ) ) {
                    _usingPrerecordedPlan = true;
                    _mayRecordPlan = false;
                    _plans.push_back( QueryPlanPtr( new QueryPlan( d , j , *_frsp , *_originalFrsp , _originalQuery, _order ,
                                                    BSONObj() , BSONObj() , _special ) ) );
                    return;
                }
            }
            uassert( 13038 , (string)"can't find special index: " + _special + " for: " + _originalQuery.toString() , 0 );
        }

        if ( _honorRecordedPlan ) {
            pair< BSONObj, long long > best = QueryUtilIndexed::bestIndexForPatterns( *_frsp, _order );
            BSONObj bestIndex = best.first;
            long long oldNScanned = best.second;
            if ( !bestIndex.isEmpty() ) {
                QueryPlanPtr p;
                _oldNScanned = oldNScanned;
                if ( !strcmp( bestIndex.firstElement().fieldName(), "$natural" ) ) {
                    // Table scan plan
                    p.reset( new QueryPlan( d, -1, *_frsp, *_originalFrsp, _originalQuery, _order ) );
                }

                NamespaceDetails::IndexIterator i = d->ii();
                while( i.more() ) {
                    int j = i.pos();
                    IndexDetails& ii = i.next();
                    if( ii.keyPattern().woCompare(bestIndex) == 0 ) {
                        p.reset( new QueryPlan( d, j, *_frsp, *_originalFrsp, _originalQuery, _order ) );
                    }
                }

                massert( 10368 ,  "Unable to locate previously recorded index", p.get() );
                if ( !( _bestGuessOnly && p->scanAndOrderRequired() ) ) {
                    _usingPrerecordedPlan = true;
                    _mayRecordPlan = false;
                    _plans.push_back( p );
                    return;
                }
            }
        }

        addOtherPlans( false );
    }
Exemplo n.º 2
0
 void QueryPlanSet::init() {
     plans_.clear();
     mayRecordPlan_ = true;
     usingPrerecordedPlan_ = false;
     
     const char *ns = fbs_.ns();
     NamespaceDetails *d = nsdetails( ns );
     if ( !d || !fbs_.matchPossible() ) {
         // Table scan plan, when no matches are possible
         plans_.push_back( PlanPtr( new QueryPlan( fbs_, order_ ) ) );
         return;
     }
     
     BSONElement hint = hint_.firstElement();
     if ( !hint.eoo() ) {
         mayRecordPlan_ = false;
         if( hint.type() == String ) {
             string hintstr = hint.valuestr();
             for (int i = 0; i < d->nIndexes; i++ ) {
                 IndexDetails& ii = d->indexes[i];
                 if ( ii.indexName() == hintstr ) {
                     plans_.push_back( PlanPtr( new QueryPlan( fbs_, order_, &ii ) ) );
                     return;
                 }
             }
         }
         else if( hint.type() == Object ) { 
             BSONObj hintobj = hint.embeddedObject();
             uassert( "bad hint", !hintobj.isEmpty() );
             if ( !strcmp( hintobj.firstElement().fieldName(), "$natural" ) ) {
                 // Table scan plan
                 plans_.push_back( PlanPtr( new QueryPlan( fbs_, order_ ) ) );
                 return;
             }
             for (int i = 0; i < d->nIndexes; i++ ) {
                 IndexDetails& ii = d->indexes[i];
                 if( ii.keyPattern().woCompare(hintobj) == 0 ) {
                     plans_.push_back( PlanPtr( new QueryPlan( fbs_, order_, &ii ) ) );
                     return;
                 }
             }
         }
         uassert( "bad hint", false );
     }
     
     if ( honorRecordedPlan_ ) {
         BSONObj bestIndex = NamespaceDetailsTransient::get( ns ).indexForPattern( fbs_.pattern( order_ ) );
         if ( !bestIndex.isEmpty() ) {
             usingPrerecordedPlan_ = true;
             mayRecordPlan_ = false;
             oldNScanned_ = NamespaceDetailsTransient::get( ns ).nScannedForPattern( fbs_.pattern( order_ ) );
             if ( !strcmp( bestIndex.firstElement().fieldName(), "$natural" ) ) {
                 // Table scan plan
                 plans_.push_back( PlanPtr( new QueryPlan( fbs_, order_ ) ) );
                 return;
             }
             for (int i = 0; i < d->nIndexes; i++ ) {
                 IndexDetails& ii = d->indexes[i];
                 if( ii.keyPattern().woCompare(bestIndex) == 0 ) {
                     plans_.push_back( PlanPtr( new QueryPlan( fbs_, order_, &ii ) ) );
                     return;
                 }
             }
             massert( "Unable to locate previously recorded index", false );
         }
     }
     
     addOtherPlans( false );
 }