diff --git a/SConstruct b/SConstruct index ff419de305b..7a8d6e1e44d 100644 --- a/SConstruct +++ b/SConstruct @@ -131,7 +131,7 @@ else: coreDbFiles = Split( "" ) -serverOnlyFiles = Split( "db/query.cpp db/introspect.cpp db/btree.cpp db/clientcursor.cpp db/javajs.cpp db/tests.cpp db/repl.cpp db/btreecursor.cpp db/cloner.cpp db/namespace.cpp db/matcher.cpp db/dbcommands.cpp db/dbeval.cpp db/dbwebserver.cpp db/dbinfo.cpp db/dbhelpers.cpp db/instance.cpp db/pdfile.cpp db/cursor.cpp db/security_commands.cpp db/security.cpp util/miniwebserver.cpp db/storage.cpp db/reccache.cpp" ) +serverOnlyFiles = Split( "db/query.cpp db/introspect.cpp db/btree.cpp db/clientcursor.cpp db/javajs.cpp db/tests.cpp db/repl.cpp db/btreecursor.cpp db/cloner.cpp db/namespace.cpp db/matcher.cpp db/dbcommands.cpp db/dbeval.cpp db/dbwebserver.cpp db/dbinfo.cpp db/dbhelpers.cpp db/instance.cpp db/pdfile.cpp db/cursor.cpp db/security_commands.cpp db/security.cpp util/miniwebserver.cpp db/storage.cpp db/reccache.cpp db/queryoptimizer.cpp" ) allClientFiles = commonFiles + coreDbFiles + [ "client/clientOnly.cpp" , "client/gridfs.cpp" ]; diff --git a/db/cursor.h b/db/cursor.h index 73859f466e3..93b49c85794 100644 --- a/db/cursor.h +++ b/db/cursor.h @@ -18,20 +18,25 @@ #include "../stdafx.h" +#include "jsobj.h" +#include "storage.h" + namespace mongo { + + class Record; /* 0 = ok 1 = kill current operation and reset this to 0 future: maybe use this as a "going away" thing on process termination with a higher flag value */ - extern int killCurrentOp; - + extern int killCurrentOp; + inline void checkForInterrupt() { if( killCurrentOp ) { killCurrentOp = 0; uasserted("interrupted"); } - } + } /* Query cursors, base class. This is for our internal cursors. "ClientCursor" is a separate concept and is for the user's cursor. diff --git a/db/database.h b/db/database.h index e64b8291363..cd21d7ca90f 100644 --- a/db/database.h +++ b/db/database.h @@ -124,7 +124,6 @@ namespace mongo { NamespaceIndex namespaceIndex; int profile; // 0=off. string profileName; // "alleyinsider.system.profile" - QueryOptimizer optimizer; bool haveLogged() { return _haveLogged; diff --git a/db/pdfile.h b/db/pdfile.h index 60db3b7ff5c..c5a5f5ae947 100644 --- a/db/pdfile.h +++ b/db/pdfile.h @@ -346,7 +346,6 @@ namespace mongo { } // namespace mongo #include "rec.h" -#include "queryoptimizer.h" #include "database.h" namespace mongo { diff --git a/db/queryoptimizer.cpp b/db/queryoptimizer.cpp index 456afe92bc8..08c29b0ac36 100644 --- a/db/queryoptimizer.cpp +++ b/db/queryoptimizer.cpp @@ -32,6 +32,83 @@ 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(); + cout << "r: " << r << endl; + if ( r ) { + lower_ = addObj( BSON( "" << r ) ).firstElement(); + upper_ = addObj( BSON( "" << simpleRegexEnd( r ) ) ).firstElement(); + cout << "lower_: " << lower_ << endl; + cout << "upper_: " << upper_ << endl; + } + 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; + default: + break; + } + cout << "lower_: " << lower_ << endl; + cout << "upper_: " << upper_ << endl; + } + + 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_; + massert( "Invalid bounds", lower_.woCompare( upper_, false ) <= 0 ); + return *this; + } + + string FieldBound::simpleRegexEnd( string regex ) { + ++regex[ regex.length() - 1 ]; + return regex; + } + + BSONObj FieldBound::addObj( BSONObj o ) { + cout << "o: " << o.toString() << endl; + 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 ); + } + } + } + } + QueryPlan QueryOptimizer::getPlan( const char *ns, BSONObj* query, diff --git a/db/queryoptimizer.h b/db/queryoptimizer.h index a1af76e1718..f2f5421d553 100644 --- a/db/queryoptimizer.h +++ b/db/queryoptimizer.h @@ -18,8 +18,34 @@ #pragma once +#include "cursor.h" +#include "jsobj.h" + namespace mongo { + class FieldBound { + public: + FieldBound( BSONElement e = emptyObj.firstElement() ); + FieldBound &operator&=( const FieldBound &other ); + BSONElement lower() const { return lower_; } + BSONElement upper() const { return upper_; } + private: + BSONObj addObj( BSONObj o ); + string simpleRegexEnd( string regex ); + BSONElement lower_; + BSONElement upper_; + vector< BSONObj > objData_; + }; + + class FieldBoundSet { + public: + FieldBoundSet( BSONObj query ); + FieldBound &bound( const char *fieldName ) { return bounds_[ fieldName ]; } + private: + map< string, FieldBound > bounds_; + BSONObj query_; + }; + class QueryPlan { public: QueryPlan() { @@ -43,7 +69,7 @@ namespace mongo { */ class QueryOptimizer { public: - QueryPlan getPlan( + static QueryPlan getPlan( const char *ns, BSONObj* query, BSONObj* order = 0, diff --git a/dbtests/dbtests.cpp b/dbtests/dbtests.cpp index 659f39fb5f8..e68f8f2b324 100644 --- a/dbtests/dbtests.cpp +++ b/dbtests/dbtests.cpp @@ -96,6 +96,7 @@ int main( int argc, char** argv ) { tests.add( pairingTests(), "pairing" ); tests.add( pdfileTests(), "pdfile" ); tests.add( queryTests(), "query" ); + tests.add( queryOptimizerTests(), "queryoptimizer" ); tests.add( replTests(), "repl" ); tests.add( sockTests(), "sock" ); diff --git a/dbtests/dbtests.h b/dbtests/dbtests.h index a0f529d73dc..f2675aa6a2b 100644 --- a/dbtests/dbtests.h +++ b/dbtests/dbtests.h @@ -30,5 +30,6 @@ UnitTest::TestPtr namespaceTests(); UnitTest::TestPtr pairingTests(); UnitTest::TestPtr pdfileTests(); UnitTest::TestPtr queryTests(); +UnitTest::TestPtr queryOptimizerTests(); UnitTest::TestPtr replTests(); UnitTest::TestPtr sockTests(); diff --git a/mongo.xcodeproj/project.pbxproj b/mongo.xcodeproj/project.pbxproj index baca77f05cc..deedc442afa 100644 --- a/mongo.xcodeproj/project.pbxproj +++ b/mongo.xcodeproj/project.pbxproj @@ -20,6 +20,8 @@ 9302D99F0F30AB8C00DFA4EF /* ShellUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShellUtils.cpp; sourceTree = ""; }; 9302D9A00F30AB8C00DFA4EF /* ShellUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShellUtils.h; sourceTree = ""; }; 9302D9A20F30AB8C00DFA4EF /* utils.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = utils.js; sourceTree = ""; }; + 932AC3EB0F4A5B34005BF8B0 /* queryoptimizertests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = queryoptimizertests.cpp; sourceTree = ""; }; + 932AC4310F4A5E9D005BF8B0 /* SConstruct */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SConstruct; sourceTree = ""; }; 933E22110F4327B2000209E3 /* perftest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = perftest.cpp; sourceTree = ""; }; 933E22120F4327B2000209E3 /* perftest.o */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.objfile"; path = perftest.o; sourceTree = ""; }; 9342232B0EF16D4F00608550 /* connpool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = connpool.cpp; sourceTree = ""; }; @@ -224,6 +226,7 @@ 08FB7795FE84155DC02AAC07 /* Source */ = { isa = PBXGroup; children = ( + 932AC4310F4A5E9D005BF8B0 /* SConstruct */, 93A13A320F4620E500AF1B0D /* tools */, 93A13A200F4620A500AF1B0D /* s */, 93A8D1D10F37544800C92B85 /* jstests */, @@ -289,6 +292,7 @@ 934223850EF16D7000608550 /* dbtests */ = { isa = PBXGroup; children = ( + 932AC3EB0F4A5B34005BF8B0 /* queryoptimizertests.cpp */, 933E22100F4327B2000209E3 /* perf */, 937D0E340F28CB070071FFA9 /* repltests.cpp */, 937CACE90F27BF4900C57AA6 /* socktests.cpp */,