PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/src/mongo/db/ops/query.h

http://github.com/mongodb/mongo
C Header | 311 lines | 189 code | 26 blank | 96 comment | 0 complexity | eba8ec3e0782b1a631c77b6644620690 MD5 | raw file
Possible License(s): BSD-3-Clause-No-Nuclear-License-2014, GPL-2.0, Apache-2.0, BSD-3-Clause, WTFPL
  1. // query.h
  2. /**
  3. * Copyright (C) 2008 10gen Inc.
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License, version 3,
  7. * as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU Affero General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Affero General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #pragma once
  18. #include "mongo/pch.h"
  19. #include "../../util/net/message.h"
  20. #include "../dbmessage.h"
  21. #include "../jsobj.h"
  22. #include "../diskloc.h"
  23. #include "../explain.h"
  24. #include "../../s/d_chunk_manager.h"
  25. // struct QueryOptions, QueryResult, QueryResultFlags in:
  26. namespace mongo {
  27. class ParsedQuery;
  28. class QueryOptimizerCursor;
  29. class QueryPlanSummary;
  30. QueryResult* processGetMore(const char *ns, int ntoreturn, long long cursorid , CurOp& op, int pass, bool& exhaust);
  31. string runQuery(Message& m, QueryMessage& q, CurOp& curop, Message &result);
  32. /** Exception indicating that a query should be retried from the beginning. */
  33. class QueryRetryException : public DBException {
  34. public:
  35. QueryRetryException() : DBException( "query retry exception" , 16083 ) {
  36. return;
  37. massert( 16083, "reserve 16083", true ); // Reserve 16083.
  38. }
  39. };
  40. /** Metadata about matching and loading a single candidate result document from a Cursor. */
  41. struct ResultDetails {
  42. ResultDetails();
  43. MatchDetails matchDetails; // Details on how the Matcher matched the query.
  44. bool match; // Matched the query, was not a dup, was not skipped etc.
  45. bool orderedMatch; // _match and belonged to an ordered query plan.
  46. bool loadedRecord; // Record was loaded (to match or return the document).
  47. bool chunkSkip; // Did not belong to an owned chunk range.
  48. };
  49. /** Interface for recording events that contribute to explain results. */
  50. class ExplainRecordingStrategy {
  51. public:
  52. ExplainRecordingStrategy( const ExplainQueryInfo::AncillaryInfo &ancillaryInfo );
  53. virtual ~ExplainRecordingStrategy() {}
  54. /** Note information about a single query plan. */
  55. virtual void notePlan( bool scanAndOrder, bool indexOnly ) {}
  56. /** Note an iteration of the query. */
  57. virtual void noteIterate( const ResultDetails& resultDetails ) {}
  58. /** Note that the query yielded. */
  59. virtual void noteYield() {}
  60. /** @return number of ordered matches noted. */
  61. virtual long long orderedMatches() const { return 0; }
  62. /** @return ExplainQueryInfo for a complete query. */
  63. shared_ptr<ExplainQueryInfo> doneQueryInfo();
  64. protected:
  65. /** @return ExplainQueryInfo for a complete query, to be implemented by subclass. */
  66. virtual shared_ptr<ExplainQueryInfo> _doneQueryInfo() = 0;
  67. private:
  68. ExplainQueryInfo::AncillaryInfo _ancillaryInfo;
  69. };
  70. /** No explain events are recorded. */
  71. class NoExplainStrategy : public ExplainRecordingStrategy {
  72. public:
  73. NoExplainStrategy();
  74. private:
  75. /** @asserts always. */
  76. virtual shared_ptr<ExplainQueryInfo> _doneQueryInfo();
  77. };
  78. class MatchCountingExplainStrategy : public ExplainRecordingStrategy {
  79. public:
  80. MatchCountingExplainStrategy( const ExplainQueryInfo::AncillaryInfo &ancillaryInfo );
  81. protected:
  82. virtual void _noteIterate( const ResultDetails& resultDetails ) = 0;
  83. private:
  84. virtual void noteIterate( const ResultDetails& resultDetails );
  85. virtual long long orderedMatches() const { return _orderedMatches; }
  86. long long _orderedMatches;
  87. };
  88. /** Record explain events for a simple cursor representing a single clause and plan. */
  89. class SimpleCursorExplainStrategy : public MatchCountingExplainStrategy {
  90. public:
  91. SimpleCursorExplainStrategy( const ExplainQueryInfo::AncillaryInfo &ancillaryInfo,
  92. const shared_ptr<Cursor> &cursor );
  93. private:
  94. virtual void notePlan( bool scanAndOrder, bool indexOnly );
  95. virtual void _noteIterate( const ResultDetails& resultDetails );
  96. virtual void noteYield();
  97. virtual shared_ptr<ExplainQueryInfo> _doneQueryInfo();
  98. shared_ptr<Cursor> _cursor;
  99. shared_ptr<ExplainSinglePlanQueryInfo> _explainInfo;
  100. };
  101. /**
  102. * Record explain events for a QueryOptimizerCursor, which may record some explain information
  103. * for multiple clauses and plans through an internal implementation.
  104. */
  105. class QueryOptimizerCursorExplainStrategy : public MatchCountingExplainStrategy {
  106. public:
  107. QueryOptimizerCursorExplainStrategy( const ExplainQueryInfo::AncillaryInfo &ancillaryInfo,
  108. const shared_ptr<QueryOptimizerCursor> &cursor );
  109. private:
  110. virtual void _noteIterate( const ResultDetails& resultDetails );
  111. virtual void noteYield();
  112. virtual shared_ptr<ExplainQueryInfo> _doneQueryInfo();
  113. shared_ptr<QueryOptimizerCursor> _cursor;
  114. };
  115. /** Interface for building a query response in a supplied BufBuilder. */
  116. class ResponseBuildStrategy {
  117. public:
  118. /**
  119. * @param queryPlan must be supplied if @param cursor is not a QueryOptimizerCursor and
  120. * results must be sorted or read with a covered index.
  121. */
  122. ResponseBuildStrategy( const ParsedQuery &parsedQuery, const shared_ptr<Cursor> &cursor,
  123. BufBuilder &buf );
  124. virtual ~ResponseBuildStrategy() {}
  125. /**
  126. * Handle the current iterate of the supplied cursor as a (possibly duplicate) match.
  127. * @return true if a match is found.
  128. * @param resultDetails details of how the result is matched and loaded.
  129. */
  130. virtual bool handleMatch( ResultDetails* resultDetails ) = 0;
  131. /**
  132. * Write all matches into the buffer, overwriting existing data.
  133. * @return number of matches written, or -1 if no op.
  134. */
  135. virtual int rewriteMatches() { return -1; }
  136. /** @return the number of matches that have been written to the buffer. */
  137. virtual int bufferedMatches() const = 0;
  138. /**
  139. * Callback when enough results have been read for the first batch, with potential handoff
  140. * to getMore.
  141. */
  142. virtual void finishedFirstBatch() {}
  143. /** Reset the buffer. */
  144. void resetBuf();
  145. protected:
  146. /**
  147. * Return the document for the current iterate. Implements the $returnKey option.
  148. * @param allowCovered enable covered index support.
  149. * @param resultDetails details of how the result is loaded.
  150. */
  151. BSONObj current( bool allowCovered, ResultDetails* resultDetails ) const;
  152. const ParsedQuery &_parsedQuery;
  153. shared_ptr<Cursor> _cursor;
  154. shared_ptr<QueryOptimizerCursor> _queryOptimizerCursor;
  155. BufBuilder &_buf;
  156. };
  157. /** Build strategy for a cursor returning in order results. */
  158. class OrderedBuildStrategy : public ResponseBuildStrategy {
  159. public:
  160. OrderedBuildStrategy( const ParsedQuery &parsedQuery, const shared_ptr<Cursor> &cursor,
  161. BufBuilder &buf );
  162. virtual bool handleMatch( ResultDetails* resultDetails );
  163. virtual int bufferedMatches() const { return _bufferedMatches; }
  164. private:
  165. int _skip;
  166. int _bufferedMatches;
  167. };
  168. class ScanAndOrder;
  169. /** Build strategy for a cursor returning out of order results. */
  170. class ReorderBuildStrategy : public ResponseBuildStrategy {
  171. public:
  172. static ReorderBuildStrategy* make( const ParsedQuery& parsedQuery,
  173. const shared_ptr<Cursor>& cursor,
  174. BufBuilder& buf,
  175. const QueryPlanSummary& queryPlan );
  176. virtual bool handleMatch( ResultDetails* resultDetails );
  177. /** Handle a match without performing deduping. */
  178. void _handleMatchNoDedup( ResultDetails* resultDetails );
  179. virtual int rewriteMatches();
  180. virtual int bufferedMatches() const { return _bufferedMatches; }
  181. private:
  182. ReorderBuildStrategy( const ParsedQuery& parsedQuery,
  183. const shared_ptr<Cursor>& cursor,
  184. BufBuilder& buf );
  185. void init( const QueryPlanSummary& queryPlan );
  186. ScanAndOrder *newScanAndOrder( const QueryPlanSummary &queryPlan ) const;
  187. shared_ptr<ScanAndOrder> _scanAndOrder;
  188. int _bufferedMatches;
  189. };
  190. /** Helper class for deduping DiskLocs */
  191. class DiskLocDupSet {
  192. public:
  193. /** @return true if dup, otherwise return false and insert. */
  194. bool getsetdup( const DiskLoc &loc ) {
  195. pair<set<DiskLoc>::iterator, bool> p = _dups.insert(loc);
  196. return !p.second;
  197. }
  198. private:
  199. set<DiskLoc> _dups;
  200. };
  201. /**
  202. * Build strategy for a QueryOptimizerCursor containing some in order and some out of order
  203. * candidate plans.
  204. */
  205. class HybridBuildStrategy : public ResponseBuildStrategy {
  206. public:
  207. static HybridBuildStrategy* make( const ParsedQuery& parsedQuery,
  208. const shared_ptr<QueryOptimizerCursor>& cursor,
  209. BufBuilder& buf );
  210. private:
  211. HybridBuildStrategy( const ParsedQuery &parsedQuery,
  212. const shared_ptr<QueryOptimizerCursor> &cursor,
  213. BufBuilder &buf );
  214. void init();
  215. virtual bool handleMatch( ResultDetails* resultDetails );
  216. virtual int rewriteMatches();
  217. virtual int bufferedMatches() const;
  218. virtual void finishedFirstBatch();
  219. bool handleReorderMatch( ResultDetails* resultDetails );
  220. DiskLocDupSet _scanAndOrderDups;
  221. OrderedBuildStrategy _orderedBuild;
  222. scoped_ptr<ReorderBuildStrategy> _reorderBuild;
  223. bool _reorderedMatches;
  224. };
  225. /**
  226. * Builds a query response with the help of an ExplainRecordingStrategy and a
  227. * ResponseBuildStrategy.
  228. */
  229. class QueryResponseBuilder {
  230. public:
  231. /**
  232. * @param queryPlan must be supplied if @param cursor is not a QueryOptimizerCursor and
  233. * results must be sorted or read with a covered index.
  234. */
  235. static QueryResponseBuilder *make( const ParsedQuery &parsedQuery,
  236. const shared_ptr<Cursor> &cursor,
  237. const QueryPlanSummary &queryPlan,
  238. const BSONObj &oldPlan );
  239. /** @return true if the current iterate matches and is added. */
  240. bool addMatch();
  241. /** Note that a yield occurred. */
  242. void noteYield();
  243. /** @return true if there are enough results to return the first batch. */
  244. bool enoughForFirstBatch() const;
  245. /** @return true if there are enough results to return the full result set. */
  246. bool enoughTotalResults() const;
  247. /**
  248. * Callback when enough results have been read for the first batch, with potential handoff
  249. * to getMore.
  250. */
  251. void finishedFirstBatch();
  252. /**
  253. * Set the data portion of the supplied Message to a buffer containing the query results.
  254. * @return the number of results in the buffer.
  255. */
  256. int handoff( Message &result );
  257. /** A chunk manager found at the beginning of the query. */
  258. ShardChunkManagerPtr chunkManager() const { return _chunkManager; }
  259. private:
  260. QueryResponseBuilder( const ParsedQuery &parsedQuery, const shared_ptr<Cursor> &cursor );
  261. void init( const QueryPlanSummary &queryPlan, const BSONObj &oldPlan );
  262. ShardChunkManagerPtr newChunkManager() const;
  263. shared_ptr<ExplainRecordingStrategy> newExplainRecordingStrategy
  264. ( const QueryPlanSummary &queryPlan, const BSONObj &oldPlan ) const;
  265. shared_ptr<ResponseBuildStrategy> newResponseBuildStrategy
  266. ( const QueryPlanSummary &queryPlan );
  267. /**
  268. * @return true if the cursor's document matches the query.
  269. * @param resultDetails describes how the document was matched and loaded.
  270. */
  271. bool currentMatches( ResultDetails* resultDetails );
  272. /**
  273. * @return true if the cursor's document is in a valid chunk range.
  274. * @param resultDetails describes how the document was matched and loaded.
  275. */
  276. bool chunkMatches( ResultDetails* resultDetails );
  277. const ParsedQuery &_parsedQuery;
  278. shared_ptr<Cursor> _cursor;
  279. shared_ptr<QueryOptimizerCursor> _queryOptimizerCursor;
  280. BufBuilder _buf;
  281. ShardChunkManagerPtr _chunkManager;
  282. shared_ptr<ExplainRecordingStrategy> _explain;
  283. shared_ptr<ResponseBuildStrategy> _builder;
  284. };
  285. } // namespace mongo