summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHana Pearlman <hana.pearlman@mongodb.com>2021-11-22 13:20:41 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-11-22 13:45:50 +0000
commit08ed50a5e31392a9bf90c5d450941ff9c281740b (patch)
treed37dc47d572c8de21d2f3937328bbc081a311a5f /src
parent7a9101652b4de3b4ef4f57c84e68d09eae793413 (diff)
downloadmongo-08ed50a5e31392a9bf90c5d450941ff9c281740b.tar.gz
SERVER-59132: Improve error message for $merge with whenMatched: fail
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/pipeline/SConscript1
-rw-r--r--src/mongo/db/pipeline/document_source_merge.cpp18
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() {