diff options
author | Gregory Noma <gregory.noma@gmail.com> | 2022-02-11 14:54:48 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-02-11 15:32:28 +0000 |
commit | 037b22172c54d5652298203077c16cc0ee7f26a1 (patch) | |
tree | cd6628d5497f93bd74d617b79652593c5e1ca5e8 | |
parent | 2d92ff7fe9a774746e5e34023256b71a5a95a722 (diff) | |
download | mongo-037b22172c54d5652298203077c16cc0ee7f26a1.tar.gz |
SERVER-62861 Use `null` instead of empty string for `actualNamespace` in `CollectionUUIDMismatch` error response
17 files changed, 46 insertions, 39 deletions
diff --git a/jstests/aggregation/aggregation_with_uuids.js b/jstests/aggregation/aggregation_with_uuids.js index dbf7833d93f..52bcc99545f 100644 --- a/jstests/aggregation/aggregation_with_uuids.js +++ b/jstests/aggregation/aggregation_with_uuids.js @@ -79,7 +79,7 @@ res = assert.commandFailedWithCode( testDB.runCommand( {aggregate: collName, collectionUUID: uuid, pipeline: [{$match: {}}], cursor: {}}), ErrorCodes.CollectionUUIDMismatch); -validateErrorResponse(res, uuid, testColl.getFullName(), ""); +validateErrorResponse(res, uuid, testColl.getFullName(), null); // Now recreate the collection. assert.commandWorked(testColl.insert(docs)); @@ -89,7 +89,7 @@ res = assert.commandFailedWithCode( testDB.runCommand( {aggregate: collName, collectionUUID: uuid, pipeline: [{$match: {}}], cursor: {}}), ErrorCodes.CollectionUUIDMismatch); -validateErrorResponse(res, uuid, testColl.getFullName(), ""); +validateErrorResponse(res, uuid, testColl.getFullName(), null); collNameRes = assert.commandWorked( testDB.runCommand({aggregate: collName, pipeline: [{$match: {}}], cursor: {}})); @@ -106,7 +106,7 @@ res = assert.commandFailedWithCode( testDB.runCommand( {aggregate: "viewCollection", collectionUUID: uuid, pipeline: [{$match: {}}], cursor: {}}), ErrorCodes.CollectionUUIDMismatch); -validateErrorResponse(res, uuid, testDB.getName() + '.viewCollection', ""); +validateErrorResponse(res, uuid, testDB.getName() + '.viewCollection', null); // // Tests for rejecting invalid collectionUUIDs and cases where collectionUUID is not allowed. diff --git a/jstests/aggregation/collection_uuid_coll_stats_index_stats.js b/jstests/aggregation/collection_uuid_coll_stats_index_stats.js index 313fdc34cd2..3ad76a86a5b 100644 --- a/jstests/aggregation/collection_uuid_coll_stats_index_stats.js +++ b/jstests/aggregation/collection_uuid_coll_stats_index_stats.js @@ -5,8 +5,9 @@ (function() { 'use strict'; -const validateErrorResponse = function(res, collectionUUID, actualNamespace) { +const validateErrorResponse = function(res, collectionUUID, expectedNamespace, actualNamespace) { assert.eq(res.collectionUUID, collectionUUID); + assert.eq(res.expectedNamespace, expectedNamespace); assert.eq(res.actualNamespace, actualNamespace); }; @@ -31,7 +32,7 @@ const testCommand = function(cmd, cmdObj) { cmdObj["collectionUUID"] = nonexistentUUID; let res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, nonexistentUUID, ""); + validateErrorResponse(res, nonexistentUUID, coll.getFullName(), null); jsTestLog("The command '" + cmd + "' fails when the provided UUID corresponds to a different collection."); @@ -41,7 +42,7 @@ const testCommand = function(cmd, cmdObj) { cmdObj["collectionUUID"] = uuid; res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, uuid, coll.getFullName()); + validateErrorResponse(res, uuid, coll2.getFullName(), coll.getFullName()); jsTestLog("The command '" + cmd + "' fails when the provided UUID corresponds to a different collection, even if the " + @@ -49,7 +50,7 @@ const testCommand = function(cmd, cmdObj) { coll2.drop(); res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, uuid, coll.getFullName()); + validateErrorResponse(res, uuid, coll2.getFullName(), coll.getFullName()); jsTestLog("The command '" + cmd + "' succeeds on view when no UUID is provided."); const viewName = "view"; @@ -66,7 +67,7 @@ const testCommand = function(cmd, cmdObj) { cmdObj["collectionUUID"] = uuid; res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, uuid, coll.getFullName()); + validateErrorResponse(res, uuid, testDB.getName() + '.' + viewName, coll.getFullName()); assert.commandWorked(testDB.runCommand({drop: viewName, writeConcern: {w: "majority"}})); jsTestLog("The command '" + cmd + @@ -84,7 +85,7 @@ const testCommand = function(cmd, cmdObj) { cmdObj["collectionUUID"] = uuid; res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, uuid, coll.getFullName()); + validateErrorResponse(res, uuid, testDB.getName() + '.' + tsCollName, coll.getFullName()); assert.commandWorked(testDB.runCommand({drop: tsCollName, writeConcern: {w: "majority"}})); }; diff --git a/jstests/core/collection_uuid_coll_mod.js b/jstests/core/collection_uuid_coll_mod.js index c71c0c868c8..176c1e7e7ba 100644 --- a/jstests/core/collection_uuid_coll_mod.js +++ b/jstests/core/collection_uuid_coll_mod.js @@ -29,7 +29,7 @@ let res = assert.commandFailedWithCode( ErrorCodes.CollectionUUIDMismatch); assert.eq(res.collectionUUID, nonexistentUUID); assert.eq(res.expectedNamespace, coll.getFullName()); -assert.eq(res.actualNamespace, ""); +assert.eq(res.actualNamespace, null); // 3. The command fails when the provided UUID corresponds to a different collection. const coll2 = testDB['coll_2']; diff --git a/jstests/core/collection_uuid_drop.js b/jstests/core/collection_uuid_drop.js index b06d0af6bc3..8ecb6eb0e13 100644 --- a/jstests/core/collection_uuid_drop.js +++ b/jstests/core/collection_uuid_drop.js @@ -31,7 +31,7 @@ let res = assert.commandFailedWithCode( ErrorCodes.CollectionUUIDMismatch); assert.eq(res.collectionUUID, nonexistentUUID); assert.eq(res.expectedNamespace, coll.getFullName()); -assert.eq(res.actualNamespace, ""); +assert.eq(res.actualNamespace, null); // The command fails when the provided UUID corresponds to a different collection. const coll2 = testDB['coll_2']; diff --git a/jstests/core/collection_uuid_find.js b/jstests/core/collection_uuid_find.js index 7391994c187..195cb1f3df7 100644 --- a/jstests/core/collection_uuid_find.js +++ b/jstests/core/collection_uuid_find.js @@ -29,7 +29,7 @@ let res = assert.commandFailedWithCode( ErrorCodes.CollectionUUIDMismatch); assert.eq(res.collectionUUID, nonexistentUUID); assert.eq(res.expectedNamespace, coll.getFullName()); -assert.eq(res.actualNamespace, ""); +assert.eq(res.actualNamespace, null); // The command fails when the provided UUID corresponds to a different collection. const coll2 = testDB['coll_2']; diff --git a/jstests/core/collection_uuid_index_commands.js b/jstests/core/collection_uuid_index_commands.js index 76e4cb09f15..8f47b5feb65 100644 --- a/jstests/core/collection_uuid_index_commands.js +++ b/jstests/core/collection_uuid_index_commands.js @@ -47,7 +47,7 @@ const testCommand = function(cmd, cmdObj) { cmdObj["collectionUUID"] = nonexistentUUID; let res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, nonexistentUUID, coll.getFullName(), ""); + validateErrorResponse(res, nonexistentUUID, coll.getFullName(), null); jsTestLog("The command '" + cmd + "' fails when the provided UUID corresponds to a different collection."); diff --git a/jstests/core/collection_uuid_rename_collection.js b/jstests/core/collection_uuid_rename_collection.js index 5b0777748b0..c26b8c11670 100644 --- a/jstests/core/collection_uuid_rename_collection.js +++ b/jstests/core/collection_uuid_rename_collection.js @@ -70,7 +70,7 @@ let res = assert.commandFailedWithCode(testDB.adminCommand({ ErrorCodes.CollectionUUIDMismatch); assert.eq(res.collectionUUID, nonexistentUUID); assert.eq(res.expectedNamespace, coll.getFullName()); -assert.eq(res.actualNamespace, ""); +assert.eq(res.actualNamespace, null); res = assert.commandFailedWithCode(testDB.adminCommand({ renameCollection: coll2.getFullName(), @@ -80,7 +80,7 @@ res = assert.commandFailedWithCode(testDB.adminCommand({ ErrorCodes.CollectionUUIDMismatch); assert.eq(res.collectionUUID, nonexistentUUID); assert.eq(res.expectedNamespace, coll.getFullName()); -assert.eq(res.actualNamespace, ""); +assert.eq(res.actualNamespace, null); // The command fails when the provided UUID corresponds to a different collection. res = assert.commandFailedWithCode(testDB.adminCommand({ diff --git a/jstests/core/collection_uuid_write_commands.js b/jstests/core/collection_uuid_write_commands.js index fde135815fc..322b492e349 100644 --- a/jstests/core/collection_uuid_write_commands.js +++ b/jstests/core/collection_uuid_write_commands.js @@ -10,7 +10,7 @@ (function() { 'use strict'; -var validateErrorResponse = function(res, collectionUUID, expectedNamespace, actualNamespace) { +const validateErrorResponse = function(res, collectionUUID, expectedNamespace, actualNamespace) { if (res.writeErrors) { // Sharded cluster scenario. res = res.writeErrors[0]; @@ -41,7 +41,7 @@ var testCommand = function(cmd, cmdObj) { cmdObj["collectionUUID"] = nonexistentUUID; let res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, nonexistentUUID, coll.getFullName(), ""); + validateErrorResponse(res, nonexistentUUID, coll.getFullName(), null); jsTestLog("The command '" + cmd + "' fails when the provided UUID corresponds to a different collection."); diff --git a/jstests/sharding/collection_uuid_coll_stats_index_stats.js b/jstests/sharding/collection_uuid_coll_stats_index_stats.js index 21cf74945b6..452af9ac512 100644 --- a/jstests/sharding/collection_uuid_coll_stats_index_stats.js +++ b/jstests/sharding/collection_uuid_coll_stats_index_stats.js @@ -84,7 +84,7 @@ const testCommand = function(cmd, cmdObj) { cmdObj["collectionUUID"] = otherShardUUID; res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, otherShardUUID, sameShardColl.getFullName(), ""); + validateErrorResponse(res, otherShardUUID, sameShardColl.getFullName(), null); }; testCommand("aggregate", {aggregate: "", pipeline: [{$collStats: {latencyStats: {}}}], cursor: {}}); diff --git a/jstests/sharding/collection_uuid_refine_collection_shard_key.js b/jstests/sharding/collection_uuid_refine_collection_shard_key.js index cb6ac1ee226..d3708e231d4 100644 --- a/jstests/sharding/collection_uuid_refine_collection_shard_key.js +++ b/jstests/sharding/collection_uuid_refine_collection_shard_key.js @@ -56,7 +56,7 @@ let res = assert.commandFailedWithCode(mongos.adminCommand({ ErrorCodes.CollectionUUIDMismatch); assert.eq(res.collectionUUID, nonexistentUUID); assert.eq(res.expectedNamespace, coll.getFullName()); -assert.eq(res.actualNamespace, ""); +assert.eq(res.actualNamespace, null); // The command fails when provided with a different collection's UUID. const coll2 = db['coll_2']; diff --git a/jstests/sharding/collection_uuid_reshard_collection.js b/jstests/sharding/collection_uuid_reshard_collection.js index 381a79147b2..2043de00bdc 100644 --- a/jstests/sharding/collection_uuid_reshard_collection.js +++ b/jstests/sharding/collection_uuid_reshard_collection.js @@ -53,7 +53,7 @@ let res = assert.commandFailedWithCode(mongos.adminCommand({ ErrorCodes.CollectionUUIDMismatch); assert.eq(res.collectionUUID, nonexistentUUID); assert.eq(res.expectedNamespace, coll.getFullName()); -assert.eq(res.actualNamespace, ""); +assert.eq(res.actualNamespace, null); // The command fails when provided with a different collection's UUID. const coll2 = db['coll_2']; diff --git a/jstests/sharding/collection_uuid_shard_collection.js b/jstests/sharding/collection_uuid_shard_collection.js index e9c2f3b5e2f..8681a4536d8 100644 --- a/jstests/sharding/collection_uuid_shard_collection.js +++ b/jstests/sharding/collection_uuid_shard_collection.js @@ -42,7 +42,7 @@ let res = assert.commandFailedWithCode( ErrorCodes.CollectionUUIDMismatch); assert.eq(res.collectionUUID, nonexistentUUID); assert.eq(res.expectedNamespace, coll.getFullName()); -assert.eq(res.actualNamespace, ""); +assert.eq(res.actualNamespace, null); // The command fails when the provided UUID corresponds to a different collection. const coll2 = db['coll_2']; diff --git a/src/mongo/db/catalog/collection_uuid_mismatch.cpp b/src/mongo/db/catalog/collection_uuid_mismatch.cpp index 1eb6d30c931..ad79a15f02e 100644 --- a/src/mongo/db/catalog/collection_uuid_mismatch.cpp +++ b/src/mongo/db/catalog/collection_uuid_mismatch.cpp @@ -49,11 +49,8 @@ void checkCollectionUUIDMismatch(OperationContext* opCtx, feature_flags::gCommandsAcceptCollectionUUID.isEnabled( serverGlobalParams.featureCompatibility)); - uassert((CollectionUUIDMismatchInfo{*uuid, - ns, - CollectionCatalog::get(opCtx) - ->lookupNSSByUUID(opCtx, *uuid) - .value_or(NamespaceString{})}), + uassert((CollectionUUIDMismatchInfo{ + *uuid, ns, CollectionCatalog::get(opCtx)->lookupNSSByUUID(opCtx, *uuid)}), "Collection UUID does not match that specified", coll && coll->uuid() == *uuid); } diff --git a/src/mongo/db/catalog/collection_uuid_mismatch_info.cpp b/src/mongo/db/catalog/collection_uuid_mismatch_info.cpp index 3813615916a..5313b459b67 100644 --- a/src/mongo/db/catalog/collection_uuid_mismatch_info.cpp +++ b/src/mongo/db/catalog/collection_uuid_mismatch_info.cpp @@ -35,18 +35,29 @@ namespace mongo { namespace { MONGO_INIT_REGISTER_ERROR_EXTRA_INFO(CollectionUUIDMismatchInfo); + +constexpr StringData kCollectionUUIDFieldName = "collectionUUID"_sd; +constexpr StringData kExpectedNamespaceFieldName = "expectedNamespace"_sd; +constexpr StringData kActualNamespaceFieldName = "actualNamespace"_sd; } // namespace std::shared_ptr<const ErrorExtraInfo> CollectionUUIDMismatchInfo::parse(const BSONObj& obj) { + auto actualNamespace = obj[kActualNamespaceFieldName]; return std::make_shared<CollectionUUIDMismatchInfo>( - UUID::parse(obj["collectionUUID"]).getValue(), - NamespaceString{obj.getStringField("expectedNamespace")}, - NamespaceString{obj.getStringField("actualNamespace")}); + UUID::parse(obj[kCollectionUUIDFieldName]).getValue(), + NamespaceString{obj.getStringField(kExpectedNamespaceFieldName)}, + actualNamespace.isNull() + ? boost::none + : boost::make_optional(NamespaceString{actualNamespace.valueStringData()})); } void CollectionUUIDMismatchInfo::serialize(BSONObjBuilder* builder) const { - _collectionUUID.appendToBuilder(builder, "collectionUUID"); - builder->append("expectedNamespace", _expectedNamespace.ns()); - builder->append("actualNamespace", _actualNamespace.ns()); + _collectionUUID.appendToBuilder(builder, kCollectionUUIDFieldName); + builder->append(kExpectedNamespaceFieldName, _expectedNamespace.ns()); + if (_actualNamespace) { + builder->append(kActualNamespaceFieldName, _actualNamespace->ns()); + } else { + builder->appendNull(kActualNamespaceFieldName); + } } } // namespace mongo diff --git a/src/mongo/db/catalog/collection_uuid_mismatch_info.h b/src/mongo/db/catalog/collection_uuid_mismatch_info.h index c851c57e36d..538527b14c9 100644 --- a/src/mongo/db/catalog/collection_uuid_mismatch_info.h +++ b/src/mongo/db/catalog/collection_uuid_mismatch_info.h @@ -40,7 +40,7 @@ public: explicit CollectionUUIDMismatchInfo(const UUID& collectionUUID, const NamespaceString& expectedNamespace, - const NamespaceString& actualNamespace) + const boost::optional<NamespaceString>& actualNamespace) : _collectionUUID(collectionUUID), _expectedNamespace(expectedNamespace), _actualNamespace(actualNamespace) {} @@ -56,6 +56,6 @@ public: private: UUID _collectionUUID; NamespaceString _expectedNamespace; - NamespaceString _actualNamespace; + boost::optional<NamespaceString> _actualNamespace; }; } // namespace mongo diff --git a/src/mongo/s/cluster_commands_helpers.cpp b/src/mongo/s/cluster_commands_helpers.cpp index 32bc6e50137..abeec91696c 100644 --- a/src/mongo/s/cluster_commands_helpers.cpp +++ b/src/mongo/s/cluster_commands_helpers.cpp @@ -626,16 +626,14 @@ RawResponsesResult appendRawResponses( auto& firstError = genericErrorsReceived.front().second; if (firstError.code() == ErrorCodes::CollectionUUIDMismatch && - firstError.extraInfo<CollectionUUIDMismatchInfo>()->actualNamespace().isEmpty()) { + !firstError.extraInfo<CollectionUUIDMismatchInfo>()->actualNamespace()) { // The first error is a CollectionUUIDMismatchInfo but it doesn't contain an actual // namespace. It's possible that the acutal namespace is unsharded, in which case only the // error from the primary shard will contain this information. Iterate through the errors to // see if this is the case. for (const auto& error : genericErrorsReceived) { if (error.second.code() == ErrorCodes::CollectionUUIDMismatch && - !error.second.extraInfo<CollectionUUIDMismatchInfo>() - ->actualNamespace() - .isEmpty()) { + error.second.extraInfo<CollectionUUIDMismatchInfo>()->actualNamespace()) { firstError = error.second; break; } diff --git a/src/mongo/s/query/establish_cursors.cpp b/src/mongo/s/query/establish_cursors.cpp index f73a1672efb..c37de60e22d 100644 --- a/src/mongo/s/query/establish_cursors.cpp +++ b/src/mongo/s/query/establish_cursors.cpp @@ -254,7 +254,7 @@ void CursorEstablisher::_favorCollectionUUIDMismatchError(Status newError) noexc // Favor 'CollectionUUIDMismatchError' that has a non empty 'actualNamespace'. auto errorInfo = _maybeFailure->extraInfo<CollectionUUIDMismatchInfo>(); invariant(errorInfo); - if (errorInfo->actualNamespace().ns().empty()) { + if (!errorInfo->actualNamespace()) { _maybeFailure = std::move(newError); } } |