00001
00002
00019 #pragma once
00020
00021 #include "../pch.h"
00022 #include "../util/message.h"
00023 #include "dbmessage.h"
00024 #include "jsobj.h"
00025 #include "diskloc.h"
00026 #include "projection.h"
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 #include "../client/dbclient.h"
00072
00073 namespace mongo {
00074
00075 extern const int MaxBytesToReturnToClientAtOnce;
00076
00077
00078 struct GetMoreWaitException { };
00079
00080 QueryResult* processGetMore(const char *ns, int ntoreturn, long long cursorid , CurOp& op, int pass, bool& exhaust);
00081
00082 struct UpdateResult {
00083 bool existing;
00084 bool mod;
00085 long long num;
00086 OID upserted;
00087
00088 UpdateResult( bool e, bool m, unsigned long long n , const BSONObj& upsertedObject = BSONObj() )
00089 : existing(e) , mod(m), num(n) {
00090 upserted.clear();
00091
00092 BSONElement id = upsertedObject["_id"];
00093 if ( ! e && n == 1 && id.type() == jstOID ) {
00094 upserted = id.OID();
00095 }
00096 }
00097
00098 };
00099
00100 class RemoveSaver;
00101
00102
00103
00104
00105
00106 UpdateResult updateObjects(const char *ns, const BSONObj& updateobj, BSONObj pattern, bool upsert, bool multi , bool logop , OpDebug& debug );
00107 UpdateResult _updateObjects(bool god, const char *ns, const BSONObj& updateobj, BSONObj pattern,
00108 bool upsert, bool multi , bool logop , OpDebug& debug , RemoveSaver * rs = 0 );
00109
00110
00111 long long deleteObjects(const char *ns, BSONObj pattern, bool justOne, bool logop = false, bool god=false, RemoveSaver * rs=0);
00112
00113 long long runCount(const char *ns, const BSONObj& cmd, string& err);
00114
00115 const char * runQuery(Message& m, QueryMessage& q, CurOp& curop, Message &result);
00116
00117
00118
00119
00120 inline BSONObj transformOrderFromArrayFormat(BSONObj order) {
00121
00122 BSONObjBuilder b;
00123 char p[2] = "0";
00124
00125 while ( 1 ) {
00126 BSONObj j = order.getObjectField(p);
00127 if ( j.isEmpty() )
00128 break;
00129 BSONElement e = j.firstElement();
00130 uassert( 10102 , "bad order array", !e.eoo());
00131 uassert( 10103 , "bad order array [2]", e.isNumber());
00132 b.append(e);
00133 (*p)++;
00134 uassert( 10104 , "too many ordering elements", *p <= '9');
00135 }
00136
00137 return b.obj();
00138 }
00139
00145 class ParsedQuery {
00146 public:
00147 ParsedQuery( QueryMessage& qm )
00148 : _ns( qm.ns ) , _ntoskip( qm.ntoskip ) , _ntoreturn( qm.ntoreturn ) , _options( qm.queryOptions ) {
00149 init( qm.query );
00150 initFields( qm.fields );
00151 }
00152 ParsedQuery( const char* ns , int ntoskip , int ntoreturn , int queryoptions , const BSONObj& query , const BSONObj& fields )
00153 : _ns( ns ) , _ntoskip( ntoskip ) , _ntoreturn( ntoreturn ) , _options( queryoptions ) {
00154 init( query );
00155 initFields( fields );
00156 }
00157
00158 ~ParsedQuery() {}
00159
00160 const char * ns() const { return _ns; }
00161 bool isLocalDB() const { return strncmp(_ns, "local.", 6) == 0; }
00162
00163 const BSONObj& getFilter() const { return _filter; }
00164 Projection* getFields() const { return _fields.get(); }
00165 shared_ptr<Projection> getFieldPtr() const { return _fields; }
00166
00167 int getSkip() const { return _ntoskip; }
00168 int getNumToReturn() const { return _ntoreturn; }
00169 bool wantMore() const { return _wantMore; }
00170 int getOptions() const { return _options; }
00171 bool hasOption( int x ) const { return x & _options; }
00172
00173
00174 bool isExplain() const { return _explain; }
00175 bool isSnapshot() const { return _snapshot; }
00176 bool returnKey() const { return _returnKey; }
00177 bool showDiskLoc() const { return _showDiskLoc; }
00178
00179 const BSONObj& getMin() const { return _min; }
00180 const BSONObj& getMax() const { return _max; }
00181 const BSONObj& getOrder() const { return _order; }
00182 const BSONElement& getHint() const { return _hint; }
00183 int getMaxScan() const { return _maxScan; }
00184
00185 bool couldBeCommand() const {
00186
00187 return _ntoreturn == 1 && strstr( _ns , ".$cmd" );
00188 }
00189
00190 bool hasIndexSpecifier() const {
00191 return ! _hint.eoo() || ! _min.isEmpty() || ! _max.isEmpty();
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201 bool enoughForFirstBatch( int n , int len ) const {
00202 if ( _ntoreturn == 0 )
00203 return ( len > 1024 * 1024 ) || n >= 101;
00204 return n >= _ntoreturn || len > MaxBytesToReturnToClientAtOnce;
00205 }
00206
00207 bool enough( int n ) const {
00208 if ( _ntoreturn == 0 )
00209 return false;
00210 return n >= _ntoreturn;
00211 }
00212
00213 private:
00214 void init( const BSONObj& q ) {
00215 _reset();
00216 uassert( 10105 , "bad skip value in query", _ntoskip >= 0);
00217
00218 if ( _ntoreturn < 0 ) {
00219
00220
00221
00222
00223 _wantMore = false;
00224 _ntoreturn = -_ntoreturn;
00225 }
00226
00227
00228 BSONElement e = q["query"];
00229 if ( ! e.isABSONObj() )
00230 e = q["$query"];
00231
00232 if ( e.isABSONObj() ) {
00233 _filter = e.embeddedObject();
00234 _initTop( q );
00235 }
00236 else {
00237 _filter = q;
00238 }
00239 }
00240
00241 void _reset() {
00242 _wantMore = true;
00243 _explain = false;
00244 _snapshot = false;
00245 _returnKey = false;
00246 _showDiskLoc = false;
00247 _maxScan = 0;
00248 }
00249
00250 void _initTop( const BSONObj& top ) {
00251 BSONObjIterator i( top );
00252 while ( i.more() ) {
00253 BSONElement e = i.next();
00254 const char * name = e.fieldName();
00255
00256 if ( strcmp( "$orderby" , name ) == 0 ||
00257 strcmp( "orderby" , name ) == 0 ) {
00258 if ( e.type() == Object ) {
00259 _order = e.embeddedObject();
00260 }
00261 else if ( e.type() == Array ) {
00262 _order = transformOrderFromArrayFormat( _order );
00263 }
00264 else {
00265 uassert(13513, "sort must be an object or array", 0);
00266 }
00267 }
00268 else if ( strcmp( "$explain" , name ) == 0 )
00269 _explain = e.trueValue();
00270 else if ( strcmp( "$snapshot" , name ) == 0 )
00271 _snapshot = e.trueValue();
00272 else if ( strcmp( "$min" , name ) == 0 )
00273 _min = e.embeddedObject();
00274 else if ( strcmp( "$max" , name ) == 0 )
00275 _max = e.embeddedObject();
00276 else if ( strcmp( "$hint" , name ) == 0 )
00277 _hint = e;
00278 else if ( strcmp( "$returnKey" , name ) == 0 )
00279 _returnKey = e.trueValue();
00280 else if ( strcmp( "$maxScan" , name ) == 0 )
00281 _maxScan = e.numberInt();
00282 else if ( strcmp( "$showDiskLoc" , name ) == 0 )
00283 _showDiskLoc = e.trueValue();
00284
00285
00286 }
00287
00288 if ( _snapshot ) {
00289 uassert( 12001 , "E12001 can't sort with $snapshot", _order.isEmpty() );
00290 uassert( 12002 , "E12002 can't use hint with $snapshot", _hint.eoo() );
00291 }
00292
00293 }
00294
00295 void initFields( const BSONObj& fields ) {
00296 if ( fields.isEmpty() )
00297 return;
00298 _fields.reset( new Projection() );
00299 _fields->init( fields );
00300 }
00301
00302 ParsedQuery( const ParsedQuery& other ) {
00303 assert(0);
00304 }
00305
00306 const char* _ns;
00307 int _ntoskip;
00308 int _ntoreturn;
00309 int _options;
00310
00311 BSONObj _filter;
00312 shared_ptr< Projection > _fields;
00313
00314 bool _wantMore;
00315
00316 bool _explain;
00317 bool _snapshot;
00318 bool _returnKey;
00319 bool _showDiskLoc;
00320 BSONObj _min;
00321 BSONObj _max;
00322 BSONElement _hint;
00323 BSONObj _order;
00324 int _maxScan;
00325 };
00326
00327
00328 }
00329
00330 #include "clientcursor.h"