diff options
author | Hana Pearlman <hana.pearlman@mongodb.com> | 2021-11-22 13:20:41 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-11-22 13:45:50 +0000 |
commit | 08ed50a5e31392a9bf90c5d450941ff9c281740b (patch) | |
tree | d37dc47d572c8de21d2f3937328bbc081a311a5f /src | |
parent | 7a9101652b4de3b4ef4f57c84e68d09eae793413 (diff) | |
download | mongo-08ed50a5e31392a9bf90c5d450941ff9c281740b.tar.gz |
SERVER-59132: Improve error message for $merge with whenMatched: fail
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/pipeline/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_merge.cpp | 18 |
2 files changed, 19 insertions, 0 deletions
diff --git a/src/mongo/db/pipeline/SConscript b/src/mongo/db/pipeline/SConscript index 3533037cd73..a5899fe73d4 100644 --- a/src/mongo/db/pipeline/SConscript +++ b/src/mongo/db/pipeline/SConscript @@ -353,6 +353,7 @@ pipelineEnv.Library( '$BUILD_DIR/mongo/db/sessions_collection', '$BUILD_DIR/mongo/db/stats/resource_consumption_metrics', '$BUILD_DIR/mongo/db/storage/encryption_hooks', + '$BUILD_DIR/mongo/db/storage/index_entry_comparison', '$BUILD_DIR/mongo/db/storage/storage_options', '$BUILD_DIR/mongo/db/update/update_document_diff', '$BUILD_DIR/mongo/db/views/resolved_view', diff --git a/src/mongo/db/pipeline/document_source_merge.cpp b/src/mongo/db/pipeline/document_source_merge.cpp index 7fc546d864d..0715ac8e65a 100644 --- a/src/mongo/db/pipeline/document_source_merge.cpp +++ b/src/mongo/db/pipeline/document_source_merge.cpp @@ -41,6 +41,7 @@ #include "mongo/db/ops/write_ops.h" #include "mongo/db/pipeline/document_path_support.h" #include "mongo/db/pipeline/variable_validation.h" +#include "mongo/db/storage/duplicate_key_error_info.h" #include "mongo/logv2/log.h" namespace mongo { @@ -557,6 +558,23 @@ void DocumentSourceMerge::spill(BatchedObjects&& batch) try { uassertStatusOKWithContext(ex.toStatus(), "$merge failed to update the matching document, did you " "attempt to modify the _id or the shard key?"); +} catch (const ExceptionFor<ErrorCodes::DuplicateKey>& ex) { + // A DuplicateKey error could be due to a collision on the 'on' fields or on any other unique + // index. + auto dupKeyPattern = ex->getKeyPattern(); + bool dupKeyFromMatchingOnFields = + (static_cast<size_t>(dupKeyPattern.nFields()) == _mergeOnFields.size()) && + std::all_of(_mergeOnFields.begin(), _mergeOnFields.end(), [&](auto onField) { + return dupKeyPattern.hasField(onField.fullPath()); + }); + + if (_descriptor.mode == kFailInsertMode && dupKeyFromMatchingOnFields) { + uassertStatusOKWithContext(ex.toStatus(), + "$merge with whenMatched: fail found an existing document with " + "the same values for the 'on' fields"); + } else { + uassertStatusOKWithContext(ex.toStatus(), "$merge failed due to a DuplicateKey error"); + } } void DocumentSourceMerge::waitWhileFailPointEnabled() { |