summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline/expression.h
diff options
context:
space:
mode:
authorAlya Berciu <alyacarina@gmail.com>2021-03-30 16:29:12 +0100
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-04-21 10:33:05 +0000
commit8736544c4a2f4fbd38792f656408f7b807b786d7 (patch)
tree954c7234c94454e41a1714b41718e241ded9e353 /src/mongo/db/pipeline/expression.h
parentc90de3e65fff76ead7b8ca4664c3f34b0c913e04 (diff)
downloadmongo-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.h62
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