diff options
author | Gregory Noma <gregory.noma@gmail.com> | 2022-02-15 05:53:54 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-02-15 06:20:36 +0000 |
commit | d02536f48aee7593077c12b1e60829b9441a7c08 (patch) | |
tree | 3e07a27328b7d2191e02159c44ef18b9ca6e3d68 | |
parent | 9e354a640fd52d5ecfbaabb305eea25d21956a38 (diff) | |
download | mongo-d02536f48aee7593077c12b1e60829b9441a7c08.tar.gz |
SERVER-63528 Use db and collection instead of namespace in CollectionUUIDMismatch error response
20 files changed, 348 insertions, 134 deletions
diff --git a/jstests/aggregation/aggregation_with_uuids.js b/jstests/aggregation/aggregation_with_uuids.js index 52bcc99545f..b5f70c54c89 100644 --- a/jstests/aggregation/aggregation_with_uuids.js +++ b/jstests/aggregation/aggregation_with_uuids.js @@ -16,10 +16,12 @@ const collName = "foo"; const testDB = db.getSiblingDB(dbName); const testColl = testDB.getCollection(collName); -const validateErrorResponse = function(res, collectionUUID, expectedNamespace, actualNamespace) { +const validateErrorResponse = function( + res, db, collectionUUID, expectedCollection, actualCollection) { + assert.eq(res.db, db); assert.eq(res.collectionUUID, collectionUUID); - assert.eq(res.expectedNamespace, expectedNamespace); - assert.eq(res.actualNamespace, actualNamespace); + assert.eq(res.expectedCollection, expectedCollection); + assert.eq(res.actualCollection, actualCollection); }; // On mongos, collectionUUID is only supported for $collStats and $indexStats aggregations. @@ -69,7 +71,7 @@ let res = assert.commandFailedWithCode( testDB.runCommand( {aggregate: "doesNotExist", collectionUUID: uuid, pipeline: [{$match: {}}], cursor: {}}), ErrorCodes.CollectionUUIDMismatch); -validateErrorResponse(res, uuid, testDB.getName() + '.doesNotExist', testColl.getFullName()); +validateErrorResponse(res, dbName, uuid, 'doesNotExist', testColl.getName()); // Drop the collection. testColl.drop({writeConcern: {w: "majority"}}); @@ -79,7 +81,7 @@ res = assert.commandFailedWithCode( testDB.runCommand( {aggregate: collName, collectionUUID: uuid, pipeline: [{$match: {}}], cursor: {}}), ErrorCodes.CollectionUUIDMismatch); -validateErrorResponse(res, uuid, testColl.getFullName(), null); +validateErrorResponse(res, dbName, uuid, testColl.getName(), null); // Now recreate the collection. assert.commandWorked(testColl.insert(docs)); @@ -89,7 +91,7 @@ res = assert.commandFailedWithCode( testDB.runCommand( {aggregate: collName, collectionUUID: uuid, pipeline: [{$match: {}}], cursor: {}}), ErrorCodes.CollectionUUIDMismatch); -validateErrorResponse(res, uuid, testColl.getFullName(), null); +validateErrorResponse(res, dbName, uuid, testColl.getName(), null); collNameRes = assert.commandWorked( testDB.runCommand({aggregate: collName, pipeline: [{$match: {}}], cursor: {}})); @@ -106,7 +108,7 @@ res = assert.commandFailedWithCode( testDB.runCommand( {aggregate: "viewCollection", collectionUUID: uuid, pipeline: [{$match: {}}], cursor: {}}), ErrorCodes.CollectionUUIDMismatch); -validateErrorResponse(res, uuid, testDB.getName() + '.viewCollection', null); +validateErrorResponse(res, dbName, uuid, '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 3ad76a86a5b..5aa92524652 100644 --- a/jstests/aggregation/collection_uuid_coll_stats_index_stats.js +++ b/jstests/aggregation/collection_uuid_coll_stats_index_stats.js @@ -5,10 +5,12 @@ (function() { 'use strict'; -const validateErrorResponse = function(res, collectionUUID, expectedNamespace, actualNamespace) { +const validateErrorResponse = function( + res, db, collectionUUID, expectedCollection, actualCollection) { + assert.eq(res.db, db); assert.eq(res.collectionUUID, collectionUUID); - assert.eq(res.expectedNamespace, expectedNamespace); - assert.eq(res.actualNamespace, actualNamespace); + assert.eq(res.expectedCollection, expectedCollection); + assert.eq(res.actualCollection, actualCollection); }; const testCommand = function(cmd, cmdObj) { @@ -32,7 +34,7 @@ const testCommand = function(cmd, cmdObj) { cmdObj["collectionUUID"] = nonexistentUUID; let res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, nonexistentUUID, coll.getFullName(), null); + validateErrorResponse(res, testDB.getName(), nonexistentUUID, coll.getName(), null); jsTestLog("The command '" + cmd + "' fails when the provided UUID corresponds to a different collection."); @@ -42,7 +44,7 @@ const testCommand = function(cmd, cmdObj) { cmdObj["collectionUUID"] = uuid; res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, uuid, coll2.getFullName(), coll.getFullName()); + validateErrorResponse(res, testDB.getName(), uuid, coll2.getName(), coll.getName()); jsTestLog("The command '" + cmd + "' fails when the provided UUID corresponds to a different collection, even if the " + @@ -50,7 +52,7 @@ const testCommand = function(cmd, cmdObj) { coll2.drop(); res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, uuid, coll2.getFullName(), coll.getFullName()); + validateErrorResponse(res, testDB.getName(), uuid, coll2.getName(), coll.getName()); jsTestLog("The command '" + cmd + "' succeeds on view when no UUID is provided."); const viewName = "view"; @@ -67,7 +69,7 @@ const testCommand = function(cmd, cmdObj) { cmdObj["collectionUUID"] = uuid; res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, uuid, testDB.getName() + '.' + viewName, coll.getFullName()); + validateErrorResponse(res, testDB.getName(), uuid, viewName, coll.getName()); assert.commandWorked(testDB.runCommand({drop: viewName, writeConcern: {w: "majority"}})); jsTestLog("The command '" + cmd + @@ -85,8 +87,19 @@ const testCommand = function(cmd, cmdObj) { cmdObj["collectionUUID"] = uuid; res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, uuid, testDB.getName() + '.' + tsCollName, coll.getFullName()); + validateErrorResponse(res, testDB.getName(), uuid, tsCollName, coll.getName()); assert.commandWorked(testDB.runCommand({drop: tsCollName, writeConcern: {w: "majority"}})); + + jsTestLog("Only collections in the same database are specified by actualCollection."); + const otherDB = testDB.getSiblingDB(testDB.getName() + '_2'); + assert.commandWorked(otherDB.dropDatabase()); + assert.commandWorked(otherDB.dropDatabase()); + const coll3 = otherDB['coll_3']; + assert.commandWorked(coll3.insert({_id: 2})); + cmdObj[cmd] = coll3.getName(); + res = + assert.commandFailedWithCode(otherDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); + validateErrorResponse(res, otherDB.getName(), uuid, coll3.getName(), null); }; testCommand("aggregate", {aggregate: "", pipeline: [{$indexStats: {}}], cursor: {}}); diff --git a/jstests/core/collection_uuid_coll_mod.js b/jstests/core/collection_uuid_coll_mod.js index 176c1e7e7ba..016e280106c 100644 --- a/jstests/core/collection_uuid_coll_mod.js +++ b/jstests/core/collection_uuid_coll_mod.js @@ -27,9 +27,10 @@ const nonexistentUUID = UUID(); let res = assert.commandFailedWithCode( testDB.runCommand({collMod: coll.getName(), collectionUUID: nonexistentUUID}), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); assert.eq(res.collectionUUID, nonexistentUUID); -assert.eq(res.expectedNamespace, coll.getFullName()); -assert.eq(res.actualNamespace, null); +assert.eq(res.expectedCollection, coll.getName()); +assert.eq(res.actualCollection, null); // 3. The command fails when the provided UUID corresponds to a different collection. const coll2 = testDB['coll_2']; @@ -37,17 +38,32 @@ assert.commandWorked(coll2.insert({_id: 1})); res = assert.commandFailedWithCode( testDB.runCommand({collMod: coll2.getName(), collectionUUID: uuid}), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); assert.eq(res.collectionUUID, uuid); -assert.eq(res.expectedNamespace, coll2.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); -// 3. The command fails when the provided UUID corresponds to a different collection, even if the +// 4. Only collections in the same database are specified by actualCollection. +const otherDB = testDB.getSiblingDB(testDB.getName() + '_2'); +assert.commandWorked(otherDB.dropDatabase()); +const coll3 = otherDB['coll_3']; +assert.commandWorked(coll3.insert({_id: 2})); +res = assert.commandFailedWithCode( + otherDB.runCommand({collMod: coll3.getName(), collectionUUID: uuid}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, otherDB.getName()); +assert.eq(res.collectionUUID, uuid); +assert.eq(res.expectedCollection, coll3.getName()); +assert.eq(res.actualCollection, null); + +// 5. The command fails when the provided UUID corresponds to a different collection, even if the // provided namespace does not exist. coll2.drop(); res = assert.commandFailedWithCode( testDB.runCommand({collMod: coll2.getName(), collectionUUID: uuid}), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); assert.eq(res.collectionUUID, uuid); -assert.eq(res.expectedNamespace, coll2.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); })(); diff --git a/jstests/core/collection_uuid_drop.js b/jstests/core/collection_uuid_drop.js index 8ecb6eb0e13..0146643c0f4 100644 --- a/jstests/core/collection_uuid_drop.js +++ b/jstests/core/collection_uuid_drop.js @@ -29,27 +29,43 @@ const nonexistentUUID = UUID(); let res = assert.commandFailedWithCode( testDB.runCommand({drop: coll.getName(), collectionUUID: nonexistentUUID}), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); assert.eq(res.collectionUUID, nonexistentUUID); -assert.eq(res.expectedNamespace, coll.getFullName()); -assert.eq(res.actualNamespace, null); +assert.eq(res.expectedCollection, coll.getName()); +assert.eq(res.actualCollection, null); // The command fails when the provided UUID corresponds to a different collection. const coll2 = testDB['coll_2']; assert.commandWorked(coll2.insert({_id: 1})); res = assert.commandFailedWithCode(testDB.runCommand({drop: coll2.getName(), collectionUUID: uuid}), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); assert.eq(res.collectionUUID, uuid); -assert.eq(res.expectedNamespace, coll2.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); + +// Only collections in the same database are specified by actualCollection. +const otherDB = testDB.getSiblingDB(testDB.getName() + '_2'); +assert.commandWorked(otherDB.dropDatabase()); +const coll3 = otherDB['coll_3']; +assert.commandWorked(coll3.insert({_id: 2})); +res = + assert.commandFailedWithCode(otherDB.runCommand({drop: coll3.getName(), collectionUUID: uuid}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, otherDB.getName()); +assert.eq(res.collectionUUID, uuid); +assert.eq(res.expectedCollection, coll3.getName()); +assert.eq(res.actualCollection, null); // The command fails when the provided UUID corresponds to a different collection, even if the // provided namespace does not exist. coll2.drop(); res = assert.commandFailedWithCode(testDB.runCommand({drop: coll2.getName(), collectionUUID: uuid}), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); assert.eq(res.collectionUUID, uuid); -assert.eq(res.expectedNamespace, coll2.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); // The command fails when the provided UUID corresponds to a different collection, even if the // provided namespace is a view. @@ -57,9 +73,10 @@ const view = 'view'; assert.commandWorked(testDB.createView(view, coll.getName(), [])); res = assert.commandFailedWithCode(testDB.runCommand({drop: view, collectionUUID: uuid}), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); assert.eq(res.collectionUUID, uuid); -assert.eq(res.expectedNamespace, testDB.getName() + "." + view); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, view); +assert.eq(res.actualCollection, coll.getName()); // The command succeeds when the correct UUID is provided. assert.commandWorked(testDB.runCommand({drop: coll.getName(), collectionUUID: uuid})); diff --git a/jstests/core/collection_uuid_find.js b/jstests/core/collection_uuid_find.js index 195cb1f3df7..c544dfed75f 100644 --- a/jstests/core/collection_uuid_find.js +++ b/jstests/core/collection_uuid_find.js @@ -27,27 +27,43 @@ const nonexistentUUID = UUID(); let res = assert.commandFailedWithCode( testDB.runCommand({find: coll.getName(), collectionUUID: nonexistentUUID}), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); assert.eq(res.collectionUUID, nonexistentUUID); -assert.eq(res.expectedNamespace, coll.getFullName()); -assert.eq(res.actualNamespace, null); +assert.eq(res.expectedCollection, coll.getName()); +assert.eq(res.actualCollection, null); // The command fails when the provided UUID corresponds to a different collection. const coll2 = testDB['coll_2']; assert.commandWorked(coll2.insert({_id: 1})); res = assert.commandFailedWithCode(testDB.runCommand({find: coll2.getName(), collectionUUID: uuid}), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); assert.eq(res.collectionUUID, uuid); -assert.eq(res.expectedNamespace, coll2.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); + +// Only collections in the same database are specified by actualCollection. +const otherDB = testDB.getSiblingDB(testDB.getName() + '_2'); +assert.commandWorked(otherDB.dropDatabase()); +const coll3 = otherDB['coll_3']; +assert.commandWorked(coll3.insert({_id: 2})); +res = + assert.commandFailedWithCode(otherDB.runCommand({find: coll3.getName(), collectionUUID: uuid}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, otherDB.getName()); +assert.eq(res.collectionUUID, uuid); +assert.eq(res.expectedCollection, coll3.getName()); +assert.eq(res.actualCollection, null); // The command fails when the provided UUID corresponds to a different collection, even if the // provided namespace does not exist. coll2.drop(); res = assert.commandFailedWithCode(testDB.runCommand({find: coll2.getName(), collectionUUID: uuid}), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); assert.eq(res.collectionUUID, uuid); -assert.eq(res.expectedNamespace, coll2.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); // The command fails when the provided UUID corresponds to a different collection, even if the // provided namespace is a view. @@ -55,7 +71,8 @@ const viewName = 'view'; assert.commandWorked(testDB.createView(viewName, coll.getName(), [])); res = assert.commandFailedWithCode(testDB.runCommand({find: viewName, collectionUUID: uuid}), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); assert.eq(res.collectionUUID, uuid); -assert.eq(res.expectedNamespace, testDB.getName() + '.' + viewName); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, viewName); +assert.eq(res.actualCollection, coll.getName()); })(); diff --git a/jstests/core/collection_uuid_index_commands.js b/jstests/core/collection_uuid_index_commands.js index 8f47b5feb65..ae0e0610c85 100644 --- a/jstests/core/collection_uuid_index_commands.js +++ b/jstests/core/collection_uuid_index_commands.js @@ -10,18 +10,22 @@ (function() { 'use strict'; -const validateErrorResponse = function(res, collectionUUID, expectedNamespace, actualNamespace) { +const validateErrorResponse = function( + res, db, collectionUUID, expectedCollection, actualCollection) { + assert.eq(res.db, db); assert.eq(res.collectionUUID, collectionUUID); - assert.eq(res.expectedNamespace, expectedNamespace); - assert.eq(res.actualNamespace, actualNamespace); + assert.eq(res.expectedCollection, expectedCollection); + assert.eq(res.actualCollection, actualCollection); if (res.raw) { // In sharded cluster scenario, the inner raw shards reply should contain the error info, // along with the outer reply obj. for (let [_, shardReply] of Object.entries(res.raw)) { assert.eq(shardReply.code, ErrorCodes.CollectionUUIDMismatch); + assert.eq(shardReply.db, db); assert.eq(shardReply.collectionUUID, collectionUUID); - assert.eq(shardReply.actualNamespace, actualNamespace); + assert.eq(shardReply.expectedCollection, expectedCollection); + assert.eq(shardReply.actualCollection, actualCollection); } } }; @@ -47,7 +51,7 @@ const testCommand = function(cmd, cmdObj) { cmdObj["collectionUUID"] = nonexistentUUID; let res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, nonexistentUUID, coll.getFullName(), null); + validateErrorResponse(res, testDB.getName(), nonexistentUUID, coll.getName(), null); jsTestLog("The command '" + cmd + "' fails when the provided UUID corresponds to a different collection."); @@ -58,7 +62,7 @@ const testCommand = function(cmd, cmdObj) { cmdObj["collectionUUID"] = uuid; res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, uuid, coll2.getFullName(), coll.getFullName()); + validateErrorResponse(res, testDB.getName(), uuid, coll2.getName(), coll.getName()); if (cmd === "dropIndexes") { assert.commandWorked(coll2.dropIndexes({y: 1})); @@ -67,7 +71,7 @@ const testCommand = function(cmd, cmdObj) { "UUID corresponds to a different collection, even if the index doesn't exist."); res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, uuid, coll2.getFullName(), coll.getFullName()); + validateErrorResponse(res, testDB.getName(), uuid, coll2.getName(), coll.getName()); } jsTestLog("The command '" + cmd + @@ -76,7 +80,17 @@ const testCommand = function(cmd, cmdObj) { coll2.drop(); res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, uuid, coll2.getFullName(), coll.getFullName()); + validateErrorResponse(res, testDB.getName(), uuid, coll2.getName(), coll.getName()); + + jsTestLog("Only collections in the same database are specified by actualCollection."); + const otherDB = testDB.getSiblingDB(testDB.getName() + '_2'); + assert.commandWorked(otherDB.dropDatabase()); + const coll3 = otherDB['coll_3']; + assert.commandWorked(coll3.insert({_id: 2})); + cmdObj[cmd] = coll3.getName(); + res = + assert.commandFailedWithCode(otherDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); + validateErrorResponse(res, otherDB.getName(), uuid, coll3.getName(), null); }; testCommand("createIndexes", {createIndexes: "", indexes: [{name: "x_1", key: {x: 1}}]}); diff --git a/jstests/core/collection_uuid_rename_collection.js b/jstests/core/collection_uuid_rename_collection.js index c26b8c11670..389150f5802 100644 --- a/jstests/core/collection_uuid_rename_collection.js +++ b/jstests/core/collection_uuid_rename_collection.js @@ -68,9 +68,10 @@ let res = assert.commandFailedWithCode(testDB.adminCommand({ collectionUUID: nonexistentUUID, }), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); assert.eq(res.collectionUUID, nonexistentUUID); -assert.eq(res.expectedNamespace, coll.getFullName()); -assert.eq(res.actualNamespace, null); +assert.eq(res.expectedCollection, coll.getName()); +assert.eq(res.actualCollection, null); res = assert.commandFailedWithCode(testDB.adminCommand({ renameCollection: coll2.getFullName(), @@ -78,9 +79,10 @@ res = assert.commandFailedWithCode(testDB.adminCommand({ dropTarget: nonexistentUUID, }), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); assert.eq(res.collectionUUID, nonexistentUUID); -assert.eq(res.expectedNamespace, coll.getFullName()); -assert.eq(res.actualNamespace, null); +assert.eq(res.expectedCollection, coll.getName()); +assert.eq(res.actualCollection, null); // The command fails when the provided UUID corresponds to a different collection. res = assert.commandFailedWithCode(testDB.adminCommand({ @@ -90,9 +92,10 @@ res = assert.commandFailedWithCode(testDB.adminCommand({ collectionUUID: uuid(coll), }), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); assert.eq(res.collectionUUID, uuid(coll)); -assert.eq(res.expectedNamespace, coll2.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); res = assert.commandFailedWithCode(testDB.adminCommand({ renameCollection: coll.getFullName(), @@ -100,9 +103,10 @@ res = assert.commandFailedWithCode(testDB.adminCommand({ dropTarget: uuid(coll), }), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); assert.eq(res.collectionUUID, uuid(coll)); -assert.eq(res.expectedNamespace, coll2.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); res = assert.commandFailedWithCode(testDB.adminCommand({ renameCollection: coll2.getFullName(), @@ -111,9 +115,51 @@ res = assert.commandFailedWithCode(testDB.adminCommand({ collectionUUID: uuid(coll), }), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); assert.eq(res.collectionUUID, uuid(coll)); -assert.eq(res.expectedNamespace, coll2.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); + +// Only collections in the same database are specified by actualCollection. +const otherDB = testDB.getSiblingDB(testDB.getName() + '_2'); +assert.commandWorked(otherDB.dropDatabase()); +const coll4 = otherDB['coll_4']; +const coll5 = otherDB['coll_5']; +assert.commandWorked(coll4.insert({_id: 2})); +res = assert.commandFailedWithCode(otherDB.adminCommand({ + renameCollection: coll4.getFullName(), + to: coll5.getFullName(), + dropTarget: true, + collectionUUID: uuid(coll), +}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, otherDB.getName()); +assert.eq(res.collectionUUID, uuid(coll)); +assert.eq(res.expectedCollection, coll4.getName()); +assert.eq(res.actualCollection, null); + +res = assert.commandFailedWithCode(otherDB.adminCommand({ + renameCollection: coll4.getFullName(), + to: coll5.getFullName(), + dropTarget: uuid(coll), +}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, otherDB.getName()); +assert.eq(res.collectionUUID, uuid(coll)); +assert.eq(res.expectedCollection, coll5.getName()); +assert.eq(res.actualCollection, null); + +res = assert.commandFailedWithCode(otherDB.adminCommand({ + renameCollection: coll4.getFullName(), + to: coll5.getFullName(), + dropTarget: uuid(coll2), + collectionUUID: uuid(coll), +}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, otherDB.getName()); +assert.eq(res.collectionUUID, uuid(coll)); +assert.eq(res.expectedCollection, coll4.getName()); +assert.eq(res.actualCollection, null); // The command fails when the provided UUID corresponds to a different collection, even if the // provided source namespace does not exist. @@ -125,9 +171,10 @@ res = assert.commandFailedWithCode(testDB.adminCommand({ collectionUUID: uuid(coll), }), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, testDB.getName()); assert.eq(res.collectionUUID, uuid(coll)); -assert.eq(res.expectedNamespace, coll2.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); // The collectionUUID parameter cannot be provided when renaming a collection between databases. const otherDBColl = db.getSiblingDB(jsTestName() + '_2').coll; diff --git a/jstests/core/collection_uuid_write_commands.js b/jstests/core/collection_uuid_write_commands.js index 322b492e349..276a1550767 100644 --- a/jstests/core/collection_uuid_write_commands.js +++ b/jstests/core/collection_uuid_write_commands.js @@ -10,15 +10,17 @@ (function() { 'use strict'; -const validateErrorResponse = function(res, collectionUUID, expectedNamespace, actualNamespace) { +const validateErrorResponse = function( + res, db, collectionUUID, expectedCollection, actualCollection) { if (res.writeErrors) { // Sharded cluster scenario. res = res.writeErrors[0]; } + assert.eq(res.db, db); assert.eq(res.collectionUUID, collectionUUID); - assert.eq(res.expectedNamespace, expectedNamespace); - assert.eq(res.actualNamespace, actualNamespace); + assert.eq(res.expectedCollection, expectedCollection); + assert.eq(res.actualCollection, actualCollection); }; var testCommand = function(cmd, cmdObj) { @@ -41,7 +43,7 @@ var testCommand = function(cmd, cmdObj) { cmdObj["collectionUUID"] = nonexistentUUID; let res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, nonexistentUUID, coll.getFullName(), null); + validateErrorResponse(res, testDB.getName(), nonexistentUUID, coll.getName(), null); jsTestLog("The command '" + cmd + "' fails when the provided UUID corresponds to a different collection."); @@ -51,7 +53,7 @@ var testCommand = function(cmd, cmdObj) { cmdObj["collectionUUID"] = uuid; res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, uuid, coll2.getFullName(), coll.getFullName()); + validateErrorResponse(res, testDB.getName(), uuid, coll2.getName(), coll.getName()); jsTestLog("The command '" + cmd + "' fails when the provided UUID corresponds to a different collection, even if the " + @@ -59,7 +61,17 @@ var testCommand = function(cmd, cmdObj) { coll2.drop(); res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, uuid, coll2.getFullName(), coll.getFullName()); + validateErrorResponse(res, testDB.getName(), uuid, coll2.getName(), coll.getName()); + + jsTestLog("Only collections in the same database are specified by actualCollection."); + const otherDB = testDB.getSiblingDB(testDB.getName() + '_2'); + assert.commandWorked(otherDB.dropDatabase()); + const coll3 = otherDB['coll_3']; + assert.commandWorked(coll3.insert({_id: 2})); + cmdObj[cmd] = coll3.getName(); + res = + assert.commandFailedWithCode(otherDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); + validateErrorResponse(res, otherDB.getName(), uuid, coll3.getName(), null); }; testCommand("insert", {insert: "", documents: [{inserted: true}]}); diff --git a/jstests/sharding/collection_uuid_coll_stats_index_stats.js b/jstests/sharding/collection_uuid_coll_stats_index_stats.js index 452af9ac512..639603aecba 100644 --- a/jstests/sharding/collection_uuid_coll_stats_index_stats.js +++ b/jstests/sharding/collection_uuid_coll_stats_index_stats.js @@ -9,10 +9,12 @@ load("jstests/libs/write_concern_util.js"); // For 'shardCollectionWithChunks' -const validateErrorResponse = function(res, collectionUUID, expectedNamespace, actualNamespace) { +const validateErrorResponse = function( + res, db, collectionUUID, expectedCollection, actualCollection) { + assert.eq(res.db, db); assert.eq(res.collectionUUID, collectionUUID); - assert.eq(res.expectedNamespace, expectedNamespace); - assert.eq(res.actualNamespace, actualNamespace); + assert.eq(res.expectedCollection, expectedCollection); + assert.eq(res.actualCollection, actualCollection); }; const getUUID = function(database, collName) { @@ -66,15 +68,14 @@ const testCommand = function(cmd, cmdObj) { let res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); validateErrorResponse( - res, sameShardUUID, shardedCollection.getFullName(), sameShardColl.getFullName()); + res, testDB.getName(), sameShardUUID, shardedCollection.getName(), sameShardColl.getName()); jsTestLog("If the aggregation command hits all shards, then it should return the " + "actual namespace of the unsharded collection that has different primary shard."); cmdObj["collectionUUID"] = otherShardUUID; res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse( - res, otherShardUUID, shardedCollection.getFullName(), otherShardColl.getFullName()); + validateErrorResponse(res, testDB.getName(), otherShardUUID, shardedCollection.getName(), null); jsTestLog( "If the aggregation command hits only one shards, then it can't find the actual namespace" + @@ -84,7 +85,7 @@ const testCommand = function(cmd, cmdObj) { cmdObj["collectionUUID"] = otherShardUUID; res = assert.commandFailedWithCode(testDB.runCommand(cmdObj), ErrorCodes.CollectionUUIDMismatch); - validateErrorResponse(res, otherShardUUID, sameShardColl.getFullName(), null); + validateErrorResponse(res, testDB.getName(), otherShardUUID, sameShardColl.getName(), null); }; testCommand("aggregate", {aggregate: "", pipeline: [{$collStats: {latencyStats: {}}}], cursor: {}}); diff --git a/jstests/sharding/collection_uuid_create_indexes.js b/jstests/sharding/collection_uuid_create_indexes.js index fdeefdf833b..4f9bd740f49 100644 --- a/jstests/sharding/collection_uuid_create_indexes.js +++ b/jstests/sharding/collection_uuid_create_indexes.js @@ -47,9 +47,10 @@ let res = assert.commandFailedWithCode(db.runCommand({ collectionUUID: uuid(unshardedColl), }), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, db.getName()); assert.eq(res.collectionUUID, uuid(unshardedColl)); -assert.eq(res.expectedNamespace, shardedColl.getFullName()); -assert.eq(res.actualNamespace, unshardedColl.getFullName()); +assert.eq(res.expectedCollection, shardedColl.getName()); +assert.eq(res.actualCollection, unshardedColl.getName()); // Run the command on the collection which is unsharded and exists only on shard0, while specifying // the UUID of the collection that is sharded. @@ -59,9 +60,10 @@ res = assert.commandFailedWithCode(db.runCommand({ collectionUUID: uuid(shardedColl), }), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, db.getName()); assert.eq(res.collectionUUID, uuid(shardedColl)); -assert.eq(res.expectedNamespace, unshardedColl.getFullName()); -assert.eq(res.actualNamespace, shardedColl.getFullName()); +assert.eq(res.expectedCollection, unshardedColl.getName()); +assert.eq(res.actualCollection, shardedColl.getName()); st.stop(); })(); diff --git a/jstests/sharding/collection_uuid_drop.js b/jstests/sharding/collection_uuid_drop.js index 82e8d42cb4d..f5fd263657c 100644 --- a/jstests/sharding/collection_uuid_drop.js +++ b/jstests/sharding/collection_uuid_drop.js @@ -44,17 +44,19 @@ assert.commandWorked(mongos.adminCommand( let res = assert.commandFailedWithCode( db.runCommand({drop: shardedColl.getName(), collectionUUID: uuid(unshardedColl)}), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, db.getName()); assert.eq(res.collectionUUID, uuid(unshardedColl)); -assert.eq(res.expectedNamespace, shardedColl.getFullName()); -assert.eq(res.actualNamespace, unshardedColl.getFullName()); +assert.eq(res.expectedCollection, shardedColl.getName()); +assert.eq(res.actualCollection, unshardedColl.getName()); // Run the drop command on the unsharded collection, which only exists on shard0. res = assert.commandFailedWithCode( db.runCommand({drop: unshardedColl.getName(), collectionUUID: uuid(shardedColl)}), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, db.getName()); assert.eq(res.collectionUUID, uuid(shardedColl)); -assert.eq(res.expectedNamespace, unshardedColl.getFullName()); -assert.eq(res.actualNamespace, shardedColl.getFullName()); +assert.eq(res.expectedCollection, unshardedColl.getName()); +assert.eq(res.actualCollection, shardedColl.getName()); st.stop(); })(); diff --git a/jstests/sharding/collection_uuid_drop_indexes.js b/jstests/sharding/collection_uuid_drop_indexes.js index b487eeabf22..6fc850bf5d8 100644 --- a/jstests/sharding/collection_uuid_drop_indexes.js +++ b/jstests/sharding/collection_uuid_drop_indexes.js @@ -50,9 +50,10 @@ let res = assert.commandFailedWithCode(db.runCommand({ collectionUUID: uuid(unshardedColl), }), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, db.getName()); assert.eq(res.collectionUUID, uuid(unshardedColl)); -assert.eq(res.expectedNamespace, shardedColl.getFullName()); -assert.eq(res.actualNamespace, unshardedColl.getFullName()); +assert.eq(res.expectedCollection, shardedColl.getName()); +assert.eq(res.actualCollection, unshardedColl.getName()); // Run the command on the collection which is unsharded and exists only on shard0, while specifying // the UUID of the collection that is sharded. @@ -62,9 +63,10 @@ res = assert.commandFailedWithCode(db.runCommand({ collectionUUID: uuid(shardedColl), }), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, db.getName()); assert.eq(res.collectionUUID, uuid(shardedColl)); -assert.eq(res.expectedNamespace, unshardedColl.getFullName()); -assert.eq(res.actualNamespace, shardedColl.getFullName()); +assert.eq(res.expectedCollection, unshardedColl.getName()); +assert.eq(res.actualCollection, shardedColl.getName()); st.stop(); })(); diff --git a/jstests/sharding/collection_uuid_refine_collection_shard_key.js b/jstests/sharding/collection_uuid_refine_collection_shard_key.js index d3708e231d4..4f4e5d82fdf 100644 --- a/jstests/sharding/collection_uuid_refine_collection_shard_key.js +++ b/jstests/sharding/collection_uuid_refine_collection_shard_key.js @@ -54,9 +54,10 @@ let res = assert.commandFailedWithCode(mongos.adminCommand({ collectionUUID: nonexistentUUID, }), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, db.getName()); assert.eq(res.collectionUUID, nonexistentUUID); -assert.eq(res.expectedNamespace, coll.getFullName()); -assert.eq(res.actualNamespace, null); +assert.eq(res.expectedCollection, coll.getName()); +assert.eq(res.actualCollection, null); // The command fails when provided with a different collection's UUID. const coll2 = db['coll_2']; @@ -67,9 +68,26 @@ res = assert.commandFailedWithCode(mongos.adminCommand({ collectionUUID: uuid(), }), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, db.getName()); assert.eq(res.collectionUUID, uuid()); -assert.eq(res.expectedNamespace, coll2.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); + +// Only collections in the same database are specified by actualCollection. +const otherDB = db.getSiblingDB(db.getName() + '_2'); +const coll3 = otherDB['coll_3']; +assert.commandWorked(mongos.adminCommand({enableSharding: otherDB.getName()})); +resetColl(coll3); +res = assert.commandFailedWithCode(mongos.adminCommand({ + refineCollectionShardKey: coll3.getFullName(), + key: newKeyDoc, + collectionUUID: uuid(), +}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, otherDB.getName()); +assert.eq(res.collectionUUID, uuid()); +assert.eq(res.expectedCollection, coll3.getName()); +assert.eq(res.actualCollection, null); // The command fails when provided with a different collection's UUID, even if the provided // namespace does not exist. @@ -80,9 +98,10 @@ res = assert.commandFailedWithCode(mongos.adminCommand({ collectionUUID: uuid(), }), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, db.getName()); assert.eq(res.collectionUUID, uuid()); -assert.eq(res.expectedNamespace, coll2.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); st.stop(); })(); diff --git a/jstests/sharding/collection_uuid_reshard_collection.js b/jstests/sharding/collection_uuid_reshard_collection.js index 2043de00bdc..7f0abb39955 100644 --- a/jstests/sharding/collection_uuid_reshard_collection.js +++ b/jstests/sharding/collection_uuid_reshard_collection.js @@ -51,9 +51,10 @@ let res = assert.commandFailedWithCode(mongos.adminCommand({ collectionUUID: nonexistentUUID, }), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, db.getName()); assert.eq(res.collectionUUID, nonexistentUUID); -assert.eq(res.expectedNamespace, coll.getFullName()); -assert.eq(res.actualNamespace, null); +assert.eq(res.expectedCollection, coll.getName()); +assert.eq(res.actualCollection, null); // The command fails when provided with a different collection's UUID. const coll2 = db['coll_2']; @@ -64,9 +65,26 @@ res = assert.commandFailedWithCode(mongos.adminCommand({ collectionUUID: uuid(), }), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, db.getName()); assert.eq(res.collectionUUID, uuid()); -assert.eq(res.expectedNamespace, coll2.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); + +// Only collections in the same database are specified by actualCollection. +const otherDB = db.getSiblingDB(db.getName() + '_2'); +const coll3 = otherDB['coll_3']; +assert.commandWorked(mongos.adminCommand({enableSharding: otherDB.getName()})); +resetColl(coll3); +res = assert.commandFailedWithCode(mongos.adminCommand({ + reshardCollection: coll3.getFullName(), + key: newKeyDoc, + collectionUUID: uuid(), +}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, otherDB.getName()); +assert.eq(res.collectionUUID, uuid()); +assert.eq(res.expectedCollection, coll3.getName()); +assert.eq(res.actualCollection, null); // The command fails when provided with a different collection's UUID, even if the provided // namespace does not exist. @@ -77,9 +95,10 @@ res = assert.commandFailedWithCode(mongos.adminCommand({ collectionUUID: uuid(), }), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, db.getName()); assert.eq(res.collectionUUID, uuid()); -assert.eq(res.expectedNamespace, coll2.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); // The command fails when the provided UUID corresponds to a different collection, even if the // provided namespace is a view. @@ -91,9 +110,10 @@ res = assert.commandFailedWithCode(mongos.adminCommand({ collectionUUID: uuid(), }), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, db.getName()); assert.eq(res.collectionUUID, uuid()); -assert.eq(res.expectedNamespace, view.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, view.getName()); +assert.eq(res.actualCollection, coll.getName()); st.stop(); })(); diff --git a/jstests/sharding/collection_uuid_shard_collection.js b/jstests/sharding/collection_uuid_shard_collection.js index 8681a4536d8..39b21c12247 100644 --- a/jstests/sharding/collection_uuid_shard_collection.js +++ b/jstests/sharding/collection_uuid_shard_collection.js @@ -40,9 +40,10 @@ let res = assert.commandFailedWithCode( mongos.adminCommand( {shardCollection: coll.getFullName(), key: {_id: 1}, collectionUUID: nonexistentUUID}), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, db.getName()); assert.eq(res.collectionUUID, nonexistentUUID); -assert.eq(res.expectedNamespace, coll.getFullName()); -assert.eq(res.actualNamespace, null); +assert.eq(res.expectedCollection, coll.getName()); +assert.eq(res.actualCollection, null); // The command fails when the provided UUID corresponds to a different collection. const coll2 = db['coll_2']; @@ -51,9 +52,26 @@ res = assert.commandFailedWithCode( mongos.adminCommand( {shardCollection: coll2.getFullName(), key: {_id: 1}, collectionUUID: uuid()}), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, db.getName()); assert.eq(res.collectionUUID, uuid()); -assert.eq(res.expectedNamespace, coll2.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); + +// Only collections in the same database are specified by actualCollection. +const otherDB = db.getSiblingDB(db.getName() + '_2'); +const coll3 = otherDB['coll_3']; +assert.commandWorked(mongos.adminCommand({enableSharding: otherDB.getName()})); +resetColl(coll3); +res = assert.commandFailedWithCode(mongos.adminCommand({ + shardCollection: coll3.getFullName(), + key: {_id: 1}, + collectionUUID: uuid(), +}), + ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, otherDB.getName()); +assert.eq(res.collectionUUID, uuid()); +assert.eq(res.expectedCollection, coll3.getName()); +assert.eq(res.actualCollection, null); // The command fails when the collection is already sharded and the provided UUID corresponds to a // different collection. @@ -62,9 +80,10 @@ res = assert.commandFailedWithCode( mongos.adminCommand( {shardCollection: coll2.getFullName(), key: {_id: 1}, collectionUUID: uuid()}), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, db.getName()); assert.eq(res.collectionUUID, uuid()); -assert.eq(res.expectedNamespace, coll2.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); // The command fails when the provided UUID corresponds to a different collection, even if the // provided namespace does not exist. @@ -73,9 +92,10 @@ res = assert.commandFailedWithCode( mongos.adminCommand( {shardCollection: coll2.getFullName(), key: {_id: 1}, collectionUUID: uuid()}), ErrorCodes.CollectionUUIDMismatch); +assert.eq(res.db, db.getName()); assert.eq(res.collectionUUID, uuid()); -assert.eq(res.expectedNamespace, coll2.getFullName()); -assert.eq(res.actualNamespace, coll.getFullName()); +assert.eq(res.expectedCollection, coll2.getName()); +assert.eq(res.actualCollection, coll.getName()); st.stop(); })(); diff --git a/src/mongo/db/catalog/collection_uuid_mismatch.cpp b/src/mongo/db/catalog/collection_uuid_mismatch.cpp index ad79a15f02e..7ae9410a2b2 100644 --- a/src/mongo/db/catalog/collection_uuid_mismatch.cpp +++ b/src/mongo/db/catalog/collection_uuid_mismatch.cpp @@ -49,9 +49,15 @@ void checkCollectionUUIDMismatch(OperationContext* opCtx, feature_flags::gCommandsAcceptCollectionUUID.isEnabled( serverGlobalParams.featureCompatibility)); - uassert((CollectionUUIDMismatchInfo{ - *uuid, ns, CollectionCatalog::get(opCtx)->lookupNSSByUUID(opCtx, *uuid)}), - "Collection UUID does not match that specified", - coll && coll->uuid() == *uuid); + auto actualNamespace = CollectionCatalog::get(opCtx)->lookupNSSByUUID(opCtx, *uuid); + uassert( + (CollectionUUIDMismatchInfo{ns.db().toString(), + *uuid, + ns.coll().toString(), + actualNamespace && actualNamespace->db() == ns.db() + ? boost::make_optional(actualNamespace->coll().toString()) + : boost::none}), + "Collection UUID does not match that specified", + coll && coll->uuid() == *uuid); } } // namespace mongo diff --git a/src/mongo/db/catalog/collection_uuid_mismatch_info.cpp b/src/mongo/db/catalog/collection_uuid_mismatch_info.cpp index 5313b459b67..7cb40347e92 100644 --- a/src/mongo/db/catalog/collection_uuid_mismatch_info.cpp +++ b/src/mongo/db/catalog/collection_uuid_mismatch_info.cpp @@ -36,28 +36,29 @@ namespace mongo { namespace { MONGO_INIT_REGISTER_ERROR_EXTRA_INFO(CollectionUUIDMismatchInfo); +constexpr StringData kDbFieldName = "db"_sd; constexpr StringData kCollectionUUIDFieldName = "collectionUUID"_sd; -constexpr StringData kExpectedNamespaceFieldName = "expectedNamespace"_sd; -constexpr StringData kActualNamespaceFieldName = "actualNamespace"_sd; +constexpr StringData kExpectedCollectionFieldName = "expectedCollection"_sd; +constexpr StringData kActualCollectionFieldName = "actualCollection"_sd; } // namespace std::shared_ptr<const ErrorExtraInfo> CollectionUUIDMismatchInfo::parse(const BSONObj& obj) { - auto actualNamespace = obj[kActualNamespaceFieldName]; + auto actualNamespace = obj[kActualCollectionFieldName]; return std::make_shared<CollectionUUIDMismatchInfo>( + obj[kDbFieldName].str(), UUID::parse(obj[kCollectionUUIDFieldName]).getValue(), - NamespaceString{obj.getStringField(kExpectedNamespaceFieldName)}, - actualNamespace.isNull() - ? boost::none - : boost::make_optional(NamespaceString{actualNamespace.valueStringData()})); + obj[kExpectedCollectionFieldName].str(), + actualNamespace.isNull() ? boost::none : boost::make_optional(actualNamespace.str())); } void CollectionUUIDMismatchInfo::serialize(BSONObjBuilder* builder) const { + builder->append(kDbFieldName, _db); _collectionUUID.appendToBuilder(builder, kCollectionUUIDFieldName); - builder->append(kExpectedNamespaceFieldName, _expectedNamespace.ns()); - if (_actualNamespace) { - builder->append(kActualNamespaceFieldName, _actualNamespace->ns()); + builder->append(kExpectedCollectionFieldName, _expectedCollection); + if (_actualCollection) { + builder->append(kActualCollectionFieldName, *_actualCollection); } else { - builder->appendNull(kActualNamespaceFieldName); + builder->appendNull(kActualCollectionFieldName); } } } // 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 538527b14c9..f32ea8c6c61 100644 --- a/src/mongo/db/catalog/collection_uuid_mismatch_info.h +++ b/src/mongo/db/catalog/collection_uuid_mismatch_info.h @@ -31,31 +31,34 @@ #include "mongo/base/error_extra_info.h" -#include "mongo/db/namespace_string.h" +#include "mongo/util/uuid.h" namespace mongo { class CollectionUUIDMismatchInfo final : public ErrorExtraInfo { public: static constexpr auto code = ErrorCodes::CollectionUUIDMismatch; - explicit CollectionUUIDMismatchInfo(const UUID& collectionUUID, - const NamespaceString& expectedNamespace, - const boost::optional<NamespaceString>& actualNamespace) - : _collectionUUID(collectionUUID), - _expectedNamespace(expectedNamespace), - _actualNamespace(actualNamespace) {} + explicit CollectionUUIDMismatchInfo(std::string db, + UUID collectionUUID, + std::string expectedCollection, + boost::optional<std::string> actualCollection) + : _db(std::move(db)), + _collectionUUID(std::move(collectionUUID)), + _expectedCollection(std::move(expectedCollection)), + _actualCollection(std::move(actualCollection)) {} static std::shared_ptr<const ErrorExtraInfo> parse(const BSONObj& obj); void serialize(BSONObjBuilder* builder) const override; - const auto& actualNamespace() const { - return _actualNamespace; + const auto& actualCollection() const { + return _actualCollection; } private: + std::string _db; UUID _collectionUUID; - NamespaceString _expectedNamespace; - boost::optional<NamespaceString> _actualNamespace; + std::string _expectedCollection; + boost::optional<std::string> _actualCollection; }; } // namespace mongo diff --git a/src/mongo/s/cluster_commands_helpers.cpp b/src/mongo/s/cluster_commands_helpers.cpp index abeec91696c..7a2ac3adca7 100644 --- a/src/mongo/s/cluster_commands_helpers.cpp +++ b/src/mongo/s/cluster_commands_helpers.cpp @@ -626,14 +626,14 @@ RawResponsesResult appendRawResponses( auto& firstError = genericErrorsReceived.front().second; if (firstError.code() == ErrorCodes::CollectionUUIDMismatch && - !firstError.extraInfo<CollectionUUIDMismatchInfo>()->actualNamespace()) { + !firstError.extraInfo<CollectionUUIDMismatchInfo>()->actualCollection()) { // 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()) { + error.second.extraInfo<CollectionUUIDMismatchInfo>()->actualCollection()) { firstError = error.second; break; } diff --git a/src/mongo/s/query/establish_cursors.cpp b/src/mongo/s/query/establish_cursors.cpp index c37de60e22d..57991fccb36 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()) { + if (!errorInfo->actualCollection()) { _maybeFailure = std::move(newError); } } |