diff options
author | Charlie Swanson <charlie.swanson@mongodb.com> | 2019-05-21 17:22:25 -0400 |
---|---|---|
committer | Charlie Swanson <charlie.swanson@mongodb.com> | 2019-05-22 16:29:09 -0400 |
commit | 5594eeb9c42f5a28ebb20c8fcce87a2a1a01f6a5 (patch) | |
tree | 8453d01043b1bc67161a4ee684c69e637e989645 /src | |
parent | 76cf536d476b50994c75dd16ec5c7caca23759a5 (diff) | |
download | mongo-5594eeb9c42f5a28ebb20c8fcce87a2a1a01f6a5.tar.gz |
SERVER-41257 Disallow persisting new 4.2 expressions in FCV 4.0
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/pipeline/expression.cpp | 44 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression.h | 4 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression_context.cpp | 1 |
3 files changed, 45 insertions, 4 deletions
diff --git a/src/mongo/db/pipeline/expression.cpp b/src/mongo/db/pipeline/expression.cpp index 0e8984a81fa..d6068398342 100644 --- a/src/mongo/db/pipeline/expression.cpp +++ b/src/mongo/db/pipeline/expression.cpp @@ -4924,7 +4924,10 @@ Value ExpressionRound::evaluate(const Document& root) const { root, _children, getOpName(), Decimal128::kRoundTiesToEven, &std::round); } -REGISTER_EXPRESSION(round, ExpressionRound::parse); +REGISTER_EXPRESSION_WITH_MIN_VERSION( + round, + ExpressionRound::parse, + ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo42); const char* ExpressionRound::getOpName() const { return "$round"; } @@ -4934,6 +4937,30 @@ Value ExpressionTrunc::evaluate(const Document& root) const { root, _children, getOpName(), Decimal128::kRoundTowardZero, &std::trunc); } +intrusive_ptr<Expression> ExpressionTrunc::parse(const intrusive_ptr<ExpressionContext>& expCtx, + BSONElement elem, + const VariablesParseState& vps) { + // In version 4.2 we added new arguments. In all previous versions the expression existed but + // only supported a single argument. + const bool newArgumentsAllowed = + (!expCtx->maxFeatureCompatibilityVersion || + (*expCtx->maxFeatureCompatibilityVersion >= + ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo42)); + uassert( + ErrorCodes::QueryFeatureNotAllowed, + // TODO SERVER-31968 we would like to include the current version and the required minimum + // version in this error message, but using FeatureCompatibilityVersion::toString() would + // introduce a dependency cycle. + str::stream() + << elem.fieldNameStringData() + << " with >1 argument is not allowed in the current feature compatibility version. See " + << feature_compatibility_version_documentation::kCompatibilityLink + << " for more information.", + // Allow non-arrays since they will be rejected anyway by the parser below. + elem.type() != BSONType::Array || elem.Array().size() <= 1 || newArgumentsAllowed); + return ExpressionRangedArity<ExpressionTrunc, 1, 2>::parse(expCtx, elem, vps); +} + REGISTER_EXPRESSION(trunc, ExpressionTrunc::parse); const char* ExpressionTrunc::getOpName() const { return "$trunc"; @@ -6015,7 +6042,10 @@ void ExpressionRegex::_doAddDependencies(DepsTracker* deps) const { /* -------------------------- ExpressionRegexFind ------------------------------ */ -REGISTER_EXPRESSION(regexFind, ExpressionRegexFind::parse); +REGISTER_EXPRESSION_WITH_MIN_VERSION( + regexFind, + ExpressionRegexFind::parse, + ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo42); boost::intrusive_ptr<Expression> ExpressionRegexFind::parse( const boost::intrusive_ptr<ExpressionContext>& expCtx, BSONElement expr, @@ -6036,7 +6066,10 @@ Value ExpressionRegexFind::evaluate(const Document& root) const { /* -------------------------- ExpressionRegexFindAll ------------------------------ */ -REGISTER_EXPRESSION(regexFindAll, ExpressionRegexFindAll::parse); +REGISTER_EXPRESSION_WITH_MIN_VERSION( + regexFindAll, + ExpressionRegexFindAll::parse, + ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo42); boost::intrusive_ptr<Expression> ExpressionRegexFindAll::parse( const boost::intrusive_ptr<ExpressionContext>& expCtx, BSONElement expr, @@ -6097,7 +6130,10 @@ Value ExpressionRegexFindAll::evaluate(const Document& root) const { /* -------------------------- ExpressionRegexMatch ------------------------------ */ -REGISTER_EXPRESSION(regexMatch, ExpressionRegexMatch::parse); +REGISTER_EXPRESSION_WITH_MIN_VERSION( + regexMatch, + ExpressionRegexMatch::parse, + ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo42); boost::intrusive_ptr<Expression> ExpressionRegexMatch::parse( const boost::intrusive_ptr<ExpressionContext>& expCtx, BSONElement expr, diff --git a/src/mongo/db/pipeline/expression.h b/src/mongo/db/pipeline/expression.h index 7033ee717d1..7ec1700afb3 100644 --- a/src/mongo/db/pipeline/expression.h +++ b/src/mongo/db/pipeline/expression.h @@ -2325,6 +2325,10 @@ public: explicit ExpressionTrunc(const boost::intrusive_ptr<ExpressionContext>& expCtx) : ExpressionRangedArity<ExpressionTrunc, 1, 2>(expCtx) {} + static boost::intrusive_ptr<Expression> parse( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONElement elem, + const VariablesParseState& vps); Value evaluate(const Document& root) const final; const char* getOpName() const final; diff --git a/src/mongo/db/pipeline/expression_context.cpp b/src/mongo/db/pipeline/expression_context.cpp index 0054e0de98c..9f65c12669f 100644 --- a/src/mongo/db/pipeline/expression_context.cpp +++ b/src/mongo/db/pipeline/expression_context.cpp @@ -160,6 +160,7 @@ intrusive_ptr<ExpressionContext> ExpressionContext::copyWith( expCtx->inMongos = inMongos; expCtx->allowDiskUse = allowDiskUse; expCtx->bypassDocumentValidation = bypassDocumentValidation; + expCtx->maxFeatureCompatibilityVersion = maxFeatureCompatibilityVersion; expCtx->subPipelineDepth = subPipelineDepth; expCtx->tempDir = tempDir; |