diff options
author | Mindaugas Malinauskas <mindaugas.malinauskas@mongodb.com> | 2020-08-21 10:54:14 +0300 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-08-31 12:08:32 +0000 |
commit | f5da4e4b7f7f04267bd92736ee9b16417e6d70ff (patch) | |
tree | f0ae8b67db601735b166dc1b592d21f4c92d7ad7 /src | |
parent | 1eb0308decd6709fe9d0df9212fa690cd20e03fd (diff) | |
download | mongo-f5da4e4b7f7f04267bd92736ee9b16417e6d70ff.tar.gz |
SERVER-49499 Upgrade/downgrade behavior and testing for generating document validation errors
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/base/error_codes.yml | 4 | ||||
-rw-r--r-- | src/mongo/db/catalog/collection_impl.cpp | 20 | ||||
-rw-r--r-- | src/mongo/db/commands/write_commands/write_commands.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/matcher/doc_validation_error.cpp | 8 |
4 files changed, 30 insertions, 7 deletions
diff --git a/src/mongo/base/error_codes.yml b/src/mongo/base/error_codes.yml index fe34bf4f7d8..676d675dc00 100644 --- a/src/mongo/base/error_codes.yml +++ b/src/mongo/base/error_codes.yml @@ -153,7 +153,9 @@ error_codes: - {code: 120,name: OplogStartMissing} # Error code 121 is only for the document validator on collections. - {code: 121,name: DocumentValidationFailure, - extra: 'doc_validation_error::DocumentValidationFailureInfo'} + extra: 'doc_validation_error::DocumentValidationFailureInfo', + # TODO SERVER-50524: Make extra info mandatory when 5.0 becomes last-lts. + extraIsOptional: True} - {code: 122,name: OBSOLETE_ReadAfterOptimeTimeout} - {code: 123,name: NotAReplicaSet} - {code: 124,name: IncompatibleElectionProtocol} diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp index 30520fe8a54..c113ce8e34c 100644 --- a/src/mongo/db/catalog/collection_impl.cpp +++ b/src/mongo/db/catalog/collection_impl.cpp @@ -65,6 +65,7 @@ #include "mongo/db/query/internal_plans.h" #include "mongo/db/repl/oplog.h" #include "mongo/db/repl/replication_coordinator.h" +#include "mongo/db/server_options.h" #include "mongo/db/service_context.h" #include "mongo/db/storage/durable_catalog.h" #include "mongo/db/storage/key_string.h" @@ -400,7 +401,15 @@ Status CollectionImpl::checkValidation(OperationContext* opCtx, const BSONObj& d if (validatorMatchExpr->matchesBSON(document)) return Status::OK(); - BSONObj generatedError = doc_validation_error::generateError(*validatorMatchExpr, document); + // TODO SERVER-50524: remove these FCV checks when 5.0 becomes last-lts in order to make sure + // that an upgrade from 4.4 directly to the 5.0 LTS version is supported. + const auto isFCVAtLeast47 = serverGlobalParams.featureCompatibility.isVersionInitialized() && + serverGlobalParams.featureCompatibility.isGreaterThanOrEqualTo( + ServerGlobalParams::FeatureCompatibility::Version::kVersion47); + BSONObj generatedError; + if (isFCVAtLeast47) { + generatedError = doc_validation_error::generateError(*validatorMatchExpr, document); + } if (_validationAction == ValidationAction::WARN) { LOGV2_WARNING(20294, @@ -411,8 +420,13 @@ Status CollectionImpl::checkValidation(OperationContext* opCtx, const BSONObj& d return Status::OK(); } - return {doc_validation_error::DocumentValidationFailureInfo(generatedError), - "Document failed validation"}; + static constexpr auto kValidationFailureErrorStr = "Document failed validation"_sd; + if (isFCVAtLeast47) { + return {doc_validation_error::DocumentValidationFailureInfo(generatedError), + kValidationFailureErrorStr}; + } else { + return {ErrorCodes::DocumentValidationFailure, kValidationFailureErrorStr}; + } } Collection::Validator CollectionImpl::parseValidator( diff --git a/src/mongo/db/commands/write_commands/write_commands.cpp b/src/mongo/db/commands/write_commands/write_commands.cpp index 8c0d4e0549d..e79e9ce5581 100644 --- a/src/mongo/db/commands/write_commands/write_commands.cpp +++ b/src/mongo/db/commands/write_commands/write_commands.cpp @@ -154,8 +154,9 @@ void serializeReply(OperationContext* opCtx, BSONObjBuilder errInfo(error.subobjStart("errInfo")); staleInfo->serialize(&errInfo); } - } else if (auto docValidationError = - status.extraInfo<doc_validation_error::DocumentValidationFailureInfo>()) { + } else if (ErrorCodes::DocumentValidationFailure == status.code() && status.extraInfo()) { + auto docValidationError = + status.extraInfo<doc_validation_error::DocumentValidationFailureInfo>(); error.append("code", static_cast<int>(ErrorCodes::DocumentValidationFailure)); error.append("errInfo", docValidationError->getDetails()); } else { diff --git a/src/mongo/db/matcher/doc_validation_error.cpp b/src/mongo/db/matcher/doc_validation_error.cpp index c5320f88bc5..bbc2f4eb1cb 100644 --- a/src/mongo/db/matcher/doc_validation_error.cpp +++ b/src/mongo/db/matcher/doc_validation_error.cpp @@ -974,6 +974,10 @@ bool hasErrorAnnotations(const MatchExpression& validatorExpr) { } // namespace std::shared_ptr<const ErrorExtraInfo> DocumentValidationFailureInfo::parse(const BSONObj& obj) { + if (!obj.hasField("errInfo"_sd)) { + // TODO SERVER-50524: remove this block when 5.0 becomes last-lts. + return nullptr; + } auto errInfo = obj["errInfo"]; uassert(4878100, "DocumentValidationFailureInfo must have a field 'errInfo' of type object", @@ -993,7 +997,9 @@ BSONObj generateError(const MatchExpression& validatorExpr, const BSONObj& doc) ValidationErrorInVisitor inVisitor{&context}; ValidationErrorPostVisitor postVisitor{&context}; // TODO SERVER-49446: Once all nodes have ErrorAnnotations, this check should be converted to an - // invariant check that all nodes have an annotation. + // invariant check that all nodes have an annotation. Also add an invariant to the + // DocumentValidationFailureInfo constructor to check that it is initialized with a non-empty + // object. if (!hasErrorAnnotations(validatorExpr)) { return BSONObj(); } |