diff options
author | Mihai Andrei <mihai.andrei@10gen.com> | 2021-09-13 23:20:19 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-09-13 23:55:08 +0000 |
commit | 15c51de0d4700d490c71ca70f961c3c44c1d4a1c (patch) | |
tree | 6e415ce171ccc92eaa7bc1f250464e39d2450e67 /src/mongo/db/pipeline/accumulation_statement.h | |
parent | 926b0287318744f7ef751aa10e64ec310d36695e (diff) | |
download | mongo-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.h | 71 |
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; |