summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuhong Zhang <yuhong.zhang@mongodb.com>2022-09-19 19:50:44 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-10-21 19:42:42 +0000
commit806ff5306840425bbe6cf8d06bc343d1294a3fb7 (patch)
treef25944fce8a5dd95481ffeaab4830b8f0eb5b265
parent220b590ded50f6a07e7df010fd5f412fa57dfceb (diff)
downloadmongo-806ff5306840425bbe6cf8d06bc343d1294a3fb7.tar.gz
SERVER-69429 Check shard key compatibility during collMod convert to unique
(cherry picked from commit 12165e687bc06fbf5df03bfef5d570e9dae7b0e9)
-rw-r--r--jstests/noPassthrough/sharding_index_uniqueness.js16
-rw-r--r--src/mongo/db/catalog/coll_mod.cpp21
2 files changed, 36 insertions, 1 deletions
diff --git a/jstests/noPassthrough/sharding_index_uniqueness.js b/jstests/noPassthrough/sharding_index_uniqueness.js
index 23cfcbd9a98..b719c656581 100644
--- a/jstests/noPassthrough/sharding_index_uniqueness.js
+++ b/jstests/noPassthrough/sharding_index_uniqueness.js
@@ -5,6 +5,8 @@
*
* @tags: [
* requires_sharding,
+ * # TODO(SERVER-61182): Fix WiredTigerKVEngine::alterIdentMetadata() under inMemory.
+ * requires_persistence,
* ]
*/
@@ -45,5 +47,19 @@ assert.commandFailedWithCode(coll.createIndex({a: 1}, {unique: 1}), ErrorCodes.C
assert.commandWorked(coll.createIndex({b: 1, a: 1}, {prepareUnique: 1}));
assert.commandWorked(coll.createIndex({b: 1, c: 1}, {unique: 1}));
+// Cannot convert an index to prepareUnique with a conflicting shard key.
+coll = db[collNamePrefix + count++];
+assert.commandWorked(st.s.adminCommand({shardCollection: coll.getFullName(), key: {b: 1}}));
+assert.commandWorked(coll.createIndex({a: 1}));
+assert.commandFailedWithCode(
+ db.runCommand({collMod: coll.getName(), index: {keyPattern: {a: 1}, prepareUnique: true}}),
+ ErrorCodes.InvalidOptions);
+// Can convert an index to prepareUnique and unique with a compatible shard key.
+assert.commandWorked(coll.createIndex({b: 1, d: 1}));
+assert.commandWorked(db.runCommand(
+ {collMod: coll.getName(), index: {keyPattern: {b: 1, d: 1}, prepareUnique: true}}));
+assert.commandWorked(
+ db.runCommand({collMod: coll.getName(), index: {keyPattern: {b: 1, d: 1}, unique: true}}));
+
st.stop();
})();
diff --git a/src/mongo/db/catalog/coll_mod.cpp b/src/mongo/db/catalog/coll_mod.cpp
index 9fc32c239cd..cedf7a39cef 100644
--- a/src/mongo/db/catalog/coll_mod.cpp
+++ b/src/mongo/db/catalog/coll_mod.cpp
@@ -62,6 +62,7 @@
#include "mongo/db/views/view_catalog_helpers.h"
#include "mongo/idl/command_generic_argument.h"
#include "mongo/logv2/log.h"
+#include "mongo/s/grid.h"
#include "mongo/util/fail_point.h"
#include "mongo/util/version/releases.h"
#include "mongo/util/visit_helper.h"
@@ -338,7 +339,7 @@ StatusWith<std::pair<ParsedCollModRequest, BSONObj>> parseCollModRequest(Operati
if (cmrIndex->idx->unique()) {
indexForOplog->setUnique(boost::none);
} else {
- // Disallow one-step unique convertion. The user has to set
+ // Disallow one-step unique conversion. The user has to set
// 'prepareUnique' to true first.
if (!cmrIndex->idx->prepareUnique()) {
return Status(ErrorCodes::InvalidOptions,
@@ -379,6 +380,24 @@ StatusWith<std::pair<ParsedCollModRequest, BSONObj>> parseCollModRequest(Operati
cmrIndex->idx->unique()) {
indexForOplog->setPrepareUnique(boost::none);
} else {
+ // Checks if the index key pattern conflicts with the shard key pattern.
+ if (auto catalogClient = Grid::get(opCtx)->catalogClient()) {
+ try {
+ auto shardedColl = catalogClient->getCollection(opCtx, nss);
+ const ShardKeyPattern shardKeyPattern(shardedColl.getKeyPattern());
+ if (!shardKeyPattern.isIndexUniquenessCompatible(
+ cmrIndex->idx->keyPattern())) {
+ return {ErrorCodes::InvalidOptions,
+ fmt::format(
+ "cannot set 'prepareUnique' for index {} with shard key "
+ "pattern {}",
+ cmrIndex->idx->keyPattern().toString(),
+ shardKeyPattern.toBSON().toString())};
+ }
+ } catch (ExceptionFor<ErrorCodes::NamespaceNotFound>&) {
+ // The collection is unsharded or doesn't exist.
+ }
+ }
cmrIndex->indexPrepareUnique = cmdIndex.getPrepareUnique();
}
}