00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #pragma once
00019
00020 #include "jsobj.h"
00021
00022 namespace mongo {
00023
00024 struct FieldBound {
00025 BSONElement _bound;
00026 bool _inclusive;
00027 bool operator==( const FieldBound &other ) const {
00028 return _bound.woCompare( other._bound ) == 0 &&
00029 _inclusive == other._inclusive;
00030 }
00031 void flipInclusive() { _inclusive = !_inclusive; }
00032 };
00033
00034 struct FieldInterval {
00035 FieldInterval() : _cachedEquality( -1 ) {}
00036 FieldInterval( const BSONElement& e ) : _cachedEquality( -1 ) {
00037 _lower._bound = _upper._bound = e;
00038 _lower._inclusive = _upper._inclusive = true;
00039 }
00040 FieldBound _lower;
00041 FieldBound _upper;
00042 bool strictValid() const {
00043 int cmp = _lower._bound.woCompare( _upper._bound, false );
00044 return ( cmp < 0 || ( cmp == 0 && _lower._inclusive && _upper._inclusive ) );
00045 }
00046 bool equality() const {
00047 if ( _cachedEquality == -1 ) {
00048 _cachedEquality = ( _lower._inclusive && _upper._inclusive && _lower._bound.woCompare( _upper._bound, false ) == 0 );
00049 }
00050 return _cachedEquality;
00051 }
00052 mutable int _cachedEquality;
00053 };
00054
00055
00056
00057 class FieldRange {
00058 public:
00059 FieldRange( const BSONElement &e = BSONObj().firstElement() , bool isNot=false , bool optimize=true );
00060 const FieldRange &operator&=( const FieldRange &other );
00061 const FieldRange &operator|=( const FieldRange &other );
00062 const FieldRange &operator-=( const FieldRange &other );
00063
00064 bool operator<=( const FieldRange &other );
00065 BSONElement min() const { assert( !empty() ); return _intervals[ 0 ]._lower._bound; }
00066 BSONElement max() const { assert( !empty() ); return _intervals[ _intervals.size() - 1 ]._upper._bound; }
00067 bool minInclusive() const { assert( !empty() ); return _intervals[ 0 ]._lower._inclusive; }
00068 bool maxInclusive() const { assert( !empty() ); return _intervals[ _intervals.size() - 1 ]._upper._inclusive; }
00069 bool equality() const {
00070 return
00071 !empty() &&
00072 min().woCompare( max(), false ) == 0 &&
00073 maxInclusive() &&
00074 minInclusive();
00075 }
00076 bool inQuery() const {
00077 if ( equality() ) {
00078 return true;
00079 }
00080 for( vector< FieldInterval >::const_iterator i = _intervals.begin(); i != _intervals.end(); ++i ) {
00081 if ( !i->equality() ) {
00082 return false;
00083 }
00084 }
00085 return true;
00086 }
00087 bool nontrivial() const {
00088 return
00089 ! empty() &&
00090 ( _intervals.size() != 1 ||
00091 minKey.firstElement().woCompare( min(), false ) != 0 ||
00092 maxKey.firstElement().woCompare( max(), false ) != 0 );
00093 }
00094 bool empty() const { return _intervals.empty(); }
00095 void makeEmpty() { _intervals.clear(); }
00096 const vector< FieldInterval > &intervals() const { return _intervals; }
00097 string getSpecial() const { return _special; }
00098 void setExclusiveBounds() {
00099 for( vector< FieldInterval >::iterator i = _intervals.begin(); i != _intervals.end(); ++i ) {
00100 i->_lower._inclusive = false;
00101 i->_upper._inclusive = false;
00102 }
00103 }
00104
00105
00106 void reverse( FieldRange &ret ) const {
00107 assert( _special.empty() );
00108 ret._intervals.clear();
00109 ret._objData = _objData;
00110 for( vector< FieldInterval >::const_reverse_iterator i = _intervals.rbegin(); i != _intervals.rend(); ++i ) {
00111 FieldInterval fi;
00112 fi._lower = i->_upper;
00113 fi._upper = i->_lower;
00114 ret._intervals.push_back( fi );
00115 }
00116 }
00117 private:
00118 BSONObj addObj( const BSONObj &o );
00119 void finishOperation( const vector< FieldInterval > &newIntervals, const FieldRange &other );
00120 vector< FieldInterval > _intervals;
00121 vector< BSONObj > _objData;
00122 string _special;
00123 };
00124
00125
00126
00127 class QueryPattern {
00128 public:
00129 friend class FieldRangeSet;
00130 enum Type {
00131 Equality,
00132 LowerBound,
00133 UpperBound,
00134 UpperAndLowerBound
00135 };
00136
00137 bool operator==( const QueryPattern &other ) const {
00138 bool less = operator<( other );
00139 bool more = other.operator<( *this );
00140 assert( !( less && more ) );
00141 return !( less || more );
00142 }
00143 bool operator!=( const QueryPattern &other ) const {
00144 return !operator==( other );
00145 }
00146 bool operator<( const QueryPattern &other ) const {
00147 map< string, Type >::const_iterator i = _fieldTypes.begin();
00148 map< string, Type >::const_iterator j = other._fieldTypes.begin();
00149 while( i != _fieldTypes.end() ) {
00150 if ( j == other._fieldTypes.end() )
00151 return false;
00152 if ( i->first < j->first )
00153 return true;
00154 else if ( i->first > j->first )
00155 return false;
00156 if ( i->second < j->second )
00157 return true;
00158 else if ( i->second > j->second )
00159 return false;
00160 ++i;
00161 ++j;
00162 }
00163 if ( j != other._fieldTypes.end() )
00164 return true;
00165 return _sort.woCompare( other._sort ) < 0;
00166 }
00167 private:
00168 QueryPattern() {}
00169 void setSort( const BSONObj sort ) {
00170 _sort = normalizeSort( sort );
00171 }
00172 BSONObj static normalizeSort( const BSONObj &spec ) {
00173 if ( spec.isEmpty() )
00174 return spec;
00175 int direction = ( spec.firstElement().number() >= 0 ) ? 1 : -1;
00176 BSONObjIterator i( spec );
00177 BSONObjBuilder b;
00178 while( i.moreWithEOO() ) {
00179 BSONElement e = i.next();
00180 if ( e.eoo() )
00181 break;
00182 b.append( e.fieldName(), direction * ( ( e.number() >= 0 ) ? -1 : 1 ) );
00183 }
00184 return b.obj();
00185 }
00186 map< string, Type > _fieldTypes;
00187 BSONObj _sort;
00188 };
00189
00190
00191
00192
00193
00194
00195 typedef vector< pair< BSONObj, BSONObj > > BoundList;
00196
00197
00198
00199 class FieldRangeSet {
00200 public:
00201 friend class FieldRangeOrSet;
00202 friend class FieldRangeVector;
00203 FieldRangeSet( const char *ns, const BSONObj &query , bool optimize=true );
00204 bool hasRange( const char *fieldName ) const {
00205 map< string, FieldRange >::const_iterator f = _ranges.find( fieldName );
00206 return f != _ranges.end();
00207 }
00208 const FieldRange &range( const char *fieldName ) const {
00209 map< string, FieldRange >::const_iterator f = _ranges.find( fieldName );
00210 if ( f == _ranges.end() )
00211 return trivialRange();
00212 return f->second;
00213 }
00214 FieldRange &range( const char *fieldName ) {
00215 map< string, FieldRange >::iterator f = _ranges.find( fieldName );
00216 if ( f == _ranges.end() )
00217 return trivialRange();
00218 return f->second;
00219 }
00220 int nNontrivialRanges() const {
00221 int count = 0;
00222 for( map< string, FieldRange >::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i ) {
00223 if ( i->second.nontrivial() )
00224 ++count;
00225 }
00226 return count;
00227 }
00228 const char *ns() const { return _ns; }
00229
00230 BSONObj simplifiedQuery( const BSONObj &fields = BSONObj() ) const;
00231 bool matchPossible() const {
00232 for( map< string, FieldRange >::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i )
00233 if ( i->second.empty() )
00234 return false;
00235 return true;
00236 }
00237 QueryPattern pattern( const BSONObj &sort = BSONObj() ) const;
00238 string getSpecial() const;
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 const FieldRangeSet &operator-=( const FieldRangeSet &other ) {
00252 int nUnincluded = 0;
00253 string unincludedKey;
00254 map< string, FieldRange >::iterator i = _ranges.begin();
00255 map< string, FieldRange >::const_iterator j = other._ranges.begin();
00256 while( nUnincluded < 2 && i != _ranges.end() && j != other._ranges.end() ) {
00257 int cmp = i->first.compare( j->first );
00258 if ( cmp == 0 ) {
00259 if ( i->second <= j->second ) {
00260
00261 }
00262 else {
00263 ++nUnincluded;
00264 unincludedKey = i->first;
00265 }
00266 ++i;
00267 ++j;
00268 }
00269 else if ( cmp < 0 ) {
00270 ++i;
00271 }
00272 else {
00273
00274 return *this;
00275 }
00276 }
00277 if ( j != other._ranges.end() ) {
00278
00279 return *this;
00280 }
00281 if ( nUnincluded > 1 ) {
00282 return *this;
00283 }
00284 if ( nUnincluded == 0 ) {
00285 makeEmpty();
00286 return *this;
00287 }
00288
00289 _ranges[ unincludedKey ] -= other._ranges[ unincludedKey ];
00290 appendQueries( other );
00291 return *this;
00292 }
00293 const FieldRangeSet &operator&=( const FieldRangeSet &other ) {
00294 map< string, FieldRange >::iterator i = _ranges.begin();
00295 map< string, FieldRange >::const_iterator j = other._ranges.begin();
00296 while( i != _ranges.end() && j != other._ranges.end() ) {
00297 int cmp = i->first.compare( j->first );
00298 if ( cmp == 0 ) {
00299 i->second &= j->second;
00300 ++i;
00301 ++j;
00302 }
00303 else if ( cmp < 0 ) {
00304 ++i;
00305 }
00306 else {
00307 _ranges[ j->first ] = j->second;
00308 ++j;
00309 }
00310 }
00311 while( j != other._ranges.end() ) {
00312 _ranges[ j->first ] = j->second;
00313 ++j;
00314 }
00315 appendQueries( other );
00316 return *this;
00317 }
00318
00319 BoundList indexBounds( const BSONObj &keyPattern, int direction ) const;
00320
00327 FieldRangeSet *subset( const BSONObj &fields ) const;
00328 private:
00329 void appendQueries( const FieldRangeSet &other ) {
00330 for( vector< BSONObj >::const_iterator i = other._queries.begin(); i != other._queries.end(); ++i ) {
00331 _queries.push_back( *i );
00332 }
00333 }
00334 void makeEmpty() {
00335 for( map< string, FieldRange >::iterator i = _ranges.begin(); i != _ranges.end(); ++i ) {
00336 i->second.makeEmpty();
00337 }
00338 }
00339 void processQueryField( const BSONElement &e, bool optimize );
00340 void processOpElement( const char *fieldName, const BSONElement &f, bool isNot, bool optimize );
00341 static FieldRange *trivialRange_;
00342 static FieldRange &trivialRange();
00343 mutable map< string, FieldRange > _ranges;
00344 const char *_ns;
00345
00346 vector< BSONObj > _queries;
00347 };
00348
00349 class IndexSpec;
00350
00355 class FieldRangeVector {
00356 public:
00362 FieldRangeVector( const FieldRangeSet &frs, const BSONObj &keyPattern, int direction )
00363 :_keyPattern( keyPattern ), _direction( direction >= 0 ? 1 : -1 ) {
00364 _queries = frs._queries;
00365 BSONObjIterator i( _keyPattern );
00366 while( i.more() ) {
00367 BSONElement e = i.next();
00368 int number = (int) e.number();
00369 bool forward = ( ( number >= 0 ? 1 : -1 ) * ( direction >= 0 ? 1 : -1 ) > 0 );
00370 if ( forward ) {
00371 _ranges.push_back( frs.range( e.fieldName() ) );
00372 }
00373 else {
00374 _ranges.push_back( FieldRange() );
00375 frs.range( e.fieldName() ).reverse( _ranges.back() );
00376 }
00377 assert( !_ranges.back().empty() );
00378 }
00379 uassert( 13385, "combinatorial limit of $in partitioning of result set exceeded", size() < 1000000 );
00380 }
00381 long long size() {
00382 long long ret = 1;
00383 for( vector< FieldRange >::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i ) {
00384 ret *= i->intervals().size();
00385 }
00386 return ret;
00387 }
00388 BSONObj startKey() const {
00389 BSONObjBuilder b;
00390 for( vector< FieldRange >::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i ) {
00391 const FieldInterval &fi = i->intervals().front();
00392 b.appendAs( fi._lower._bound, "" );
00393 }
00394 return b.obj();
00395 }
00396 BSONObj endKey() const {
00397 BSONObjBuilder b;
00398 for( vector< FieldRange >::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i ) {
00399 const FieldInterval &fi = i->intervals().back();
00400 b.appendAs( fi._upper._bound, "" );
00401 }
00402 return b.obj();
00403 }
00404 BSONObj obj() const {
00405 BSONObjBuilder b;
00406 BSONObjIterator k( _keyPattern );
00407 for( int i = 0; i < (int)_ranges.size(); ++i ) {
00408 BSONArrayBuilder a( b.subarrayStart( k.next().fieldName() ) );
00409 for( vector< FieldInterval >::const_iterator j = _ranges[ i ].intervals().begin();
00410 j != _ranges[ i ].intervals().end(); ++j ) {
00411 a << BSONArray( BSON_ARRAY( j->_lower._bound << j->_upper._bound ).clientReadable() );
00412 }
00413 a.done();
00414 }
00415 return b.obj();
00416 }
00423 bool matches( const BSONObj &obj ) const;
00424 class Iterator {
00425 public:
00426 Iterator( const FieldRangeVector &v ) : _v( v ), _i( _v._ranges.size(), -1 ), _cmp( _v._ranges.size(), 0 ), _inc( _v._ranges.size(), false ), _after() {
00427 }
00428 static BSONObj minObject() {
00429 BSONObjBuilder b;
00430 b.appendMinKey( "" );
00431 return b.obj();
00432 }
00433 static BSONObj maxObject() {
00434 BSONObjBuilder b;
00435 b.appendMaxKey( "" );
00436 return b.obj();
00437 }
00438 bool advance() {
00439 int i = _i.size() - 1;
00440 while( i >= 0 && _i[ i ] >= ( (int)_v._ranges[ i ].intervals().size() - 1 ) ) {
00441 --i;
00442 }
00443 if( i >= 0 ) {
00444 _i[ i ]++;
00445 for( unsigned j = i + 1; j < _i.size(); ++j ) {
00446 _i[ j ] = 0;
00447 }
00448 }
00449 else {
00450 _i[ 0 ] = _v._ranges[ 0 ].intervals().size();
00451 }
00452 return ok();
00453 }
00454
00455
00456
00457
00458 int advance( const BSONObj &curr );
00459 const vector< const BSONElement * > &cmp() const { return _cmp; }
00460 const vector< bool > &inc() const { return _inc; }
00461 bool after() const { return _after; }
00462 void prepDive();
00463 void setZero( int i ) {
00464 for( int j = i; j < (int)_i.size(); ++j ) {
00465 _i[ j ] = 0;
00466 }
00467 }
00468 void setMinus( int i ) {
00469 for( int j = i; j < (int)_i.size(); ++j ) {
00470 _i[ j ] = -1;
00471 }
00472 }
00473 bool ok() {
00474 return _i[ 0 ] < (int)_v._ranges[ 0 ].intervals().size();
00475 }
00476 BSONObj startKey() {
00477 BSONObjBuilder b;
00478 for( int unsigned i = 0; i < _i.size(); ++i ) {
00479 const FieldInterval &fi = _v._ranges[ i ].intervals()[ _i[ i ] ];
00480 b.appendAs( fi._lower._bound, "" );
00481 }
00482 return b.obj();
00483 }
00484
00485 BSONObj endKey() {
00486 BSONObjBuilder b;
00487 for( int unsigned i = 0; i < _i.size(); ++i ) {
00488 const FieldInterval &fi = _v._ranges[ i ].intervals()[ _i[ i ] ];
00489 b.appendAs( fi._upper._bound, "" );
00490 }
00491 return b.obj();
00492 }
00493
00494 private:
00495 const FieldRangeVector &_v;
00496 vector< int > _i;
00497 vector< const BSONElement* > _cmp;
00498 vector< bool > _inc;
00499 bool _after;
00500 };
00501 private:
00502 int matchingLowElement( const BSONElement &e, int i, bool direction, bool &lowEquality ) const;
00503 bool matchesElement( const BSONElement &e, int i, bool direction ) const;
00504 vector< FieldRange > _ranges;
00505 BSONObj _keyPattern;
00506 int _direction;
00507 vector< BSONObj > _queries;
00508
00509 mutable shared_ptr< IndexSpec > _indexSpec;
00510 };
00511
00512
00513 class FieldRangeOrSet {
00514 public:
00515 FieldRangeOrSet( const char *ns, const BSONObj &query , bool optimize=true );
00516
00517 bool orFinished() const { return _orFound && _orSets.empty(); }
00528 void popOrClause( const BSONObj &indexSpec = BSONObj() );
00529 FieldRangeSet *topFrs() const {
00530 FieldRangeSet *ret = new FieldRangeSet( _baseSet );
00531 if (_orSets.size()) {
00532 *ret &= _orSets.front();
00533 }
00534 return ret;
00535 }
00536
00537
00538
00539 FieldRangeSet *topFrsOriginal() const {
00540 FieldRangeSet *ret = new FieldRangeSet( _baseSet );
00541 if (_originalOrSets.size()) {
00542 *ret &= _originalOrSets.front();
00543 }
00544 return ret;
00545 }
00546 void allClausesSimplified( vector< BSONObj > &ret ) const {
00547 for( list< FieldRangeSet >::const_iterator i = _orSets.begin(); i != _orSets.end(); ++i ) {
00548 if ( i->matchPossible() ) {
00549 ret.push_back( i->simplifiedQuery() );
00550 }
00551 }
00552 }
00553 string getSpecial() const { return _baseSet.getSpecial(); }
00554
00555 bool moreOrClauses() const { return !_orSets.empty(); }
00556 private:
00557 FieldRangeSet _baseSet;
00558 list< FieldRangeSet > _orSets;
00559 list< FieldRangeSet > _originalOrSets;
00560 list< FieldRangeSet > _oldOrSets;
00561 bool _orFound;
00562 };
00563
00570 string simpleRegex(const char* regex, const char* flags, bool* purePrefix=NULL);
00571
00573 string simpleRegexEnd( string prefix );
00574
00575 long long applySkipLimit( long long num , const BSONObj& cmd );
00576
00577 }