summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/index/index_access_method.cpp3
-rw-r--r--src/mongo/db/storage/biggie/biggie_sorted_impl.cpp15
-rw-r--r--src/mongo/db/storage/biggie/biggie_sorted_impl.h5
-rw-r--r--src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.cpp30
-rw-r--r--src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.h1
-rw-r--r--src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl_test.cpp4
-rw-r--r--src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.cpp1
-rw-r--r--src/mongo/db/storage/index_entry_comparison.cpp53
-rw-r--r--src/mongo/db/storage/index_entry_comparison.h4
-rw-r--r--src/mongo/db/storage/index_entry_comparison_test.cpp58
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp26
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_index.h1
12 files changed, 167 insertions, 34 deletions
diff --git a/src/mongo/db/index/index_access_method.cpp b/src/mongo/db/index/index_access_method.cpp
index 49b69bc92d6..938e0261a86 100644
--- a/src/mongo/db/index/index_access_method.cpp
+++ b/src/mongo/db/index/index_access_method.cpp
@@ -653,7 +653,8 @@ Status AbstractIndexAccessMethod::commitBulk(OperationContext* opCtx,
return buildDupKeyErrorStatus(dupKey.getOwned(),
_descriptor->parentNS(),
_descriptor->indexName(),
- _descriptor->keyPattern());
+ _descriptor->keyPattern(),
+ _descriptor->collation());
}
}
diff --git a/src/mongo/db/storage/biggie/biggie_sorted_impl.cpp b/src/mongo/db/storage/biggie/biggie_sorted_impl.cpp
index 68bcb271f96..666bed4ea80 100644
--- a/src/mongo/db/storage/biggie/biggie_sorted_impl.cpp
+++ b/src/mongo/db/storage/biggie/biggie_sorted_impl.cpp
@@ -195,7 +195,8 @@ SortedDataBuilderInterface::SortedDataBuilderInterface(OperationContext* opCtx,
const std::string& identEnd,
const NamespaceString& collectionNamespace,
const std::string& indexName,
- const BSONObj& keyPattern)
+ const BSONObj& keyPattern,
+ const BSONObj& collation)
: _opCtx(opCtx),
_unique(unique),
_dupsAllowed(dupsAllowed),
@@ -205,6 +206,7 @@ SortedDataBuilderInterface::SortedDataBuilderInterface(OperationContext* opCtx,
_collectionNamespace(collectionNamespace),
_indexName(indexName),
_keyPattern(keyPattern),
+ _collation(collation),
_hasLast(false),
_lastKeyToString(""),
_lastRID(-1) {}
@@ -242,7 +244,8 @@ Status SortedDataBuilderInterface::addKey(const KeyString::Value& keyString) {
if (twoKeyCmp == 0 && twoRIDCmp != 0) {
if (!_dupsAllowed) {
auto key = KeyString::toBson(keyString, _order);
- return buildDupKeyErrorStatus(key, _collectionNamespace, _indexName, _keyPattern);
+ return buildDupKeyErrorStatus(
+ key, _collectionNamespace, _indexName, _keyPattern, _collation);
}
// Duplicate index entries are allowed on this unique index, so we put the RecordId in the
// KeyString until the unique constraint is resolved.
@@ -279,7 +282,8 @@ SortedDataBuilderInterface* SortedDataInterface::getBulkBuilder(OperationContext
_identEnd,
_collectionNamespace,
_indexName,
- _keyPattern);
+ _keyPattern,
+ _collation);
}
// We append \1 to all idents we get, and therefore the KeyString with ident + \0 will only be
@@ -296,6 +300,7 @@ SortedDataInterface::SortedDataInterface(OperationContext* opCtx,
_collectionNamespace(desc->getCollection()->ns()),
_indexName(desc->indexName()),
_keyPattern(desc->keyPattern()),
+ _collation(desc->collation()),
_isUnique(desc->unique()),
_isPartial(desc->isPartial()) {
// This is the string representation of the KeyString before elements in this ident, which is
@@ -355,7 +360,7 @@ Status SortedDataInterface::insert(OperationContext* opCtx,
// dups were not allowed.
auto key = KeyString::toBson(keyString, _ordering);
return buildDupKeyErrorStatus(
- key, _collectionNamespace, _indexName, _keyPattern);
+ key, _collectionNamespace, _indexName, _keyPattern, _collation);
}
} else {
return Status::OK();
@@ -492,7 +497,7 @@ Status SortedDataInterface::dupKeyCheck(OperationContext* opCtx, const KeyString
next->keyString.getSize()),
key.getSize()) == 0) {
return buildDupKeyErrorStatus(
- key, _collectionNamespace, _indexName, _keyPattern, _ordering);
+ key, _collectionNamespace, _indexName, _keyPattern, _collation, _ordering);
}
return Status::OK();
diff --git a/src/mongo/db/storage/biggie/biggie_sorted_impl.h b/src/mongo/db/storage/biggie/biggie_sorted_impl.h
index 559789df44e..96f0229197c 100644
--- a/src/mongo/db/storage/biggie/biggie_sorted_impl.h
+++ b/src/mongo/db/storage/biggie/biggie_sorted_impl.h
@@ -46,7 +46,8 @@ public:
const std::string& identEnd,
const NamespaceString& collectionNamespace,
const std::string& indexName,
- const BSONObj& keyPattern);
+ const BSONObj& keyPattern,
+ const BSONObj& collation);
void commit(bool mayInterrupt) override;
virtual Status addKey(const KeyString::Value& keyString);
@@ -63,6 +64,7 @@ private:
const NamespaceString _collectionNamespace;
const std::string _indexName;
const BSONObj _keyPattern;
+ const BSONObj _collation;
// Whether or not we've already added something before.
bool _hasLast;
// This is the KeyString of the last key added.
@@ -195,6 +197,7 @@ private:
const NamespaceString _collectionNamespace;
const std::string _indexName;
const BSONObj _keyPattern;
+ const BSONObj _collation;
// These are the keystring representations of the _prefix and the _identEnd.
std::string _KSForIdentStart;
std::string _KSForIdentEnd;
diff --git a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.cpp b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.cpp
index 8eb549629e2..f3160e96033 100644
--- a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.cpp
+++ b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.cpp
@@ -75,7 +75,8 @@ public:
bool dupsAllowed,
const NamespaceString& collectionNamespace,
const std::string& indexName,
- const BSONObj& keyPattern)
+ const BSONObj& keyPattern,
+ const BSONObj& collation)
: _data(data),
_currentKeySize(currentKeySize),
_ordering(ordering),
@@ -83,7 +84,8 @@ public:
_comparator(_data->key_comp()),
_collectionNamespace(collectionNamespace),
_indexName(indexName),
- _keyPattern(keyPattern) {
+ _keyPattern(keyPattern),
+ _collation(collation) {
invariant(_data->empty());
}
@@ -100,7 +102,8 @@ public:
return Status(ErrorCodes::InternalError,
"expected ascending (key, RecordId) order in bulk builder");
} else if (!_dupsAllowed && cmp == 0 && loc != _last->loc) {
- return buildDupKeyErrorStatus(key, _collectionNamespace, _indexName, _keyPattern);
+ return buildDupKeyErrorStatus(
+ key, _collectionNamespace, _indexName, _keyPattern, _collation);
}
}
@@ -133,6 +136,7 @@ private:
const NamespaceString _collectionNamespace;
const std::string _indexName;
const BSONObj _keyPattern;
+ const BSONObj _collation;
};
class EphemeralForTestBtreeImpl : public SortedDataInterface {
@@ -142,13 +146,15 @@ public:
bool isUnique,
const NamespaceString& collectionNamespace,
const std::string& indexName,
- const BSONObj& keyPattern)
+ const BSONObj& keyPattern,
+ const BSONObj& collation)
: SortedDataInterface(KeyString::Version::kLatestVersion, ordering),
_data(data),
_isUnique(isUnique),
_collectionNamespace(collectionNamespace),
_indexName(indexName),
- _keyPattern(keyPattern) {
+ _keyPattern(keyPattern),
+ _collation(collation) {
_currentKeySize = 0;
}
@@ -159,7 +165,8 @@ public:
dupsAllowed,
_collectionNamespace,
_indexName,
- _keyPattern);
+ _keyPattern,
+ _collation);
}
virtual Status insert(OperationContext* opCtx,
@@ -172,7 +179,8 @@ public:
// TODO optimization: save the iterator from the dup-check to speed up insert
if (!dupsAllowed && keyExists(*_data, key))
- return buildDupKeyErrorStatus(key, _collectionNamespace, _indexName, _keyPattern);
+ return buildDupKeyErrorStatus(
+ key, _collectionNamespace, _indexName, _keyPattern, _collation);
IndexKeyEntry entry(key.getOwned(), loc);
if (_data->insert(entry).second) {
@@ -240,7 +248,8 @@ public:
Status _dupKeyCheck(OperationContext* opCtx, const BSONObj& key) {
invariant(!key.hasFieldNames());
if (isDup(*_data, key))
- return buildDupKeyErrorStatus(key, _collectionNamespace, _indexName, _keyPattern);
+ return buildDupKeyErrorStatus(
+ key, _collectionNamespace, _indexName, _keyPattern, _collation);
return Status::OK();
}
@@ -618,6 +627,7 @@ private:
const NamespaceString _collectionNamespace;
const std::string _indexName;
const BSONObj _keyPattern;
+ const BSONObj _collation;
};
} // namespace
@@ -629,6 +639,7 @@ std::unique_ptr<SortedDataInterface> getEphemeralForTestBtreeImpl(
const NamespaceString& collectionNamespace,
const std::string& indexName,
const BSONObj& keyPattern,
+ const BSONObj& collation,
std::shared_ptr<void>* dataInOut) {
invariant(dataInOut);
if (!*dataInOut) {
@@ -639,7 +650,8 @@ std::unique_ptr<SortedDataInterface> getEphemeralForTestBtreeImpl(
isUnique,
collectionNamespace,
indexName,
- keyPattern);
+ keyPattern,
+ collation);
}
} // namespace mongo
diff --git a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.h b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.h
index 60431c1cfa7..fe570288cec 100644
--- a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.h
+++ b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl.h
@@ -46,6 +46,7 @@ std::unique_ptr<SortedDataInterface> getEphemeralForTestBtreeImpl(
const NamespaceString& collectionNamespace,
const std::string& indexName,
const BSONObj& keyPattern,
+ const BSONObj& collation,
std::shared_ptr<void>* dataInOut);
} // namespace mongo
diff --git a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl_test.cpp b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl_test.cpp
index bcd0a0ebc32..32895759022 100644
--- a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl_test.cpp
+++ b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_btree_impl_test.cpp
@@ -57,6 +57,7 @@ public:
NamespaceString("test.EphemeralForTest"),
"indexName",
spec,
+ BSONObj{},
&_data));
}
@@ -66,7 +67,8 @@ public:
unique,
NamespaceString("test.EphemeralForTest"),
"indexName",
- BSONObj(),
+ BSONObj{},
+ BSONObj{},
&_data));
}
diff --git a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.cpp b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.cpp
index 7e0974a8e4f..490635f37f1 100644
--- a/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.cpp
+++ b/src/mongo/db/storage/ephemeral_for_test/ephemeral_for_test_engine.cpp
@@ -106,6 +106,7 @@ std::unique_ptr<SortedDataInterface> EphemeralForTestEngine::getSortedDataInterf
desc->parentNS(),
desc->indexName(),
desc->keyPattern(),
+ desc->collation(),
&_dataMap[ident]);
}
diff --git a/src/mongo/db/storage/index_entry_comparison.cpp b/src/mongo/db/storage/index_entry_comparison.cpp
index fb817e93a0f..86e0e502290 100644
--- a/src/mongo/db/storage/index_entry_comparison.cpp
+++ b/src/mongo/db/storage/index_entry_comparison.cpp
@@ -36,6 +36,8 @@
#include "mongo/db/namespace_string.h"
#include "mongo/db/storage/duplicate_key_error_info.h"
#include "mongo/db/storage/key_string.h"
+#include "mongo/util/hex.h"
+#include "mongo/util/text.h"
namespace mongo {
@@ -177,14 +179,29 @@ KeyString::Value IndexEntryComparison::makeKeyStringFromBSONKeyForSeek(const BSO
Status buildDupKeyErrorStatus(const BSONObj& key,
const NamespaceString& collectionNamespace,
const std::string& indexName,
- const BSONObj& keyPattern) {
+ const BSONObj& keyPattern,
+ const BSONObj& indexCollation) {
+ const bool hasCollation = !indexCollation.isEmpty();
+
StringBuilder sb;
sb << "E11000 duplicate key error";
sb << " collection: " << collectionNamespace;
sb << " index: " << indexName;
+ if (hasCollation) {
+ sb << " collation: " << indexCollation;
+ }
sb << " dup key: ";
- BSONObjBuilder builder;
+ // For the purpose of producing a useful error message, generate a representation of the key
+ // with field names hydrated and with invalid UTF-8 hex-encoded.
+ BSONObjBuilder builderForErrmsg;
+
+ // Used to build a version of the key after hydrating with field names but without hex encoding
+ // invalid UTF-8. This key is attached to the extra error info and consumed by callers who may
+ // wish to retry on duplicate key errors. The field names are rehydrated so that we don't return
+ // BSON with duplicate key names to clients.
+ BSONObjBuilder builderForErrorExtraInfo;
+
// key is a document with forms like: '{ : 123}', '{ : {num: 123} }', '{ : 123, : "str" }'
BSONObjIterator keyValueIt(key);
// keyPattern is a document with only one level. e.g. '{a : 1, b : -1}', '{a.b : 1}'
@@ -197,23 +214,45 @@ Status buildDupKeyErrorStatus(const BSONObj& key,
if (keyNameElem.eoo())
break;
- builder.appendAs(keyValueElem, keyNameElem.fieldName());
+ builderForErrorExtraInfo.appendAs(keyValueElem, keyNameElem.fieldName());
+
+ // If the duplicate key value contains a string, then it's possible that the string contains
+ // binary data which is not valid UTF-8. This is true for all indexes with a collation,
+ // since the index stores collation keys rather than raw user strings. But it's also
+ // possible that the application has stored binary data inside a string, which the system
+ // has never rejected.
+ //
+ // If the string in the key is invalid UTF-8, then we hex encode it before adding it to the
+ // error message so that the driver can assume valid UTF-8 when reading the reply.
+ const bool shouldHexEncode = keyValueElem.type() == BSONType::String &&
+ (hasCollation || !isValidUTF8(keyValueElem.valueStringData()));
+
+ if (shouldHexEncode) {
+ auto stringToEncode = keyValueElem.valueStringData();
+ builderForErrmsg.append(
+ keyNameElem.fieldName(),
+ str::stream() << "0x"
+ << toHexLower(stringToEncode.rawData(), stringToEncode.size()));
+ } else {
+ builderForErrmsg.appendAs(keyValueElem, keyNameElem.fieldName());
+ }
}
- auto keyValueWithName = builder.obj();
- sb << keyValueWithName;
- return Status(DuplicateKeyErrorInfo(keyPattern, keyValueWithName), sb.str());
+ sb << builderForErrmsg.obj();
+
+ return Status(DuplicateKeyErrorInfo(keyPattern, builderForErrorExtraInfo.obj()), sb.str());
}
Status buildDupKeyErrorStatus(const KeyString::Value& keyString,
const NamespaceString& collectionNamespace,
const std::string& indexName,
const BSONObj& keyPattern,
+ const BSONObj& indexCollation,
const Ordering& ordering) {
const BSONObj key = KeyString::toBson(
keyString.getBuffer(), keyString.getSize(), ordering, keyString.getTypeBits());
- return buildDupKeyErrorStatus(key, collectionNamespace, indexName, keyPattern);
+ return buildDupKeyErrorStatus(key, collectionNamespace, indexName, keyPattern, indexCollation);
}
} // namespace mongo
diff --git a/src/mongo/db/storage/index_entry_comparison.h b/src/mongo/db/storage/index_entry_comparison.h
index 802e5d4e489..ad4bbbc8aa6 100644
--- a/src/mongo/db/storage/index_entry_comparison.h
+++ b/src/mongo/db/storage/index_entry_comparison.h
@@ -258,7 +258,8 @@ private:
Status buildDupKeyErrorStatus(const BSONObj& key,
const NamespaceString& collectionNamespace,
const std::string& indexName,
- const BSONObj& keyPattern);
+ const BSONObj& keyPattern,
+ const BSONObj& indexCollation);
/**
* Returns the formatted error status about the duplicate KeyString.
@@ -267,6 +268,7 @@ Status buildDupKeyErrorStatus(const KeyString::Value& keyString,
const NamespaceString& collectionNamespace,
const std::string& indexName,
const BSONObj& keyPattern,
+ const BSONObj& indexCollation,
const Ordering& ordering);
} // namespace mongo
diff --git a/src/mongo/db/storage/index_entry_comparison_test.cpp b/src/mongo/db/storage/index_entry_comparison_test.cpp
index 0cfd6b830fc..5ef646b36e0 100644
--- a/src/mongo/db/storage/index_entry_comparison_test.cpp
+++ b/src/mongo/db/storage/index_entry_comparison_test.cpp
@@ -32,6 +32,7 @@
#include "mongo/db/storage/duplicate_key_error_info.h"
#include "mongo/db/storage/index_entry_comparison.h"
#include "mongo/unittest/unittest.h"
+#include "mongo/util/hex.h"
namespace mongo {
@@ -42,7 +43,7 @@ TEST(IndexEntryComparison, BuildDupKeyErrorStatusProducesExpectedErrorObject) {
auto keyValue = BSON("" << 10 << ""
<< "abc");
- auto dupKeyStatus = buildDupKeyErrorStatus(keyValue, collNss, indexName, keyPattern);
+ auto dupKeyStatus = buildDupKeyErrorStatus(keyValue, collNss, indexName, keyPattern, BSONObj{});
ASSERT_NOT_OK(dupKeyStatus);
ASSERT_EQUALS(dupKeyStatus.code(), ErrorCodes::DuplicateKey);
@@ -61,4 +62,59 @@ TEST(IndexEntryComparison, BuildDupKeyErrorStatusProducesExpectedErrorObject) {
BSON("keyPattern" << keyPattern << "keyValue" << keyValueWithFieldName));
}
+TEST(IndexEntryComparison, BuildDupKeyErrorMessageIncludesCollationAndHexEncodedCollationKey) {
+ StringData mockCollationKey("bar");
+
+ NamespaceString collNss("test.foo");
+ std::string indexName("a_1");
+ auto keyPattern = BSON("a" << 1);
+ auto keyValue = BSON("" << mockCollationKey);
+ auto collation = BSON("locale"
+ << "en_US");
+
+ auto dupKeyStatus = buildDupKeyErrorStatus(keyValue, collNss, indexName, keyPattern, collation);
+ ASSERT_NOT_OK(dupKeyStatus);
+ ASSERT_EQUALS(dupKeyStatus.code(), ErrorCodes::DuplicateKey);
+
+ ASSERT(dupKeyStatus.reason().find("collation:") != std::string::npos);
+
+ // Verify that the collation key is hex encoded in the error message.
+ std::string expectedHexEncoding =
+ "0x" + toHexLower(mockCollationKey.rawData(), mockCollationKey.size());
+ ASSERT(dupKeyStatus.reason().find(expectedHexEncoding) != std::string::npos);
+
+ // But no hex encoding should have taken place inside the key attached to the extra error info.
+ auto extraInfo = dupKeyStatus.extraInfo<DuplicateKeyErrorInfo>();
+ ASSERT(extraInfo);
+ ASSERT_BSONOBJ_EQ(extraInfo->getKeyPattern(), keyPattern);
+ ASSERT_BSONOBJ_EQ(extraInfo->getDuplicatedKeyValue(), BSON("a" << mockCollationKey));
+}
+
+TEST(IndexEntryComparison, BuildDupKeyErrorMessageHexEncodesInvalidUTF8ForIndexWithoutCollation) {
+ NamespaceString collNss("test.foo");
+ std::string indexName("a_1");
+ auto keyPattern = BSON("a" << 1);
+
+ // The byte sequence c0 16 is invalid UTF-8 since this is an overlong encoding of the letter
+ // "a", which should be represented as simply 0x16. The byte 0xc0 is always illegal in UTF-8
+ // since it would only ever be used for an overload two-byte encoding of an ASCII character.
+ auto keyValue = BSON(""
+ << "\xc0\x16");
+ auto dupKeyStatus = buildDupKeyErrorStatus(keyValue, collNss, indexName, keyPattern, BSONObj{});
+ ASSERT_NOT_OK(dupKeyStatus);
+ ASSERT_EQUALS(dupKeyStatus.code(), ErrorCodes::DuplicateKey);
+
+ // We expect to find a hex-encoded version of the illegal UTF-8 byte sequence inside the error
+ // string.
+ ASSERT(dupKeyStatus.reason().find("0xc016") != std::string::npos);
+
+ // In the extra error info, we expect that no hex encoding has taken place.
+ auto extraInfo = dupKeyStatus.extraInfo<DuplicateKeyErrorInfo>();
+ ASSERT(extraInfo);
+ ASSERT_BSONOBJ_EQ(extraInfo->getKeyPattern(), keyPattern);
+ ASSERT_BSONOBJ_EQ(extraInfo->getDuplicatedKeyValue(),
+ BSON("a"
+ << "\xc0\x16"));
+}
+
} // namespace mongo
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp
index 137fb2cb52d..6339021a1b5 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp
@@ -245,6 +245,7 @@ WiredTigerIndex::WiredTigerIndex(OperationContext* ctx,
_collectionNamespace(desc->parentNS()),
_indexName(desc->indexName()),
_keyPattern(desc->keyPattern()),
+ _collation(desc->collation()),
_prefix(prefix),
_isIdIndex(desc->isIdIndex()) {}
@@ -380,7 +381,7 @@ Status WiredTigerIndex::dupKeyCheck(OperationContext* opCtx, const KeyString::Va
if (isDup(opCtx, c, key))
return buildDupKeyErrorStatus(
- key, _collectionNamespace, _indexName, _keyPattern, _ordering);
+ key, _collectionNamespace, _indexName, _keyPattern, _collation, _ordering);
return Status::OK();
}
@@ -699,8 +700,11 @@ private:
if (cmp == 0) {
// Duplicate found!
auto newKey = KeyString::toBson(newKeyString, _idx->_ordering);
- return buildDupKeyErrorStatus(
- newKey, _idx->collectionNamespace(), _idx->indexName(), _idx->keyPattern());
+ return buildDupKeyErrorStatus(newKey,
+ _idx->collectionNamespace(),
+ _idx->indexName(),
+ _idx->keyPattern(),
+ _idx->_collation);
} else {
/*
* _previousKeyString.isEmpty() is only true on the first call to addKey().
@@ -744,8 +748,11 @@ private:
// Dup found!
if (!_dupsAllowed) {
auto newKey = KeyString::toBson(newKeyString, _idx->_ordering);
- return buildDupKeyErrorStatus(
- newKey, _idx->collectionNamespace(), _idx->indexName(), _idx->keyPattern());
+ return buildDupKeyErrorStatus(newKey,
+ _idx->collectionNamespace(),
+ _idx->indexName(),
+ _idx->keyPattern(),
+ _idx->_collation);
}
// If we get here, we are in the weird mode where dups are allowed on a unique
@@ -1526,7 +1533,8 @@ Status WiredTigerIndexUnique::_insertTimestampUnsafe(OperationContext* opCtx,
if (!dupsAllowed) {
auto key = KeyString::toBson(keyString, _ordering);
- return buildDupKeyErrorStatus(key, _collectionNamespace, _indexName, _keyPattern);
+ return buildDupKeyErrorStatus(
+ key, _collectionNamespace, _indexName, _keyPattern, _collation);
}
if (!insertedId) {
@@ -1572,7 +1580,8 @@ Status WiredTigerIndexUnique::_insertTimestampSafe(OperationContext* opCtx,
if (ret == WT_DUPLICATE_KEY) {
auto key = KeyString::toBson(
keyString.getBuffer(), sizeWithoutRecordId, _ordering, keyString.getTypeBits());
- return buildDupKeyErrorStatus(key, _collectionNamespace, _indexName, _keyPattern);
+ return buildDupKeyErrorStatus(
+ key, _collectionNamespace, _indexName, _keyPattern, _collation);
}
invariantWTOK(ret);
@@ -1587,7 +1596,8 @@ Status WiredTigerIndexUnique::_insertTimestampSafe(OperationContext* opCtx,
if (_keyExists(opCtx, c, keyString.getBuffer(), sizeWithoutRecordId)) {
auto key = KeyString::toBson(
keyString.getBuffer(), sizeWithoutRecordId, _ordering, keyString.getTypeBits());
- return buildDupKeyErrorStatus(key, _collectionNamespace, _indexName, _keyPattern);
+ return buildDupKeyErrorStatus(
+ key, _collectionNamespace, _indexName, _keyPattern, _collation);
}
}
diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_index.h b/src/mongo/db/storage/wiredtiger/wiredtiger_index.h
index 5fefad39b92..dddf3dc054c 100644
--- a/src/mongo/db/storage/wiredtiger/wiredtiger_index.h
+++ b/src/mongo/db/storage/wiredtiger/wiredtiger_index.h
@@ -183,6 +183,7 @@ protected:
const NamespaceString _collectionNamespace;
const std::string _indexName;
const BSONObj _keyPattern;
+ const BSONObj _collation;
KVPrefix _prefix;
bool _isIdIndex;
};