summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/aggregation/collection_uuid_coll_stats_index_stats.js8
-rw-r--r--jstests/core/collection_uuid_coll_mod.js10
-rw-r--r--jstests/core/collection_uuid_drop.js10
-rw-r--r--jstests/core/collection_uuid_find.js10
-rw-r--r--jstests/core/collection_uuid_index_commands.js8
-rw-r--r--jstests/core/collection_uuid_rename_collection.js14
-rw-r--r--jstests/core/collection_uuid_write_commands.js8
-rw-r--r--src/mongo/db/catalog/drop_collection.cpp9
-rw-r--r--src/mongo/s/commands/SConscript1
-rw-r--r--src/mongo/s/commands/cluster_collection_mod_cmd.cpp14
-rw-r--r--src/mongo/s/commands/cluster_drop_collection_cmd.cpp8
-rw-r--r--src/mongo/s/commands/cluster_rename_collection_cmd.cpp12
-rw-r--r--src/mongo/s/query/SConscript1
-rw-r--r--src/mongo/s/query/cluster_aggregate.cpp8
-rw-r--r--src/mongo/s/query/cluster_find.cpp7
15 files changed, 124 insertions, 4 deletions
diff --git a/jstests/aggregation/collection_uuid_coll_stats_index_stats.js b/jstests/aggregation/collection_uuid_coll_stats_index_stats.js
index b0779a310f4..67c8ca65113 100644
--- a/jstests/aggregation/collection_uuid_coll_stats_index_stats.js
+++ b/jstests/aggregation/collection_uuid_coll_stats_index_stats.js
@@ -55,6 +55,14 @@ const testCommand = function(cmd, cmdObj) {
validateErrorResponse(res, testDB.getName(), uuid, coll2.getName(), coll.getName());
assert(!testDB.getCollectionNames().includes(coll2.getName()));
+ jsTestLog("The command '" + cmd +
+ "' fails with CollectionUUIDMismatch even if the database does not exist.");
+ const nonexistentDB = testDB.getSiblingDB(testDB.getName() + '_nonexistent');
+ cmdObj[cmd] = 'nonexistent';
+ res = assert.commandFailedWithCode(nonexistentDB.runCommand(cmdObj),
+ ErrorCodes.CollectionUUIDMismatch);
+ validateErrorResponse(res, nonexistentDB.getName(), uuid, 'nonexistent', null);
+
jsTestLog("The command '" + cmd + "' succeeds on view when no UUID is provided.");
const viewName = "view";
assert.commandWorked(testDB.runCommand(
diff --git a/jstests/core/collection_uuid_coll_mod.js b/jstests/core/collection_uuid_coll_mod.js
index 2e984d81713..218a758c0b3 100644
--- a/jstests/core/collection_uuid_coll_mod.js
+++ b/jstests/core/collection_uuid_coll_mod.js
@@ -66,4 +66,14 @@ assert.eq(res.collectionUUID, uuid);
assert.eq(res.expectedCollection, coll2.getName());
assert.eq(res.actualCollection, coll.getName());
assert(!testDB.getCollectionNames().includes(coll2.getName()));
+
+// 6. The command fails with CollectionUUIDMismatch even if the database does not exist.
+const nonexistentDB = testDB.getSiblingDB(testDB.getName() + '_nonexistent');
+res = assert.commandFailedWithCode(
+ nonexistentDB.runCommand({collMod: 'nonexistent', collectionUUID: uuid}),
+ ErrorCodes.CollectionUUIDMismatch);
+assert.eq(res.db, nonexistentDB.getName());
+assert.eq(res.collectionUUID, uuid);
+assert.eq(res.expectedCollection, 'nonexistent');
+assert.eq(res.actualCollection, null);
})();
diff --git a/jstests/core/collection_uuid_drop.js b/jstests/core/collection_uuid_drop.js
index 747a4b114ed..a3465795292 100644
--- a/jstests/core/collection_uuid_drop.js
+++ b/jstests/core/collection_uuid_drop.js
@@ -67,6 +67,16 @@ assert.eq(res.expectedCollection, coll2.getName());
assert.eq(res.actualCollection, coll.getName());
assert(!testDB.getCollectionNames().includes(coll2.getName()));
+// The command fails with CollectionUUIDMismatch even if the database does not exist.
+const nonexistentDB = testDB.getSiblingDB(testDB.getName() + '_nonexistent');
+res = assert.commandFailedWithCode(
+ nonexistentDB.runCommand({drop: 'nonexistent', collectionUUID: uuid}),
+ ErrorCodes.CollectionUUIDMismatch);
+assert.eq(res.db, nonexistentDB.getName());
+assert.eq(res.collectionUUID, uuid);
+assert.eq(res.expectedCollection, 'nonexistent');
+assert.eq(res.actualCollection, null);
+
// The command fails when the provided UUID corresponds to a different collection, even if the
// provided namespace is a view.
const view = 'view';
diff --git a/jstests/core/collection_uuid_find.js b/jstests/core/collection_uuid_find.js
index 93d6d011266..241435c1350 100644
--- a/jstests/core/collection_uuid_find.js
+++ b/jstests/core/collection_uuid_find.js
@@ -66,6 +66,16 @@ assert.eq(res.expectedCollection, coll2.getName());
assert.eq(res.actualCollection, coll.getName());
assert(!testDB.getCollectionNames().includes(coll2.getName()));
+// The command fails with CollectionUUIDMismatch even if the database does not exist.
+const nonexistentDB = testDB.getSiblingDB(testDB.getName() + '_nonexistent');
+res = assert.commandFailedWithCode(
+ nonexistentDB.runCommand({find: 'nonexistent', collectionUUID: uuid}),
+ ErrorCodes.CollectionUUIDMismatch);
+assert.eq(res.db, nonexistentDB.getName());
+assert.eq(res.collectionUUID, uuid);
+assert.eq(res.expectedCollection, 'nonexistent');
+assert.eq(res.actualCollection, null);
+
// The command fails when the provided UUID corresponds to a different collection, even if the
// provided namespace is a view.
const viewName = 'view';
diff --git a/jstests/core/collection_uuid_index_commands.js b/jstests/core/collection_uuid_index_commands.js
index 76ee83d8336..785183b8019 100644
--- a/jstests/core/collection_uuid_index_commands.js
+++ b/jstests/core/collection_uuid_index_commands.js
@@ -88,6 +88,14 @@ const testCommand = function(cmd, cmdObj) {
validateErrorResponse(res, testDB.getName(), uuid, coll2.getName(), coll.getName());
assert(!testDB.getCollectionNames().includes(coll2.getName()));
+ jsTestLog("The command '" + cmd +
+ "' fails with CollectionUUIDMismatch even if the database does not exist.");
+ const nonexistentDB = testDB.getSiblingDB(testDB.getName() + '_nonexistent');
+ cmdObj[cmd] = 'nonexistent';
+ res = assert.commandFailedWithCode(nonexistentDB.runCommand(cmdObj),
+ ErrorCodes.CollectionUUIDMismatch);
+ validateErrorResponse(res, nonexistentDB.getName(), uuid, 'nonexistent', null);
+
jsTestLog("Only collections in the same database are specified by actualCollection.");
const otherDB = testDB.getSiblingDB(testDB.getName() + '_2');
assert.commandWorked(otherDB.dropDatabase());
diff --git a/jstests/core/collection_uuid_rename_collection.js b/jstests/core/collection_uuid_rename_collection.js
index 85e8507c9d2..bc294fd7aab 100644
--- a/jstests/core/collection_uuid_rename_collection.js
+++ b/jstests/core/collection_uuid_rename_collection.js
@@ -176,6 +176,20 @@ assert.eq(res.expectedCollection, coll2.getName());
assert.eq(res.actualCollection, coll.getName());
assert(!testDB.getCollectionNames().includes(coll2.getName()));
+// The command fails with CollectionUUIDMismatch even if the database does not exist.
+const nonexistentDB = testDB.getSiblingDB(testDB.getName() + '_nonexistent');
+res = assert.commandFailedWithCode(testDB.adminCommand({
+ renameCollection: nonexistentDB.getName() + '.nonexistent',
+ to: nonexistentDB.getName() + '.nonexistent_2',
+ dropTarget: true,
+ collectionUUID: uuid(coll),
+}),
+ ErrorCodes.CollectionUUIDMismatch);
+assert.eq(res.db, nonexistentDB.getName());
+assert.eq(res.collectionUUID, uuid(coll));
+assert.eq(res.expectedCollection, 'nonexistent');
+assert.eq(res.actualCollection, null);
+
// The collectionUUID parameter cannot be provided when renaming a collection between databases.
const otherDBColl = db.getSiblingDB(jsTestName() + '_2').coll;
otherDBColl.drop();
diff --git a/jstests/core/collection_uuid_write_commands.js b/jstests/core/collection_uuid_write_commands.js
index 0ab9794df6f..080ce1772d5 100644
--- a/jstests/core/collection_uuid_write_commands.js
+++ b/jstests/core/collection_uuid_write_commands.js
@@ -64,6 +64,14 @@ var testCommand = function(cmd, cmdObj) {
validateErrorResponse(res, testDB.getName(), uuid, coll2.getName(), coll.getName());
assert(!testDB.getCollectionNames().includes(coll2.getName()));
+ jsTestLog("The command '" + cmd +
+ "' fails with CollectionUUIDMismatch even if the database does not exist.");
+ const nonexistentDB = testDB.getSiblingDB(testDB.getName() + '_nonexistent');
+ cmdObj[cmd] = 'nonexistent';
+ res = assert.commandFailedWithCode(nonexistentDB.runCommand(cmdObj),
+ ErrorCodes.CollectionUUIDMismatch);
+ validateErrorResponse(res, nonexistentDB.getName(), uuid, 'nonexistent', null);
+
jsTestLog("Only collections in the same database are specified by actualCollection.");
const otherDB = testDB.getSiblingDB(testDB.getName() + '_2');
assert.commandWorked(otherDB.dropDatabase());
diff --git a/src/mongo/db/catalog/drop_collection.cpp b/src/mongo/db/catalog/drop_collection.cpp
index c8849d06825..cc164c4aa0f 100644
--- a/src/mongo/db/catalog/drop_collection.cpp
+++ b/src/mongo/db/catalog/drop_collection.cpp
@@ -35,6 +35,7 @@
#include "mongo/db/audit.h"
#include "mongo/db/catalog/collection_catalog.h"
#include "mongo/db/catalog/collection_uuid_mismatch.h"
+#include "mongo/db/catalog/collection_uuid_mismatch_info.h"
#include "mongo/db/catalog/index_catalog.h"
#include "mongo/db/client.h"
#include "mongo/db/concurrency/exception_util.h"
@@ -357,7 +358,13 @@ Status _dropCollection(OperationContext* opCtx,
AutoGetDb autoDb(opCtx, collectionName.db(), MODE_IX);
auto db = autoDb.getDb();
if (!db) {
- return Status(ErrorCodes::NamespaceNotFound, "ns not found");
+ return expectedUUID
+ ? Status{CollectionUUIDMismatchInfo(collectionName.db().toString(),
+ *expectedUUID,
+ collectionName.coll().toString(),
+ boost::none),
+ "Database does not exist"}
+ : Status(ErrorCodes::NamespaceNotFound, "ns not found");
}
if (CollectionCatalog::get(opCtx)->lookupCollectionByNamespace(opCtx, collectionName)) {
diff --git a/src/mongo/s/commands/SConscript b/src/mongo/s/commands/SConscript
index 7e7e076e49d..c4bcd08df66 100644
--- a/src/mongo/s/commands/SConscript
+++ b/src/mongo/s/commands/SConscript
@@ -103,6 +103,7 @@ env.Library(
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/db/api_parameters',
'$BUILD_DIR/mongo/db/auth/auth_checks',
+ '$BUILD_DIR/mongo/db/catalog/collection_uuid_mismatch_info',
'$BUILD_DIR/mongo/db/change_stream_options_manager',
'$BUILD_DIR/mongo/db/commands/cluster_server_parameter_cmds_idl',
'$BUILD_DIR/mongo/db/commands/cluster_server_parameter_commands_invocation',
diff --git a/src/mongo/s/commands/cluster_collection_mod_cmd.cpp b/src/mongo/s/commands/cluster_collection_mod_cmd.cpp
index ecab8d581f3..f2c38f38bca 100644
--- a/src/mongo/s/commands/cluster_collection_mod_cmd.cpp
+++ b/src/mongo/s/commands/cluster_collection_mod_cmd.cpp
@@ -32,6 +32,7 @@
#include "mongo/db/auth/authorization_checks.h"
#include "mongo/db/auth/authorization_session.h"
+#include "mongo/db/catalog/collection_uuid_mismatch_info.h"
#include "mongo/db/coll_mod_gen.h"
#include "mongo/db/coll_mod_reply_validation.h"
#include "mongo/db/commands.h"
@@ -96,8 +97,17 @@ public:
"namespace"_attr = nss,
"command"_attr = redact(cmdObj));
- const auto dbInfo =
- uassertStatusOK(Grid::get(opCtx)->catalogCache()->getDatabase(opCtx, cmd.getDbName()));
+ auto swDbInfo = Grid::get(opCtx)->catalogCache()->getDatabase(opCtx, cmd.getDbName());
+ if (swDbInfo == ErrorCodes::NamespaceNotFound) {
+ uassert(CollectionUUIDMismatchInfo(cmd.getDbName().toString(),
+ *cmd.getCollectionUUID(),
+ nss.coll().toString(),
+ boost::none),
+ "Database does not exist",
+ !cmd.getCollectionUUID());
+ }
+ const auto dbInfo = uassertStatusOK(swDbInfo);
+
ShardsvrCollMod collModCommand(nss);
collModCommand.setCollModRequest(cmd.getCollModRequest());
auto cmdResponse =
diff --git a/src/mongo/s/commands/cluster_drop_collection_cmd.cpp b/src/mongo/s/commands/cluster_drop_collection_cmd.cpp
index b28d250f21c..12d3b138aaa 100644
--- a/src/mongo/s/commands/cluster_drop_collection_cmd.cpp
+++ b/src/mongo/s/commands/cluster_drop_collection_cmd.cpp
@@ -32,6 +32,7 @@
#include "mongo/base/status.h"
#include "mongo/db/auth/authorization_session.h"
+#include "mongo/db/catalog/collection_uuid_mismatch_info.h"
#include "mongo/db/commands.h"
#include "mongo/db/drop_gen.h"
#include "mongo/db/operation_context.h"
@@ -118,6 +119,13 @@ public:
// Ensure our reply conforms to the IDL-defined reply structure.
return DropReply::parse({"drop"}, resultObj);
} catch (const ExceptionFor<ErrorCodes::NamespaceNotFound>&) {
+ uassert(CollectionUUIDMismatchInfo(request().getDbName().toString(),
+ *request().getCollectionUUID(),
+ request().getNamespace().coll().toString(),
+ boost::none),
+ "Database does not exist",
+ !request().getCollectionUUID());
+
// If the namespace isn't found, treat the drop as a success but inform about the
// failure.
DropReply reply;
diff --git a/src/mongo/s/commands/cluster_rename_collection_cmd.cpp b/src/mongo/s/commands/cluster_rename_collection_cmd.cpp
index 6a3fec1c4d2..98584802646 100644
--- a/src/mongo/s/commands/cluster_rename_collection_cmd.cpp
+++ b/src/mongo/s/commands/cluster_rename_collection_cmd.cpp
@@ -31,6 +31,7 @@
#include "mongo/platform/basic.h"
#include "mongo/db/auth/authorization_session.h"
+#include "mongo/db/catalog/collection_uuid_mismatch_info.h"
#include "mongo/db/commands.h"
#include "mongo/db/commands/rename_collection_common.h"
#include "mongo/db/commands/rename_collection_gen.h"
@@ -94,7 +95,16 @@ public:
renameCollRequest.setRenameCollectionRequest(renameCollReq);
auto catalogCache = Grid::get(opCtx)->catalogCache();
- const auto dbInfo = uassertStatusOK(catalogCache->getDatabase(opCtx, fromNss.db()));
+ auto swDbInfo = Grid::get(opCtx)->catalogCache()->getDatabase(opCtx, fromNss.db());
+ if (swDbInfo == ErrorCodes::NamespaceNotFound) {
+ uassert(CollectionUUIDMismatchInfo(fromNss.db().toString(),
+ *request().getCollectionUUID(),
+ fromNss.coll().toString(),
+ boost::none),
+ "Database does not exist",
+ !request().getCollectionUUID());
+ }
+ const auto dbInfo = uassertStatusOK(swDbInfo);
auto cri = uassertStatusOK(catalogCache->getCollectionRoutingInfo(opCtx, fromNss));
auto shard = uassertStatusOK(
diff --git a/src/mongo/s/query/SConscript b/src/mongo/s/query/SConscript
index ab67239ff80..90f67801d66 100644
--- a/src/mongo/s/query/SConscript
+++ b/src/mongo/s/query/SConscript
@@ -43,6 +43,7 @@ env.Library(
'cluster_query',
],
LIBDEPS_PRIVATE=[
+ '$BUILD_DIR/mongo/db/catalog/collection_uuid_mismatch_info',
'$BUILD_DIR/mongo/db/timeseries/timeseries_options',
],
)
diff --git a/src/mongo/s/query/cluster_aggregate.cpp b/src/mongo/s/query/cluster_aggregate.cpp
index b990c1c9bfc..edd41446142 100644
--- a/src/mongo/s/query/cluster_aggregate.cpp
+++ b/src/mongo/s/query/cluster_aggregate.cpp
@@ -36,6 +36,7 @@
#include "mongo/db/api_parameters.h"
#include "mongo/db/auth/authorization_session.h"
+#include "mongo/db/catalog/collection_uuid_mismatch_info.h"
#include "mongo/db/client.h"
#include "mongo/db/commands.h"
#include "mongo/db/curop.h"
@@ -327,6 +328,13 @@ Status ClusterAggregate::runAggregate(OperationContext* opCtx,
sharded_agg_helpers::getExecutionNsRoutingInfo(opCtx, namespaces.executionNss);
if (!executionNsRoutingInfoStatus.isOK()) {
+ uassert(CollectionUUIDMismatchInfo(request.getDbName().toString(),
+ *request.getCollectionUUID(),
+ request.getNamespace().coll().toString(),
+ boost::none),
+ "Database does not exist",
+ !request.getCollectionUUID());
+
if (liteParsedPipeline.startsWithCollStats()) {
uassertStatusOKWithContext(executionNsRoutingInfoStatus,
"Unable to retrieve information for $collStats stage");
diff --git a/src/mongo/s/query/cluster_find.cpp b/src/mongo/s/query/cluster_find.cpp
index 7d6f93623f9..bf0030c54c9 100644
--- a/src/mongo/s/query/cluster_find.cpp
+++ b/src/mongo/s/query/cluster_find.cpp
@@ -516,6 +516,13 @@ CursorId ClusterFind::runQuery(OperationContext* opCtx,
for (size_t retries = 1; retries <= kMaxRetries; ++retries) {
auto swCM = getCollectionRoutingInfoForTxnCmd(opCtx, query.nss());
if (swCM == ErrorCodes::NamespaceNotFound) {
+ uassert(CollectionUUIDMismatchInfo(query.nss().db().toString(),
+ *findCommand.getCollectionUUID(),
+ query.nss().coll().toString(),
+ boost::none),
+ "Database does not exist",
+ !findCommand.getCollectionUUID());
+
// If the database doesn't exist, we successfully return an empty result set without
// creating a cursor.
return CursorId(0);