diff options
author | Alya Berciu <alyacarina@gmail.com> | 2021-03-30 16:29:12 +0100 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-04-21 10:33:05 +0000 |
commit | 8736544c4a2f4fbd38792f656408f7b807b786d7 (patch) | |
tree | 954c7234c94454e41a1714b41718e241ded9e353 /src/mongo/db/pipeline/expression.h | |
parent | c90de3e65fff76ead7b8ca4664c3f34b0c913e04 (diff) | |
download | mongo-8736544c4a2f4fbd38792f656408f7b807b786d7.tar.gz |
SERVER-30417: Implement $getField expression
Co-authored-by: Katherine Wu <katherine.wu@mongodb.com>
Diffstat (limited to 'src/mongo/db/pipeline/expression.h')
-rw-r--r-- | src/mongo/db/pipeline/expression.h | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/mongo/db/pipeline/expression.h b/src/mongo/db/pipeline/expression.h index f89e45a46a1..e0571735a18 100644 --- a/src/mongo/db/pipeline/expression.h +++ b/src/mongo/db/pipeline/expression.h @@ -50,6 +50,7 @@ #include "mongo/db/pipeline/field_path.h" #include "mongo/db/pipeline/variables.h" #include "mongo/db/query/datetime/date_time_support.h" +#include "mongo/db/query/query_feature_flags_gen.h" #include "mongo/db/query/sort_pattern.h" #include "mongo/db/server_options.h" #include "mongo/util/intrusive_counter.h" @@ -78,6 +79,25 @@ class DocumentSource; } /** + * Registers a Parser so it can be called from parseExpression and friends (but only if + * 'featureFlag' is enabled). + * + * As an example, if your expression looks like {"$foo": [1,2,3]} and should be flag-guarded by + * feature_flags::gFoo, you would add this line: + * REGISTER_FEATURE_FLAG_GUARDED_EXPRESSION(foo, ExpressionFoo::parse, feature_flags::gFoo); + * + * An expression registered this way can be used in any featureCompatibilityVersion. + */ +#define REGISTER_FEATURE_FLAG_GUARDED_EXPRESSION(key, parser, featureFlag) \ + MONGO_INITIALIZER_GENERAL( \ + addToExpressionParserMap_##key, ("default"), ("expressionParserMap")) \ + (InitializerContext*) { \ + if (featureFlag.isEnabledAndIgnoreFCV()) { \ + Expression::registerExpression("$" #key, (parser), boost::none); \ + } \ + } + +/** * Registers a Parser so it can be called from parseExpression and friends. Use this version if your * expression can only be persisted to a catalog data structure in a feature compatibility version * >= X. @@ -3472,4 +3492,46 @@ private: // Accepted BSON type: String. If not specified, "sunday" is used. boost::intrusive_ptr<Expression>& _startOfWeek; }; + +class ExpressionGetField final : public Expression { +public: + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement exprElement, + const VariablesParseState& vps); + + /** + * Constructs a $getField expression where 'field' is an expression resolving to a string Value + * (or null) and 'from' is an expression resolving to an object Value (or null). + * + * If either 'field' or 'from' is nullish, $getField evaluates to null. Furthermore, if 'from' + * does not contain 'field', then $getField returns missing. + */ + ExpressionGetField(ExpressionContext* const expCtx, + boost::intrusive_ptr<Expression> field, + boost::intrusive_ptr<Expression> from) + : Expression(expCtx, {std::move(field), std::move(from)}), + _field(_children[0]), + _from(_children[1]) { + expCtx->sbeCompatible = false; + } + + Value serialize(const bool explain) const final; + + Value evaluate(const Document& root, Variables* variables) const final; + + boost::intrusive_ptr<Expression> optimize() final; + + void acceptVisitor(ExpressionVisitor* visitor) final { + return visitor->visit(this); + } + + static constexpr auto kExpressionName = "$getField"_sd; + +protected: + void _doAddDependencies(DepsTracker* deps) const final override; + +private: + boost::intrusive_ptr<Expression>& _field; + boost::intrusive_ptr<Expression>& _from; +}; } // namespace mongo |