diff options
author | Randolph Tan <randolph@10gen.com> | 2022-03-14 15:23:36 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-03-14 16:18:28 +0000 |
commit | 0f28913257b0d6fee3b92927d7ec16a2ad54a0a0 (patch) | |
tree | 1caedee8a8fef474b7a72cb665acaf519afb58f7 | |
parent | 1512c333827379f6ae74a4e2cceeaadbe768ba04 (diff) | |
download | mongo-0f28913257b0d6fee3b92927d7ec16a2ad54a0a0.tar.gz |
SERVER-63732 Add new implicitlyCreateIndex and enforceUniqueness to shardCollection command
-rw-r--r-- | etc/backports_required_for_multiversion_tests.yml | 4 | ||||
-rw-r--r-- | jstests/sharding/shard_collection_basic.js | 29 | ||||
-rw-r--r-- | src/mongo/db/s/config/configsvr_refine_collection_shard_key_command.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/s/create_collection_coordinator.cpp | 28 | ||||
-rw-r--r-- | src/mongo/db/s/resharding/resharding_recipient_service.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/s/shard_key_util.cpp | 14 | ||||
-rw-r--r-- | src/mongo/db/s/shard_key_util.h | 3 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_shard_collection_cmd.cpp | 2 | ||||
-rw-r--r-- | src/mongo/s/commands/shard_collection.idl | 10 | ||||
-rw-r--r-- | src/mongo/s/request_types/sharded_ddl_commands.idl | 11 |
10 files changed, 90 insertions, 13 deletions
diff --git a/etc/backports_required_for_multiversion_tests.yml b/etc/backports_required_for_multiversion_tests.yml index e180f466b91..bf463998461 100644 --- a/etc/backports_required_for_multiversion_tests.yml +++ b/etc/backports_required_for_multiversion_tests.yml @@ -154,6 +154,8 @@ last-continuous: test_file: jstests/replsets/tenant_migration_resume_collection_cloner_after_recipient_failover_with_dropped_views.js - ticket: SERVER-62759 test_file: jstests/replsets/apply_ops_dropDatabase.js + - ticket: SERVER-63732 + test_file: jstests/sharding/shard_collection_basic.js # Tests that should only be excluded from particular suites should be listed under that suite. suites: @@ -447,6 +449,8 @@ last-lts: test_file: jstests/replsets/tenant_migration_resume_collection_cloner_after_recipient_failover_with_dropped_views.js - ticket: SERVER-62759 test_file: jstests/replsets/apply_ops_dropDatabase.js + - ticket: SERVER-63732 + test_file: jstests/sharding/shard_collection_basic.js # Tests that should only be excluded from particular suites should be listed under that suite. suites: diff --git a/jstests/sharding/shard_collection_basic.js b/jstests/sharding/shard_collection_basic.js index 439f5da38fe..7fc136dbc8b 100644 --- a/jstests/sharding/shard_collection_basic.js +++ b/jstests/sharding/shard_collection_basic.js @@ -98,6 +98,12 @@ jsTestLog('Shard key can contain dotted path to embedded element.'); assert.commandWorked( mongos.adminCommand({shardCollection: kDbName + '.shard_key_dotted_path', key: {'_id.a': 1}})); +jsTestLog('Command should still verify index even if implicitlyCreateIndex is false.'); +assert.commandFailedWithCode( + mongos.adminCommand( + {shardCollection: kDbName + '.foo', key: {x: 1}, implicitlyCreateIndex: false}), + 6373200); + // // Test shardCollection's idempotency // @@ -120,6 +126,29 @@ assert.commandFailed( assert.commandWorked(mongos.getDB(kDbName).dropDatabase()); +jsTestLog('Allow non-unique index if enforceUniquenessCheck is false'); +assert.commandWorked(mongos.getDB(kDbName).foo.createIndex({x: 1})); +assert.commandWorked(mongos.adminCommand( + {shardCollection: kDbName + '.foo', key: {x: 1}, unique: true, enforceUniquenessCheck: false})); +let collDoc = mongos.getDB('config').collections.findOne({_id: `${kDbName}.foo`}); +assert(collDoc); +assert(collDoc.unique); +assert.commandWorked(mongos.getDB(kDbName).dropDatabase()); + +jsTestLog('mongosync unique key pattern use case'); +assert.commandWorked(mongos.getDB(kDbName).foo.createIndex({x: 1})); +assert.commandWorked(mongos.adminCommand({ + shardCollection: kDbName + '.foo', + key: {x: 1}, + unique: true, + implicitlyCreateIndex: false, + enforceUniquenessCheck: false +})); +collDoc = mongos.getDB('config').collections.findOne({_id: `${kDbName}.foo`}); +assert(collDoc); +assert(collDoc.unique); +assert.commandWorked(mongos.getDB(kDbName).dropDatabase()); + jsTestLog('Shard empty collections no index required.'); testAndClenaupWithKeyNoIndexOK({_id: 1}); testAndClenaupWithKeyNoIndexOK({_id: 'hashed'}); diff --git a/src/mongo/db/s/config/configsvr_refine_collection_shard_key_command.cpp b/src/mongo/db/s/config/configsvr_refine_collection_shard_key_command.cpp index a58168f06be..28bdc7869df 100644 --- a/src/mongo/db/s/config/configsvr_refine_collection_shard_key_command.cpp +++ b/src/mongo/db/s/config/configsvr_refine_collection_shard_key_command.cpp @@ -128,6 +128,7 @@ public: newShardKeyPattern, boost::none, collType.getUnique(), + true /* enforceUniquenessCheck */, shardkeyutil::ValidationBehaviorsRefineShardKey(opCtx, nss)); }); diff --git a/src/mongo/db/s/create_collection_coordinator.cpp b/src/mongo/db/s/create_collection_coordinator.cpp index 76122d24165..eaf25a98659 100644 --- a/src/mongo/db/s/create_collection_coordinator.cpp +++ b/src/mongo/db/s/create_collection_coordinator.cpp @@ -759,13 +759,27 @@ void CreateCollectionCoordinator::_createCollectionAndIndexes(OperationContext* shardkeyutil::validateShardKeyIsNotEncrypted(opCtx, nss(), *_shardKeyPattern); - const auto indexCreated = shardkeyutil::validateShardKeyIndexExistsOrCreateIfPossible( - opCtx, - nss(), - *_shardKeyPattern, - _collationBSON, - _doc.getUnique().value_or(false), - shardkeyutil::ValidationBehaviorsShardCollection(opCtx)); + auto indexCreated = false; + if (_doc.getImplicitlyCreateIndex()) { + indexCreated = shardkeyutil::validateShardKeyIndexExistsOrCreateIfPossible( + opCtx, + nss(), + *_shardKeyPattern, + _collationBSON, + _doc.getUnique().value_or(false), + _doc.getEnforceUniquenessCheck(), + shardkeyutil::ValidationBehaviorsShardCollection(opCtx)); + } else { + uassert(6373200, + "Must have an index compatible with the proposed shard key", + validShardKeyIndexExists(opCtx, + nss(), + *_shardKeyPattern, + _collationBSON, + _doc.getUnique().value_or(false) && + _doc.getEnforceUniquenessCheck(), + shardkeyutil::ValidationBehaviorsShardCollection(opCtx))); + } auto replClientInfo = repl::ReplClientInfo::forClient(opCtx->getClient()); diff --git a/src/mongo/db/s/resharding/resharding_recipient_service.cpp b/src/mongo/db/s/resharding/resharding_recipient_service.cpp index 2af2050a1f3..a6d35892ee9 100644 --- a/src/mongo/db/s/resharding/resharding_recipient_service.cpp +++ b/src/mongo/db/s/resharding/resharding_recipient_service.cpp @@ -532,6 +532,7 @@ void ReshardingRecipientService::RecipientStateMachine:: ShardKeyPattern{_metadata.getReshardingKey()}, CollationSpec::kSimpleSpec, false /* unique */, + true /* enforceUniquenessCheck */, shardkeyutil::ValidationBehaviorsShardCollection(opCtx.get())); }); } diff --git a/src/mongo/db/s/shard_key_util.cpp b/src/mongo/db/s/shard_key_util.cpp index d263712fa91..2a081555d0e 100644 --- a/src/mongo/db/s/shard_key_util.cpp +++ b/src/mongo/db/s/shard_key_util.cpp @@ -106,7 +106,7 @@ bool validShardKeyIndexExists(OperationContext* opCtx, const NamespaceString& nss, const ShardKeyPattern& shardKeyPattern, const boost::optional<BSONObj>& defaultCollation, - bool unique, + bool requiresUnique, const ShardKeyValidationBehaviors& behaviors) { auto indexes = behaviors.loadIndexes(nss); @@ -146,7 +146,7 @@ bool validShardKeyIndexExists(OperationContext* opCtx, } // 3. If proposed key is required to be unique, additionally check for exact match. - if (hasUsefulIndexForKey && unique) { + if (hasUsefulIndexForKey && requiresUnique) { BSONObj eqQuery = BSON("ns" << nss.ns() << "key" << shardKeyPattern.toBSON()); BSONObj eqQueryResult; @@ -186,13 +186,17 @@ bool validateShardKeyIndexExistsOrCreateIfPossible(OperationContext* opCtx, const ShardKeyPattern& shardKeyPattern, const boost::optional<BSONObj>& defaultCollation, bool unique, + bool enforceUniquenessCheck, const ShardKeyValidationBehaviors& behaviors) { - if (validShardKeyIndexExists( - opCtx, nss, shardKeyPattern, defaultCollation, unique, behaviors)) { + if (validShardKeyIndexExists(opCtx, + nss, + shardKeyPattern, + defaultCollation, + unique && enforceUniquenessCheck, + behaviors)) { return false; } - // 4. If no useful index, verify we can create one. behaviors.verifyCanCreateShardKeyIndex(nss); diff --git a/src/mongo/db/s/shard_key_util.h b/src/mongo/db/s/shard_key_util.h index dd5363df700..5d20a013bef 100644 --- a/src/mongo/db/s/shard_key_util.h +++ b/src/mongo/db/s/shard_key_util.h @@ -150,6 +150,7 @@ bool validateShardKeyIndexExistsOrCreateIfPossible(OperationContext* opCtx, const ShardKeyPattern& shardKeyPattern, const boost::optional<BSONObj>& defaultCollation, bool unique, + bool enforceUniquenessCheck, const ShardKeyValidationBehaviors& behaviors); /** * Compares the proposed shard key with the collection's existing indexes to ensure they are a legal @@ -163,7 +164,7 @@ bool validShardKeyIndexExists(OperationContext* opCtx, const NamespaceString& nss, const ShardKeyPattern& shardKeyPattern, const boost::optional<BSONObj>& defaultCollation, - bool unique, + bool requiresUnique, const ShardKeyValidationBehaviors& behaviors); void validateShardKeyIsNotEncrypted(OperationContext* opCtx, diff --git a/src/mongo/s/commands/cluster_shard_collection_cmd.cpp b/src/mongo/s/commands/cluster_shard_collection_cmd.cpp index 68ec95bb05c..6624a1ec2bc 100644 --- a/src/mongo/s/commands/cluster_shard_collection_cmd.cpp +++ b/src/mongo/s/commands/cluster_shard_collection_cmd.cpp @@ -102,6 +102,8 @@ public: requestParamsObj.setCollation(shardCollRequest.getCollation()); requestParamsObj.setTimeseries(shardCollRequest.getTimeseries()); requestParamsObj.setCollectionUUID(shardCollRequest.getCollectionUUID()); + requestParamsObj.setImplicitlyCreateIndex(shardCollRequest.getImplicitlyCreateIndex()); + requestParamsObj.setEnforceUniquenessCheck(shardCollRequest.getEnforceUniquenessCheck()); shardsvrCollRequest.setCreateCollectionRequest(std::move(requestParamsObj)); shardsvrCollRequest.setDbName(nss.db()); diff --git a/src/mongo/s/commands/shard_collection.idl b/src/mongo/s/commands/shard_collection.idl index 005aa90c1b9..82ea915656a 100644 --- a/src/mongo/s/commands/shard_collection.idl +++ b/src/mongo/s/commands/shard_collection.idl @@ -78,3 +78,13 @@ structs: description: "The expected UUID of the collection." type: uuid optional: true + implicitlyCreateIndex: + description: "Creates an index on the shard key pattern if the collection is empty." + type: bool + default: true + enforceUniquenessCheck: + description: >- + Controls whether this command verifies that any unique indexes are prefixed by the shard + key pattern if unique is true. If true then it will verify and if false then it won't. + type: bool + default: true diff --git a/src/mongo/s/request_types/sharded_ddl_commands.idl b/src/mongo/s/request_types/sharded_ddl_commands.idl index 9bd7602a7dc..bd20052c334 100644 --- a/src/mongo/s/request_types/sharded_ddl_commands.idl +++ b/src/mongo/s/request_types/sharded_ddl_commands.idl @@ -154,6 +154,17 @@ structs: type: uuid description: "The expected UUID of the collection." optional: true + implicitlyCreateIndex: + description: "Creates an index on the shard key pattern if the collection is empty." + type: bool + default: true + enforceUniquenessCheck: + description: >- + Controls whether this command verifies that any unique indexes are prefixed by + the shard key pattern if unique is true. If true then it will verify and if + false then it won't. + type: bool + default: true CreateCollectionResponse: description: "Response of the create collection command" |