summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline/accumulation_statement.h
diff options
context:
space:
mode:
authorMihai Andrei <mihai.andrei@10gen.com>2021-09-13 23:20:19 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-09-13 23:55:08 +0000
commit15c51de0d4700d490c71ca70f961c3c44c1d4a1c (patch)
tree6e415ce171ccc92eaa7bc1f250464e39d2450e67 /src/mongo/db/pipeline/accumulation_statement.h
parent926b0287318744f7ef751aa10e64ec310d36695e (diff)
downloadmongo-15c51de0d4700d490c71ca70f961c3c44c1d4a1c.tar.gz
SERVER-58379 Extend REGISTER macros to support API version, FCV, and conditional checks for accumulators, expressions, and window functions
Diffstat (limited to 'src/mongo/db/pipeline/accumulation_statement.h')
-rw-r--r--src/mongo/db/pipeline/accumulation_statement.h71
1 files changed, 56 insertions, 15 deletions
diff --git a/src/mongo/db/pipeline/accumulation_statement.h b/src/mongo/db/pipeline/accumulation_statement.h
index e473d5d7ea1..b056b3ca2d9 100644
--- a/src/mongo/db/pipeline/accumulation_statement.h
+++ b/src/mongo/db/pipeline/accumulation_statement.h
@@ -43,15 +43,45 @@ namespace mongo {
* you would add this line:
* REGISTER_ACCUMULATOR(foo, AccumulatorFoo::create);
*/
-#define REGISTER_ACCUMULATOR(key, factory) \
- REGISTER_ACCUMULATOR_WITH_MIN_VERSION(key, factory, boost::none)
-
-#define REGISTER_ACCUMULATOR_WITH_MIN_VERSION(key, factory, minVersion) \
- MONGO_INITIALIZER_GENERAL(addToAccumulatorFactoryMap_##key, \
- ("BeginAccumulatorRegistration"), \
- ("EndAccumulatorRegistration")) \
- (InitializerContext*) { \
- AccumulationStatement::registerAccumulator("$" #key, (factory), (minVersion)); \
+#define REGISTER_ACCUMULATOR(key, factory) \
+ REGISTER_ACCUMULATOR_CONDITIONALLY(key, \
+ factory, \
+ AllowedWithApiStrict::kAlways, \
+ AllowedWithClientType::kAny, \
+ boost::none, \
+ true)
+
+#define REGISTER_ACCUMULATOR_WITH_MIN_VERSION(key, factory, minVersion) \
+ REGISTER_ACCUMULATOR_CONDITIONALLY(key, \
+ factory, \
+ AllowedWithApiStrict::kAlways, \
+ AllowedWithClientType::kAny, \
+ minVersion, \
+ true)
+
+/**
+ * Like REGISTER_ACCUMULATOR_WITH_MIN_VERSION, except you can also specify a condition,
+ * evaluated during startup, that decides whether to register the parser.
+ *
+ * For example, you could check a feature flag, and register the parser only when it's enabled.
+ *
+ * Note that the condition is evaluated only once, during a MONGO_INITIALIZER. Don't specify
+ * a condition that can change at runtime, such as FCV. (Feature flags are ok, because they
+ * cannot be toggled at runtime.)
+ *
+ * This is the most general REGISTER_ACCUMULATOR* macro, which all others should delegate to.
+ */
+#define REGISTER_ACCUMULATOR_CONDITIONALLY( \
+ key, factory, allowedWithApiStrict, allowedClientType, minVersion, ...) \
+ MONGO_INITIALIZER_GENERAL(addToAccumulatorFactoryMap_##key, \
+ ("BeginAccumulatorRegistration"), \
+ ("EndAccumulatorRegistration")) \
+ (InitializerContext*) { \
+ if (!(__VA_ARGS__)) { \
+ return; \
+ } \
+ AccumulationStatement::registerAccumulator( \
+ "$" #key, (factory), (allowedWithApiStrict), (allowedClientType), (minVersion)); \
}
/**
@@ -179,6 +209,16 @@ public:
using Parser = std::function<AccumulationExpression(
ExpressionContext* const, BSONElement, VariablesParseState)>;
+ /**
+ * Associates a Parser with information regarding which contexts it can be used in, including
+ * API Version and FCV.
+ */
+ using ParserRegistration =
+ std::tuple<Parser,
+ AllowedWithApiStrict,
+ AllowedWithClientType,
+ boost::optional<multiversion::FeatureCompatibilityVersion>>;
+
AccumulationStatement(std::string fieldName, AccumulationExpression expr)
: fieldName(std::move(fieldName)), expr(std::move(expr)) {}
@@ -186,7 +226,9 @@ public:
* Parses a BSONElement that is an accumulated field, and returns an AccumulationStatement for
* that accumulated field.
*
- * Throws an AssertionException if parsing fails.
+ * Throws an AssertionException if parsing fails, if the configured API version is not
+ * compatible with this AccumulationStatement, or if the Parser is registered under an FCV
+ * greater than the specified maximum allowed FCV.
*/
static AccumulationStatement parseAccumulationStatement(ExpressionContext* expCtx,
const BSONElement& elem,
@@ -203,16 +245,15 @@ public:
static void registerAccumulator(
std::string name,
Parser parser,
+ AllowedWithApiStrict allowedWithApiStrict,
+ AllowedWithClientType allowedWithClientType,
boost::optional<multiversion::FeatureCompatibilityVersion> requiredMinVersion);
/**
* Retrieves the Parser for the accumulator specified by the given name, and raises an error if
- * there is no such Parser registered, or the Parser is registered under an FCV greater than the
- * specified maximum allowed FCV.
+ * there is no such Parser registered.
*/
- static Parser& getParser(
- StringData name,
- boost::optional<multiversion::FeatureCompatibilityVersion> allowedMaxVersion);
+ static ParserRegistration& getParser(StringData name);
// The field name is used to store the results of the accumulation in a result document.
std::string fieldName;