diff options
Diffstat (limited to 'src/mongo/db/query/canonical_query.h')
-rw-r--r-- | src/mongo/db/query/canonical_query.h | 377 |
1 files changed, 194 insertions, 183 deletions
diff --git a/src/mongo/db/query/canonical_query.h b/src/mongo/db/query/canonical_query.h index 365a06e4802..58a2c46f3a8 100644 --- a/src/mongo/db/query/canonical_query.h +++ b/src/mongo/db/query/canonical_query.h @@ -38,188 +38,199 @@ namespace mongo { - class CanonicalQuery { - public: - /** - * Caller owns the pointer in 'out' if any call to canonicalize returns Status::OK(). - * - * Used for legacy find through the OP_QUERY message. - */ - static Status canonicalize(const QueryMessage& qm, - CanonicalQuery** out, - const MatchExpressionParser::WhereCallback& whereCallback = - MatchExpressionParser::WhereCallback()); - - /** - * Takes ownership of 'lpq'. - * - * Caller owns the pointer in 'out' if any call to canonicalize returns Status::OK(). - * - * Used for finds using the find command path. - */ - static Status canonicalize(LiteParsedQuery* lpq, - CanonicalQuery** out, - const MatchExpressionParser::WhereCallback& whereCallback = - MatchExpressionParser::WhereCallback()); - - /** - * For testing or for internal clients to use. - */ - - /** - * Used for creating sub-queries from an existing CanonicalQuery. - * - * 'root' must be an expression in baseQuery.root(). - * - * Does not take ownership of 'root'. - */ - static Status canonicalize(const CanonicalQuery& baseQuery, - MatchExpression* root, - CanonicalQuery** out, - const MatchExpressionParser::WhereCallback& whereCallback = - MatchExpressionParser::WhereCallback()); - - static Status canonicalize(const std::string& ns, - const BSONObj& query, - CanonicalQuery** out, - const MatchExpressionParser::WhereCallback& whereCallback = - MatchExpressionParser::WhereCallback()); - - static Status canonicalize(const std::string& ns, - const BSONObj& query, - bool explain, - CanonicalQuery** out, - const MatchExpressionParser::WhereCallback& whereCallback = - MatchExpressionParser::WhereCallback()); - - static Status canonicalize(const std::string& ns, - const BSONObj& query, - long long skip, - long long limit, - CanonicalQuery** out, - const MatchExpressionParser::WhereCallback& whereCallback = - MatchExpressionParser::WhereCallback()); - - static Status canonicalize(const std::string& ns, - const BSONObj& query, - const BSONObj& sort, - const BSONObj& proj, - CanonicalQuery** out, - const MatchExpressionParser::WhereCallback& whereCallback = - MatchExpressionParser::WhereCallback()); - - static Status canonicalize(const std::string& ns, - const BSONObj& query, - const BSONObj& sort, - const BSONObj& proj, - long long skip, - long long limit, - CanonicalQuery** out, - const MatchExpressionParser::WhereCallback& whereCallback = - MatchExpressionParser::WhereCallback()); - - static Status canonicalize(const std::string& ns, - const BSONObj& query, - const BSONObj& sort, - const BSONObj& proj, - long long skip, - long long limit, - const BSONObj& hint, - CanonicalQuery** out, - const MatchExpressionParser::WhereCallback& whereCallback = - MatchExpressionParser::WhereCallback()); - - static Status canonicalize(const std::string& ns, - const BSONObj& query, - const BSONObj& sort, - const BSONObj& proj, - long long skip, - long long limit, - const BSONObj& hint, - const BSONObj& minObj, - const BSONObj& maxObj, - bool snapshot, - bool explain, - CanonicalQuery** out, - const MatchExpressionParser::WhereCallback& whereCallback = - MatchExpressionParser::WhereCallback()); - - /** - * Returns true if "query" describes an exact-match query on _id, possibly with - * the $isolated/$atomic modifier. - */ - static bool isSimpleIdQuery(const BSONObj& query); - - // What namespace is this query over? - const std::string& ns() const { return _pq->ns(); } - - // - // Accessors for the query - // - MatchExpression* root() const { return _root.get(); } - BSONObj getQueryObj() const { return _pq->getFilter(); } - const LiteParsedQuery& getParsed() const { return *_pq; } - const ParsedProjection* getProj() const { return _proj.get(); } - - // Debugging - std::string toString() const; - std::string toStringShort() const; - - /** - * Validates match expression, checking for certain - * combinations of operators in match expression and - * query options in LiteParsedQuery. - * Since 'root' is derived from 'filter' in LiteParsedQuery, - * 'filter' is not validated. - * - * TODO: Move this to query_validator.cpp - */ - static Status isValid(MatchExpression* root, const LiteParsedQuery& parsed); - - /** - * Returns the normalized version of the subtree rooted at 'root'. - * - * Takes ownership of 'root'. - */ - static MatchExpression* normalizeTree(MatchExpression* root); - - /** - * Traverses expression tree post-order. - * Sorts children at each non-leaf node by (MatchType, path(), children, number of children) - */ - static void sortTree(MatchExpression* tree); - - /** - * Returns a count of 'type' nodes in expression tree. - */ - static size_t countNodes(const MatchExpression* root, MatchExpression::MatchType type); - - /** - * Takes ownership of 'tree'. Performs some rewriting of the query to a logically - * equivalent but more digestible form. - * - * TODO: This doesn't entirely belong here. Really we'd do this while exploring - * solutions in an enumeration setting but given the current lack of pruning - * while exploring the enumeration space we do it here. - */ - static MatchExpression* logicalRewrite(MatchExpression* tree); - private: - // You must go through canonicalize to create a CanonicalQuery. - CanonicalQuery() { } - - /** - * Takes ownership of 'root' and 'lpq'. - */ - Status init(LiteParsedQuery* lpq, - const MatchExpressionParser::WhereCallback& whereCallback, - MatchExpression* root); - - std::unique_ptr<LiteParsedQuery> _pq; - - // _root points into _pq->getFilter() - std::unique_ptr<MatchExpression> _root; - - std::unique_ptr<ParsedProjection> _proj; - }; +class CanonicalQuery { +public: + /** + * Caller owns the pointer in 'out' if any call to canonicalize returns Status::OK(). + * + * Used for legacy find through the OP_QUERY message. + */ + static Status canonicalize(const QueryMessage& qm, + CanonicalQuery** out, + const MatchExpressionParser::WhereCallback& whereCallback = + MatchExpressionParser::WhereCallback()); + + /** + * Takes ownership of 'lpq'. + * + * Caller owns the pointer in 'out' if any call to canonicalize returns Status::OK(). + * + * Used for finds using the find command path. + */ + static Status canonicalize(LiteParsedQuery* lpq, + CanonicalQuery** out, + const MatchExpressionParser::WhereCallback& whereCallback = + MatchExpressionParser::WhereCallback()); + + /** + * For testing or for internal clients to use. + */ + + /** + * Used for creating sub-queries from an existing CanonicalQuery. + * + * 'root' must be an expression in baseQuery.root(). + * + * Does not take ownership of 'root'. + */ + static Status canonicalize(const CanonicalQuery& baseQuery, + MatchExpression* root, + CanonicalQuery** out, + const MatchExpressionParser::WhereCallback& whereCallback = + MatchExpressionParser::WhereCallback()); + + static Status canonicalize(const std::string& ns, + const BSONObj& query, + CanonicalQuery** out, + const MatchExpressionParser::WhereCallback& whereCallback = + MatchExpressionParser::WhereCallback()); + + static Status canonicalize(const std::string& ns, + const BSONObj& query, + bool explain, + CanonicalQuery** out, + const MatchExpressionParser::WhereCallback& whereCallback = + MatchExpressionParser::WhereCallback()); + + static Status canonicalize(const std::string& ns, + const BSONObj& query, + long long skip, + long long limit, + CanonicalQuery** out, + const MatchExpressionParser::WhereCallback& whereCallback = + MatchExpressionParser::WhereCallback()); + + static Status canonicalize(const std::string& ns, + const BSONObj& query, + const BSONObj& sort, + const BSONObj& proj, + CanonicalQuery** out, + const MatchExpressionParser::WhereCallback& whereCallback = + MatchExpressionParser::WhereCallback()); + + static Status canonicalize(const std::string& ns, + const BSONObj& query, + const BSONObj& sort, + const BSONObj& proj, + long long skip, + long long limit, + CanonicalQuery** out, + const MatchExpressionParser::WhereCallback& whereCallback = + MatchExpressionParser::WhereCallback()); + + static Status canonicalize(const std::string& ns, + const BSONObj& query, + const BSONObj& sort, + const BSONObj& proj, + long long skip, + long long limit, + const BSONObj& hint, + CanonicalQuery** out, + const MatchExpressionParser::WhereCallback& whereCallback = + MatchExpressionParser::WhereCallback()); + + static Status canonicalize(const std::string& ns, + const BSONObj& query, + const BSONObj& sort, + const BSONObj& proj, + long long skip, + long long limit, + const BSONObj& hint, + const BSONObj& minObj, + const BSONObj& maxObj, + bool snapshot, + bool explain, + CanonicalQuery** out, + const MatchExpressionParser::WhereCallback& whereCallback = + MatchExpressionParser::WhereCallback()); + + /** + * Returns true if "query" describes an exact-match query on _id, possibly with + * the $isolated/$atomic modifier. + */ + static bool isSimpleIdQuery(const BSONObj& query); + + // What namespace is this query over? + const std::string& ns() const { + return _pq->ns(); + } + + // + // Accessors for the query + // + MatchExpression* root() const { + return _root.get(); + } + BSONObj getQueryObj() const { + return _pq->getFilter(); + } + const LiteParsedQuery& getParsed() const { + return *_pq; + } + const ParsedProjection* getProj() const { + return _proj.get(); + } + + // Debugging + std::string toString() const; + std::string toStringShort() const; + + /** + * Validates match expression, checking for certain + * combinations of operators in match expression and + * query options in LiteParsedQuery. + * Since 'root' is derived from 'filter' in LiteParsedQuery, + * 'filter' is not validated. + * + * TODO: Move this to query_validator.cpp + */ + static Status isValid(MatchExpression* root, const LiteParsedQuery& parsed); + + /** + * Returns the normalized version of the subtree rooted at 'root'. + * + * Takes ownership of 'root'. + */ + static MatchExpression* normalizeTree(MatchExpression* root); + + /** + * Traverses expression tree post-order. + * Sorts children at each non-leaf node by (MatchType, path(), children, number of children) + */ + static void sortTree(MatchExpression* tree); + + /** + * Returns a count of 'type' nodes in expression tree. + */ + static size_t countNodes(const MatchExpression* root, MatchExpression::MatchType type); + + /** + * Takes ownership of 'tree'. Performs some rewriting of the query to a logically + * equivalent but more digestible form. + * + * TODO: This doesn't entirely belong here. Really we'd do this while exploring + * solutions in an enumeration setting but given the current lack of pruning + * while exploring the enumeration space we do it here. + */ + static MatchExpression* logicalRewrite(MatchExpression* tree); + +private: + // You must go through canonicalize to create a CanonicalQuery. + CanonicalQuery() {} + + /** + * Takes ownership of 'root' and 'lpq'. + */ + Status init(LiteParsedQuery* lpq, + const MatchExpressionParser::WhereCallback& whereCallback, + MatchExpression* root); + + std::unique_ptr<LiteParsedQuery> _pq; + + // _root points into _pq->getFilter() + std::unique_ptr<MatchExpression> _root; + + std::unique_ptr<ParsedProjection> _proj; +}; } // namespace mongo |