diff options
Diffstat (limited to 'src/mongo/db/matcher/expression_parser.h')
-rw-r--r-- | src/mongo/db/matcher/expression_parser.h | 78 |
1 files changed, 60 insertions, 18 deletions
diff --git a/src/mongo/db/matcher/expression_parser.h b/src/mongo/db/matcher/expression_parser.h index 1adb7640ed1..6091d3f1426 100644 --- a/src/mongo/db/matcher/expression_parser.h +++ b/src/mongo/db/matcher/expression_parser.h @@ -36,8 +36,10 @@ #include "mongo/db/matcher/expression_leaf.h" #include "mongo/db/matcher/expression_tree.h" #include "mongo/db/matcher/expression_type.h" +#include "mongo/db/matcher/expression_with_placeholder.h" #include "mongo/db/matcher/extensions_callback.h" #include "mongo/db/matcher/extensions_callback_noop.h" +#include "mongo/db/matcher/schema/expression_internal_schema_allowed_properties.h" #include "mongo/db/pipeline/expression.h" #include "mongo/db/pipeline/expression_context.h" #include "mongo/stdx/functional.h" @@ -127,9 +129,8 @@ public: const ExtensionsCallback& extensionsCallback = ExtensionsCallbackNoop(), AllowedFeatureSet allowedFeatures = kDefaultSpecialFeatures) { invariant(expCtx.get()); - const bool topLevelCall = true; return MatchExpressionParser(&extensionsCallback) - ._parse(obj, expCtx, allowedFeatures, topLevelCall); + ._parse(obj, expCtx, allowedFeatures, DocumentParseLevel::kPredicateTopLevel); } /** @@ -154,6 +155,23 @@ public: static StatusWith<long long> parseIntegerElementToLong(BSONElement elem); private: + /** + * 'DocumentParseLevel' refers to the current position of the parser as it descends a + * MatchExpression tree. + */ + enum class DocumentParseLevel { + // Indicates that the parser is looking at the root level of the BSON object containing the + // user's query predicate. + kPredicateTopLevel, + // Indicates that match expression nodes in this position will match against the complete + // user document, as opposed to matching against a nested document or a subdocument inside + // an array. + kUserDocumentTopLevel, + // Indicates that match expression nodes in this position will match against a nested + // document or a subdocument inside an array. + kUserSubDocument, + }; + MatchExpressionParser(const ExtensionsCallback* extensionsCallback) : _extensionsCallback(extensionsCallback) {} @@ -179,26 +197,23 @@ private: /** * Parse 'obj' and return either a MatchExpression or an error. - * - * 'topLevel' indicates whether or not the we are at the top level of the tree across recursive - * class to this function. This is used to apply special logic at the top level. */ StatusWithMatchExpression _parse(const BSONObj& obj, const boost::intrusive_ptr<ExpressionContext>& expCtx, AllowedFeatureSet allowedFeatures, - bool topLevel); + DocumentParseLevel currentLevel); /** * parses a field in a sub expression * if the query is { x : { $gt : 5, $lt : 8 } } - * e is { $gt : 5, $lt : 8 } + * obj is { $gt : 5, $lt : 8 } */ Status _parseSub(const char* name, const BSONObj& obj, AndMatchExpression* root, const boost::intrusive_ptr<ExpressionContext>& expCtx, AllowedFeatureSet allowedFeatures, - bool topLevel); + DocumentParseLevel currentLevel); /** * parses a single field in a sub expression @@ -211,7 +226,7 @@ private: const BSONElement& e, const boost::intrusive_ptr<ExpressionContext>& expCtx, AllowedFeatureSet allowedFeatures, - bool topLevel); + DocumentParseLevel currentLevel); StatusWithMatchExpression _parseComparison( const char* name, @@ -247,14 +262,12 @@ private: StatusWithMatchExpression _parseElemMatch(const char* name, const BSONElement& e, const boost::intrusive_ptr<ExpressionContext>& expCtx, - AllowedFeatureSet allowedFeatures, - bool topLevel); + AllowedFeatureSet allowedFeatures); StatusWithMatchExpression _parseAll(const char* name, const BSONElement& e, const boost::intrusive_ptr<ExpressionContext>& expCtx, - AllowedFeatureSet allowedFeatures, - bool topLevel); + AllowedFeatureSet allowedFeatures); // tree @@ -262,13 +275,13 @@ private: ListOfMatchExpression* out, const boost::intrusive_ptr<ExpressionContext>& expCtx, AllowedFeatureSet allowedFeatures, - bool topLevel); + DocumentParseLevel currentLevel); StatusWithMatchExpression _parseNot(const char* name, const BSONElement& e, const boost::intrusive_ptr<ExpressionContext>& expCtx, AllowedFeatureSet allowedFeatures, - bool topLevel); + DocumentParseLevel currentLevel); /** * Parses 'e' into a BitTestMatchExpression. @@ -284,6 +297,29 @@ private: StatusWithMatchExpression _parseInternalSchemaFmod(const char* name, const BSONElement& e); /** + * Looks at the field named 'exprWithPlaceholderFieldName' within 'containingObject' and parses + * an ExpressionWithPlaceholder from that element. Fails if an error occurs during parsing, or + * if the ExpressionWithPlaceholder has a different name placeholder than 'expectedPlaceholder'. + * 'expressionName' is the name of the expression that requires the ExpressionWithPlaceholder + * and is used to generate helpful error messages. + */ + StatusWith<std::unique_ptr<ExpressionWithPlaceholder>> _parseExprWithPlaceholder( + const BSONObj& containingObject, + StringData exprWithPlaceholderFieldName, + StringData expressionName, + StringData expectedPlaceholder, + const boost::intrusive_ptr<ExpressionContext>& expCtx, + AllowedFeatureSet allowedFeatures, + DocumentParseLevel currentLevel); + + StatusWith<std::vector<InternalSchemaAllowedPropertiesMatchExpression::PatternSchema>> + _parsePatternProperties(BSONElement patternPropertiesElem, + StringData expectedPlaceholder, + const boost::intrusive_ptr<ExpressionContext>& expCtx, + AllowedFeatureSet allowedFeatures, + DocumentParseLevel currentLevel); + + /** * Parses a MatchExpression which takes a fixed-size array of MatchExpressions as arguments. */ template <class T> @@ -291,7 +327,8 @@ private: StringData name, const BSONElement& elem, const boost::intrusive_ptr<ExpressionContext>& expCtx, - AllowedFeatureSet allowedFeatures); + AllowedFeatureSet allowedFeatures, + DocumentParseLevel currentLevel); /** * Parses the given BSONElement into a single integer argument and creates a MatchExpression @@ -315,10 +352,15 @@ private: StatusWithMatchExpression _parseInternalSchemaMatchArrayIndex( const char* path, const BSONElement& elem, - const boost::intrusive_ptr<ExpressionContext>& expCtx); + const boost::intrusive_ptr<ExpressionContext>& expCtx, + AllowedFeatureSet allowedFeatures, + DocumentParseLevel currentLevel); StatusWithMatchExpression _parseInternalSchemaAllowedProperties( - const BSONElement& elem, const boost::intrusive_ptr<ExpressionContext>& expCtx); + const BSONElement& elem, + const boost::intrusive_ptr<ExpressionContext>& expCtx, + AllowedFeatureSet allowedFeatures, + DocumentParseLevel currentLevel); // Performs parsing for the match extensions. We do not own this pointer - it has to live // as long as the parser is active. |