0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00
mongodb/db/queryoptimizer.cpp
2009-02-17 20:57:36 -05:00

171 lines
5.2 KiB
C++

/* queryoptimizer.cpp */
/**
* Copyright (C) 2008 10gen Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdafx.h"
#include "query.h"
#include "pdfile.h"
#include "jsobj.h"
#include "../util/builder.h"
#include <time.h>
#include "btree.h"
#include "../util/lruishmap.h"
#include "json.h"
#include "repl.h"
#include "replset.h"
#include "scanandorder.h"
#include "queryoptimizer.h"
namespace mongo {
FieldBound::FieldBound( BSONElement e ) :
lower_( minKey.firstElement() ),
upper_( maxKey.firstElement() ) {
if ( e.eoo() )
return;
if ( e.type() == RegEx ) {
const char *r = e.simpleRegex();
if ( r ) {
lower_ = addObj( BSON( "" << r ) ).firstElement();
upper_ = addObj( BSON( "" << simpleRegexEnd( r ) ) ).firstElement();
}
return;
}
switch( e.getGtLtOp() ) {
case JSMatcher::Equality:
lower_ = e;
upper_ = e;
break;
case JSMatcher::LT:
case JSMatcher::LTE:
upper_ = e;
break;
case JSMatcher::GT:
case JSMatcher::GTE:
lower_ = e;
break;
case JSMatcher::opIN: {
massert( "$in requires array", e.type() == Array );
BSONElement max = minKey.firstElement();
BSONElement min = maxKey.firstElement();
BSONObjIterator i( e.embeddedObject() );
while( i.more() ) {
BSONElement f = i.next();
if ( f.eoo() )
break;
if ( max.woCompare( f, false ) < 0 )
max = f;
if ( min.woCompare( f, false ) > 0 )
min = f;
}
lower_ = min;
upper_ = max;
}
default:
break;
}
}
FieldBound &FieldBound::operator&=( const FieldBound &other ) {
if ( other.upper_.woCompare( upper_, false ) < 0 )
upper_ = other.upper_;
if ( other.lower_.woCompare( lower_, false ) > 0 )
lower_ = other.lower_;
for( vector< BSONObj >::const_iterator i = other.objData_.begin(); i != other.objData_.end(); ++i )
objData_.push_back( *i );
massert( "Incompatible bounds", lower_.woCompare( upper_, false ) <= 0 );
return *this;
}
string FieldBound::simpleRegexEnd( string regex ) {
++regex[ regex.length() - 1 ];
return regex;
}
BSONObj FieldBound::addObj( BSONObj o ) {
objData_.push_back( o );
return o;
}
FieldBoundSet::FieldBoundSet( BSONObj query ) :
query_( query.copy() ) {
BSONObjIterator i( query_ );
while( i.more() ) {
BSONElement e = i.next();
if ( e.eoo() )
break;
if ( getGtLtOp( e ) == JSMatcher::Equality ) {
bounds_[ e.fieldName() ] &= FieldBound( e );
}
else {
BSONObjIterator i( e.embeddedObject() );
while( i.more() ) {
BSONElement f = i.next();
if ( f.eoo() )
break;
bounds_[ e.fieldName() ] &= FieldBound( f );
}
}
}
}
FieldBound FieldBoundSet::trivialBound_;
QueryPlan::QueryPlan( const FieldBoundSet &fbs, BSONObj order, BSONObj idxKey ) :
optimal_( false ),
scanAndOrderRequired_( true ),
keyMatch_( false ),
exactKeyMatch_( false ) {
massert( "Index unhelpful", fbs.nNontrivialBounds() != 0 || !order.isEmpty() );
BSONObjIterator o( order );
BSONObjIterator k( idxKey );
int direction = 0;
while( o.more() ) {
if ( !k.more() )
break;
BSONElement oe = o.next();
BSONElement ke = k.next();
if ( oe.eoo() ) {
scanAndOrderRequired_ = false;
break;
}
if ( strcmp( oe.fieldName(), ke.fieldName() ) != 0 )
break;
int d = oe.number() == ke.number() ? 1 : -1;
if ( direction == 0 )
direction = d;
else if ( direction != d )
break;
}
}
// QueryPlan QueryOptimizer::getPlan(
// const char *ns,
// BSONObj* query,
// BSONObj* order,
// BSONObj* hint)
// {
// QueryPlan plan;
//
//
//
// return plan;
// }
} // namespace mongo