summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorA. Jesse Jiryu Davis <jesse@mongodb.com>2021-02-09 15:06:07 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-02-09 22:47:45 +0000
commitfcb69334e15e32049a45ebdcc7d2988acf441f5e (patch)
tree8211c18a65852f1d6b7c4701b9a4264a365f93b7 /src/mongo/db
parent4a732d685ffa7c29e541c5ef6fe41751c9227d18 (diff)
downloadmongo-fcb69334e15e32049a45ebdcc7d2988acf441f5e.tar.gz
SERVER-52542 Convert dropIndexes to IDL
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/SConscript1
-rw-r--r--src/mongo/db/catalog/drop_indexes.cpp242
-rw-r--r--src/mongo/db/catalog/drop_indexes.h18
-rw-r--r--src/mongo/db/commands.h26
-rw-r--r--src/mongo/db/commands/drop_indexes.cpp54
-rw-r--r--src/mongo/db/commands/set_feature_compatibility_version_command.cpp16
-rw-r--r--src/mongo/db/drop_indexes.idl68
-rw-r--r--src/mongo/db/repl/oplog.cpp12
8 files changed, 236 insertions, 201 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index ca823f10c88..1f472114232 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -577,6 +577,7 @@ env.Library(
'commands.cpp',
'drop.idl',
'drop_database.idl',
+ 'drop_indexes.idl',
'list_collections.idl',
'list_indexes.idl',
],
diff --git a/src/mongo/db/catalog/drop_indexes.cpp b/src/mongo/db/catalog/drop_indexes.cpp
index 93bc44b3a0f..49b08b38b65 100644
--- a/src/mongo/db/catalog/drop_indexes.cpp
+++ b/src/mongo/db/catalog/drop_indexes.cpp
@@ -33,6 +33,8 @@
#include "mongo/db/catalog/drop_indexes.h"
+#include <boost/algorithm/string/join.hpp>
+
#include "mongo/db/catalog/index_catalog.h"
#include "mongo/db/client.h"
#include "mongo/db/concurrency/write_conflict_exception.h"
@@ -102,19 +104,17 @@ Status checkReplState(OperationContext* opCtx,
*/
StatusWith<const IndexDescriptor*> getDescriptorByKeyPattern(OperationContext* opCtx,
const IndexCatalog* indexCatalog,
- const BSONElement& keyPattern) {
+ const BSONObj& keyPattern) {
const bool includeUnfinished = true;
std::vector<const IndexDescriptor*> indexes;
- indexCatalog->findIndexesByKeyPattern(
- opCtx, keyPattern.embeddedObject(), includeUnfinished, &indexes);
+ indexCatalog->findIndexesByKeyPattern(opCtx, keyPattern, includeUnfinished, &indexes);
if (indexes.empty()) {
return Status(ErrorCodes::IndexNotFound,
- str::stream()
- << "can't find index with key: " << keyPattern.embeddedObject());
+ str::stream() << "can't find index with key: " << keyPattern);
} else if (indexes.size() > 1) {
return Status(ErrorCodes::AmbiguousIndexKeyPattern,
- str::stream() << indexes.size() << " indexes found for key: "
- << keyPattern.embeddedObject() << ", identify by name instead."
+ str::stream() << indexes.size() << " indexes found for key: " << keyPattern
+ << ", identify by name instead."
<< " Conflicting indexes: " << indexes[0]->infoObj() << ", "
<< indexes[1]->infoObj());
}
@@ -143,28 +143,28 @@ StatusWith<const IndexDescriptor*> getDescriptorByKeyPattern(OperationContext* o
*/
StatusWith<std::vector<std::string>> getIndexNames(OperationContext* opCtx,
const CollectionPtr& collection,
- const BSONElement& indexElem) {
+ const IndexArgument& index) {
invariant(opCtx->lockState()->isCollectionLockedForMode(collection->ns(), MODE_IX));
- std::vector<std::string> indexNames;
- if (indexElem.type() == String) {
- std::string indexToAbort = indexElem.valuestr();
- indexNames.push_back(indexToAbort);
- } else if (indexElem.type() == Object) {
- auto swDescriptor =
- getDescriptorByKeyPattern(opCtx, collection->getIndexCatalog(), indexElem);
- if (!swDescriptor.isOK()) {
- return swDescriptor.getStatus();
- }
- indexNames.push_back(swDescriptor.getValue()->indexName());
- } else if (indexElem.type() == Array) {
- for (auto indexNameElem : indexElem.Array()) {
- invariant(indexNameElem.type() == String);
- indexNames.push_back(indexNameElem.valuestr());
- }
- }
-
- return indexNames;
+ return stdx::visit(
+ [&](auto&& arg) -> StatusWith<std::vector<std::string>> {
+ using T = std::decay_t<decltype(arg)>;
+ if constexpr (std::is_same_v<T, std::string>) {
+ return {{arg}};
+ } else if constexpr (std::is_same_v<T, std::vector<std::string>>) {
+ return arg;
+ } else if constexpr (std::is_same_v<T, BSONObj>) {
+ auto swDescriptor =
+ getDescriptorByKeyPattern(opCtx, collection->getIndexCatalog(), arg);
+ if (!swDescriptor.isOK()) {
+ return swDescriptor.getStatus();
+ }
+ return {{swDescriptor.getValue()->indexName()}};
+ } else {
+ MONGO_UNREACHABLE;
+ }
+ },
+ index);
}
/**
@@ -245,14 +245,14 @@ std::vector<UUID> abortActiveIndexBuilders(OperationContext* opCtx,
return abortIndexBuildByIndexNames(opCtx, collectionUUID, indexNames);
}
-Status dropReadyIndexes(OperationContext* opCtx,
- Collection* collection,
- const std::vector<std::string>& indexNames,
- BSONObjBuilder* anObjBuilder) {
+void dropReadyIndexes(OperationContext* opCtx,
+ Collection* collection,
+ const std::vector<std::string>& indexNames,
+ DropIndexesReply* reply) {
invariant(opCtx->lockState()->isCollectionLockedForMode(collection->ns(), MODE_X));
if (indexNames.empty()) {
- return Status::OK();
+ return;
}
IndexCatalog* indexCatalog = collection->getIndexCatalog();
@@ -266,23 +266,19 @@ Status dropReadyIndexes(OperationContext* opCtx,
desc->infoObj());
});
- anObjBuilder->append("msg", "non-_id indexes dropped for collection");
- return Status::OK();
+ reply->setMsg("non-_id indexes dropped for collection"_sd);
+ return;
}
bool includeUnfinished = true;
for (const auto& indexName : indexNames) {
auto desc = indexCatalog->findIndexByName(opCtx, indexName, includeUnfinished);
if (!desc) {
- return Status(ErrorCodes::IndexNotFound,
- str::stream() << "index not found with name [" << indexName << "]");
- }
- Status status = dropIndexByDescriptor(opCtx, collection, indexCatalog, desc);
- if (!status.isOK()) {
- return status;
+ uasserted(ErrorCodes::IndexNotFound,
+ str::stream() << "index not found with name [" << indexName << "]");
}
+ uassertStatusOK(dropIndexByDescriptor(opCtx, collection, indexCatalog, desc));
}
- return Status::OK();
}
void assertMovePrimaryInProgress(OperationContext* opCtx, const NamespaceString& ns) {
@@ -314,55 +310,45 @@ void assertMovePrimaryInProgress(OperationContext* opCtx, const NamespaceString&
} // namespace
-Status dropIndexes(OperationContext* opCtx,
- const NamespaceString& nss,
- const BSONObj& cmdObj,
- BSONObjBuilder* result) {
+DropIndexesReply dropIndexes(OperationContext* opCtx,
+ const NamespaceString& nss,
+ const IndexArgument& index) {
// We only need to hold an intent lock to send abort signals to the active index builder(s) we
// intend to abort.
boost::optional<AutoGetCollection> collection;
collection.emplace(opCtx, nss, MODE_IX);
Database* db = collection->getDb();
- Status status = checkView(opCtx, nss, db, collection->getCollection());
- if (!status.isOK()) {
- return status;
- }
-
+ uassertStatusOK(checkView(opCtx, nss, db, collection->getCollection()));
const UUID collectionUUID = (*collection)->uuid();
const NamespaceStringOrUUID dbAndUUID = {nss.db().toString(), collectionUUID};
-
- status = checkReplState(opCtx, dbAndUUID, collection->getCollection());
- if (!status.isOK()) {
- return status;
- }
-
+ uassertStatusOK(checkReplState(opCtx, dbAndUUID, collection->getCollection()));
if (!serverGlobalParams.quiet.load()) {
LOGV2(51806,
"CMD: dropIndexes",
"namespace"_attr = nss,
"uuid"_attr = collectionUUID,
- "indexes"_attr = cmdObj[kIndexFieldName].toString(false));
+ "indexes"_attr = stdx::visit(
+ [](auto&& arg) -> std::string {
+ using T = std::decay_t<decltype(arg)>;
+ if constexpr (std::is_same_v<T, std::string>) {
+ return arg;
+ } else if constexpr (std::is_same_v<T, std::vector<std::string>>) {
+ return boost::algorithm::join(arg, ",");
+ } else if constexpr (std::is_same_v<T, BSONObj>) {
+ return arg.toString();
+ } else {
+ MONGO_UNREACHABLE;
+ }
+ },
+ index));
}
- result->appendNumber("nIndexesWas", (*collection)->getIndexCatalog()->numIndexesTotal(opCtx));
-
- // Validate basic user input.
- BSONElement indexElem = cmdObj.getField(kIndexFieldName);
- const bool isWildcard = indexElem.type() == String && indexElem.String() == "*";
-
- // If an Array was passed in, verify that all the elements are of type String.
- if (indexElem.type() == Array) {
- for (auto indexNameElem : indexElem.Array()) {
- if (indexNameElem.type() != String) {
- return Status(ErrorCodes::TypeMismatch,
- str::stream()
- << "dropIndexes " << (*collection)->ns() << " (" << collectionUUID
- << ") failed to drop multiple indexes "
- << indexElem.toString(false) << ": index name must be a string");
- }
- }
- }
+ DropIndexesReply reply;
+ reply.setNIndexesWas((*collection)->getIndexCatalog()->numIndexesTotal(opCtx));
+
+ const bool isWildcard =
+ stdx::holds_alternative<std::string>(index) && stdx::get<std::string>(index) == "*";
IndexBuildsCoordinator* indexBuildsCoord = IndexBuildsCoordinator::get(opCtx);
@@ -372,22 +358,18 @@ Status dropIndexes(OperationContext* opCtx,
std::vector<UUID> abortedIndexBuilders;
std::vector<std::string> indexNames;
while (true) {
- auto swIndexNames = getIndexNames(opCtx, collection->getCollection(), indexElem);
- if (!swIndexNames.isOK()) {
- return swIndexNames.getStatus();
- }
-
- indexNames = swIndexNames.getValue();
+ indexNames = uassertStatusOK(getIndexNames(opCtx, collection->getCollection(), index));
// Copy the namespace and UUID before dropping locks.
auto collUUID = (*collection)->uuid();
auto collNs = (*collection)->ns();
- // Release locks before aborting index builds. The helper will acquire locks on our behalf.
+ // Release locks before aborting index builds. The helper will acquire locks on our
+ // behalf.
collection = boost::none;
- // Send the abort signal to any index builders that match the users request. Waits until all
- // aborted builders complete.
+ // Send the abort signal to any index builders that match the users request. Waits until
+ // all aborted builders complete.
auto justAborted = abortActiveIndexBuilders(opCtx, collNs, collUUID, indexNames);
abortedIndexBuilders.insert(
abortedIndexBuilders.end(), justAborted.begin(), justAborted.end());
@@ -397,28 +379,25 @@ Status dropIndexes(OperationContext* opCtx,
hangAfterAbortingIndexes.pauseWhileSet();
}
- // Abandon the snapshot as the index catalog will compare the in-memory state to the disk
- // state, which may have changed when we released the lock temporarily.
+ // Abandon the snapshot as the index catalog will compare the in-memory state to the
+ // disk state, which may have changed when we released the lock temporarily.
opCtx->recoveryUnit()->abandonSnapshot();
- // Take an exclusive lock on the collection now to be able to perform index catalog writes
- // when removing ready indexes from disk.
+ // Take an exclusive lock on the collection now to be able to perform index catalog
+ // writes when removing ready indexes from disk.
collection.emplace(opCtx, dbAndUUID, MODE_X);
db = collection->getDb();
if (!*collection) {
- return Status(ErrorCodes::NamespaceNotFound,
- str::stream()
- << "Collection '" << nss << "' with UUID " << dbAndUUID.uuid()
- << " in database " << dbAndUUID.db() << " does not exist.");
+ uasserted(ErrorCodes::NamespaceNotFound,
+ str::stream() << "Collection '" << nss << "' with UUID " << dbAndUUID.uuid()
+ << " in database " << dbAndUUID.db() << " does not exist.");
}
- status = checkReplState(opCtx, dbAndUUID, collection->getCollection());
- if (!status.isOK()) {
- return status;
- }
+ uassertStatusOK(checkReplState(opCtx, dbAndUUID, collection->getCollection()));
- // Check to see if a new index build was started that the caller requested to be aborted.
+ // Check to see if a new index build was started that the caller requested to be
+ // aborted.
bool abortAgain = false;
if (isWildcard) {
abortAgain = indexBuildsCoord->inProgForCollection(collectionUUID);
@@ -435,15 +414,15 @@ Status dropIndexes(OperationContext* opCtx,
// Drop any ready indexes that were created while we yielded our locks while aborting using
// similar index specs.
if (!isWildcard && !abortedIndexBuilders.empty()) {
- return writeConflictRetry(opCtx, "dropIndexes", dbAndUUID.toString(), [&] {
+ writeConflictRetry(opCtx, "dropIndexes", dbAndUUID.toString(), [&] {
WriteUnitOfWork wuow(opCtx);
// This is necessary to check shard version.
OldClientContext ctx(opCtx, (*collection)->ns().ns());
- // Iterate through all the aborted indexes and drop any indexes that are ready in the
- // index catalog. This would indicate that while we yielded our locks during the abort
- // phase, a new identical index was created.
+ // Iterate through all the aborted indexes and drop any indexes that are ready in
+ // the index catalog. This would indicate that while we yielded our locks during the
+ // abort phase, a new identical index was created.
auto indexCatalog = collection->getWritableCollection()->getIndexCatalog();
const bool includeUnfinished = false;
for (const auto& indexName : indexNames) {
@@ -453,21 +432,19 @@ Status dropIndexes(OperationContext* opCtx,
continue;
}
- Status status =
- dropIndexByDescriptor(opCtx, collection->getCollection(), indexCatalog, desc);
- if (!status.isOK()) {
- return status;
- }
+ uassertStatusOK(
+ dropIndexByDescriptor(opCtx, collection->getCollection(), indexCatalog, desc));
}
wuow.commit();
- return Status::OK();
});
+
+ return reply;
}
if (!abortedIndexBuilders.empty()) {
- // All the index builders were sent the abort signal, remove all the remaining indexes in
- // the index catalog.
+ // All the index builders were sent the abort signal, remove all the remaining indexes
+ // in the index catalog.
invariant(isWildcard);
invariant(indexNames.size() == 1);
invariant(indexNames.front() == "*");
@@ -478,34 +455,28 @@ Status dropIndexes(OperationContext* opCtx,
IndexBuildsCoordinator::get(opCtx)->assertNoIndexBuildInProgForCollection(collectionUUID);
}
- return writeConflictRetry(
- opCtx, "dropIndexes", dbAndUUID.toString(), [opCtx, &collection, &indexNames, result] {
+ writeConflictRetry(
+ opCtx, "dropIndexes", dbAndUUID.toString(), [opCtx, &collection, &indexNames, &reply] {
WriteUnitOfWork wunit(opCtx);
// This is necessary to check shard version.
OldClientContext ctx(opCtx, (*collection)->ns().ns());
-
- // Use an empty BSONObjBuilder to avoid duplicate appends to result on retry loops.
- BSONObjBuilder tempObjBuilder;
- Status status = dropReadyIndexes(
- opCtx, collection->getWritableCollection(), indexNames, &tempObjBuilder);
- if (!status.isOK()) {
- return status;
- }
-
+ dropReadyIndexes(opCtx, collection->getWritableCollection(), indexNames, &reply);
wunit.commit();
-
- result->appendElementsUnique(
- tempObjBuilder.done()); // This append will only happen once.
- return Status::OK();
});
+
+ return reply;
}
Status dropIndexesForApplyOps(OperationContext* opCtx,
const NamespaceString& nss,
- const BSONObj& cmdObj,
- BSONObjBuilder* result) {
- return writeConflictRetry(opCtx, "dropIndexes", nss.db(), [opCtx, &nss, &cmdObj, result] {
+ const BSONObj& cmdObj) try {
+ BSONObjBuilder bob(cmdObj);
+ bob.append("$db", nss.db());
+ auto cmdObjWithDb = bob.obj();
+ auto parsed = DropIndexes::parse({"dropIndexes"}, cmdObjWithDb);
+
+ return writeConflictRetry(opCtx, "dropIndexes", nss.db(), [opCtx, &nss, &cmdObj, &parsed] {
AutoGetCollection collection(opCtx, nss, MODE_X);
// If db/collection does not exist, short circuit and return.
@@ -525,8 +496,7 @@ Status dropIndexesForApplyOps(OperationContext* opCtx,
IndexBuildsCoordinator::get(opCtx)->assertNoIndexBuildInProgForCollection(
collection->uuid());
- BSONElement indexElem = cmdObj.getField(kIndexFieldName);
- auto swIndexNames = getIndexNames(opCtx, collection.getCollection(), indexElem);
+ auto swIndexNames = getIndexNames(opCtx, collection.getCollection(), parsed.getIndex());
if (!swIndexNames.isOK()) {
return swIndexNames.getStatus();
}
@@ -536,19 +506,15 @@ Status dropIndexesForApplyOps(OperationContext* opCtx,
// This is necessary to check shard version.
OldClientContext ctx(opCtx, nss.ns());
- // Use an empty BSONObjBuilder to avoid duplicate appends to result on retry loops.
- BSONObjBuilder tempObjBuilder;
- status = dropReadyIndexes(
- opCtx, collection.getWritableCollection(), swIndexNames.getValue(), &tempObjBuilder);
- if (!status.isOK()) {
- return status;
- }
+ DropIndexesReply ignoredReply;
+ dropReadyIndexes(
+ opCtx, collection.getWritableCollection(), swIndexNames.getValue(), &ignoredReply);
wunit.commit();
-
- result->appendElementsUnique(tempObjBuilder.done()); // This append will only happen once.
return Status::OK();
});
+} catch (const DBException& exc) {
+ return exc.toStatus();
}
} // namespace mongo
diff --git a/src/mongo/db/catalog/drop_indexes.h b/src/mongo/db/catalog/drop_indexes.h
index c465f6dab52..74b90d75384 100644
--- a/src/mongo/db/catalog/drop_indexes.h
+++ b/src/mongo/db/catalog/drop_indexes.h
@@ -29,34 +29,36 @@
#include "mongo/base/status.h"
+#include "mongo/db/drop_indexes_gen.h"
+
namespace mongo {
class BSONObj;
class BSONObjBuilder;
class NamespaceString;
class OperationContext;
+using IndexArgument = stdx::variant<std::string, std::vector<std::string>, mongo::BSONObj>;
+
/**
* Drops one or more ready indexes, or aborts a single index builder from the "nss" collection that
- * matches the caller's "cmdObj" input. Populates "result" with some statistics about the operation.
+ * matches the caller's "index" input.
*
- * "cmdObj" must have a field named "index" that has one of the following as its value:
+ * The "index" field may be:
* 1) "*" <-- Aborts all index builders and drops all ready indexes except the _id index.
* 2) "indexName" <-- Aborts an index builder or drops a ready index with the given name.
* 3) { keyPattern } <-- Aborts an index builder or drops a ready index with a matching key pattern.
* 4) ["indexName1", ..., "indexNameN"] <-- Aborts an index builder or drops ready indexes that
* match the given names.
*/
-Status dropIndexes(OperationContext* opCtx,
- const NamespaceString& nss,
- const BSONObj& cmdObj,
- BSONObjBuilder* result);
+DropIndexesReply dropIndexes(OperationContext* opCtx,
+ const NamespaceString& nss,
+ const IndexArgument& index);
/**
* Same behaviour as "dropIndexes" but only drops ready indexes.
*/
Status dropIndexesForApplyOps(OperationContext* opCtx,
const NamespaceString& nss,
- const BSONObj& cmdObj,
- BSONObjBuilder* result);
+ const BSONObj& cmdObj);
} // namespace mongo
diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h
index 2d3df2eb106..813c5397ab2 100644
--- a/src/mongo/db/commands.h
+++ b/src/mongo/db/commands.h
@@ -930,6 +930,23 @@ public:
}
};
+namespace {
+// Used in BasicCommandWithRequestParser below.
+template <typename T, typename = int>
+struct CommandAlias {
+ // An empty alias is equivalent to no alias, see CommandRegistry::registerCommand.
+ static constexpr StringData kAlias = ""_sd;
+};
+
+template <typename T>
+struct CommandAlias<T, decltype((void)T::kCommandAlias, 0)> {
+ static constexpr StringData kAlias = T::kCommandAlias;
+};
+
+template <typename T>
+constexpr StringData command_alias_v = CommandAlias<T>::kAlias;
+} // namespace
+
/**
* A CRTP base class for BasicCommandWithRequestParser, which simplifies writing commands that
* accept requests generated by IDL to enforce API versioning and to overcome the complexity
@@ -952,7 +969,8 @@ public:
*
* which enables it to be parsed as an IDL command.
*
- * - a 'constexpr StringData kCommandName' member.
+ * - a 'static constexpr StringData kCommandName' member.
+ * - (optional) a 'static constexpr StringData kCommandAlias' member.
*
* - validateResult: that has a custom logic to validate the result BSON object
* to enforce API versioning.
@@ -961,9 +979,9 @@ public:
template <typename Derived>
class BasicCommandWithRequestParser : public BasicCommandWithReplyBuilderInterface {
protected:
- // Commands that only have a single name don't need to define any constructors.
BasicCommandWithRequestParser()
- : BasicCommandWithReplyBuilderInterface(Derived::Request::kCommandName) {}
+ : BasicCommandWithReplyBuilderInterface(Derived::Request::kCommandName,
+ command_alias_v<typename Derived::Request>) {}
bool runWithReplyBuilder(OperationContext* opCtx,
const std::string& db,
@@ -1003,7 +1021,7 @@ protected:
auto wcStatus = getWriteConcernStatusFromCommandResult(resultObj);
if (!wcStatus.isOK()) {
if (wcStatus.code() == ErrorCodes::TypeMismatch) {
- // Result has "writeConcerError" field but it is not valid wce object.
+ // Result has "writeConcernError" field but it is not valid wce object.
uassertStatusOK(wcStatus);
}
}
diff --git a/src/mongo/db/commands/drop_indexes.cpp b/src/mongo/db/commands/drop_indexes.cpp
index 7ddcfcbab10..9a4ef95c51f 100644
--- a/src/mongo/db/commands/drop_indexes.cpp
+++ b/src/mongo/db/commands/drop_indexes.cpp
@@ -34,6 +34,7 @@
#include <string>
#include <vector>
+#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/catalog/collection.h"
#include "mongo/db/catalog/database.h"
#include "mongo/db/catalog/drop_indexes.h"
@@ -45,6 +46,7 @@
#include "mongo/db/concurrency/write_conflict_exception.h"
#include "mongo/db/curop.h"
#include "mongo/db/db_raii.h"
+#include "mongo/db/drop_indexes_gen.h"
#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/index_builds_coordinator.h"
#include "mongo/db/op_observer.h"
@@ -65,46 +67,38 @@ using std::vector;
MONGO_FAIL_POINT_DEFINE(reIndexCrashAfterDrop);
-/* "dropIndexes" is now the preferred form - "deleteIndexes" deprecated */
-class CmdDropIndexes : public BasicCommand {
+class CmdDropIndexes : public DropIndexesCmdVersion1Gen<CmdDropIndexes> {
public:
- const std::set<std::string>& apiVersions() const {
- return kApiVersions1;
- }
-
AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
return AllowedOnSecondary::kNever;
}
-
- virtual bool supportsWriteConcern(const BSONObj& cmd) const override {
- return true;
- }
-
bool collectsResourceConsumptionMetrics() const override {
return true;
}
-
std::string help() const override {
return "drop indexes for a collection";
}
- virtual void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) const {
- ActionSet actions;
- actions.addAction(ActionType::dropIndex);
- out->push_back(Privilege(parseResourcePattern(dbname, cmdObj), actions));
- }
-
- CmdDropIndexes() : BasicCommand("dropIndexes", "deleteIndexes") {}
- bool run(OperationContext* opCtx,
- const string& dbname,
- const BSONObj& jsobj,
- BSONObjBuilder& result) {
- const NamespaceString nss = CommandHelpers::parseNsCollectionRequired(dbname, jsobj);
- uassertStatusOK(dropIndexes(opCtx, nss, jsobj, &result));
- return true;
- }
-
+ class Invocation final : public InvocationBaseGen {
+ public:
+ using InvocationBaseGen::InvocationBaseGen;
+ bool supportsWriteConcern() const final {
+ return true;
+ }
+ NamespaceString ns() const final {
+ return request().getNamespace();
+ }
+ void doCheckAuthorization(OperationContext* opCtx) const final {
+ uassert(ErrorCodes::Unauthorized,
+ str::stream() << "Not authorized to drop index(es) on collection"
+ << request().getNamespace(),
+ AuthorizationSession::get(opCtx->getClient())
+ ->isAuthorizedForActionsOnNamespace(request().getNamespace(),
+ ActionType::dropIndex));
+ }
+ Reply typedRun(OperationContext* opCtx) final {
+ return dropIndexes(opCtx, request().getNamespace(), request().getIndex());
+ }
+ };
} cmdDropIndexes;
class CmdReIndex : public ErrmsgCommandDeprecated {
diff --git a/src/mongo/db/commands/set_feature_compatibility_version_command.cpp b/src/mongo/db/commands/set_feature_compatibility_version_command.cpp
index a2c478ef871..15fe66d7c37 100644
--- a/src/mongo/db/commands/set_feature_compatibility_version_command.cpp
+++ b/src/mongo/db/commands/set_feature_compatibility_version_command.cpp
@@ -498,21 +498,11 @@ private:
continue;
}
- // Construct a dropIndexes command to drop the indexes in 'haystackIndexes'.
- BSONObjBuilder dropIndexesCmd;
- dropIndexesCmd.append("dropIndexes", collName.nss()->coll());
- BSONArrayBuilder indexNames;
+ std::vector<std::string> indexNames;
for (auto&& haystackIndex : haystackIndexes) {
- indexNames.append(haystackIndex->indexName());
+ indexNames.emplace_back(haystackIndex->indexName());
}
- dropIndexesCmd.append("index", indexNames.arr());
-
- BSONObjBuilder response; // This response is ignored.
- uassertStatusOK(
- dropIndexes(opCtx,
- *collName.nss(),
- CommandHelpers::appendMajorityWriteConcern(dropIndexesCmd.obj()),
- &response));
+ dropIndexes(opCtx, *collName.nss(), indexNames);
}
}
}
diff --git a/src/mongo/db/drop_indexes.idl b/src/mongo/db/drop_indexes.idl
new file mode 100644
index 00000000000..914688e4b15
--- /dev/null
+++ b/src/mongo/db/drop_indexes.idl
@@ -0,0 +1,68 @@
+# Copyright (C) 2021-present MongoDB, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the Server Side Public License, version 1,
+# as published by MongoDB, Inc.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# Server Side Public License for more details.
+#
+# You should have received a copy of the Server Side Public License
+# along with this program. If not, see
+# <http://www.mongodb.com/licensing/server-side-public-license>.
+#
+# As a special exception, the copyright holders give permission to link the
+# code of portions of this program with the OpenSSL library under certain
+# conditions as described in each individual source file and distribute
+# linked combinations including the program with the OpenSSL library. You
+# must comply with the Server Side Public License in all respects for
+# all of the code used other than as permitted herein. If you modify file(s)
+# with this exception, you may extend this exception to your version of the
+# file(s), but you are not obligated to do so. If you do not wish to do so,
+# delete this exception statement from your version. If you delete this
+# exception statement from all source files in the program, then also delete
+# it in the license file.
+#
+
+global:
+ cpp_namespace: "mongo"
+
+imports:
+ - "mongo/idl/basic_types.idl"
+
+structs:
+ DropIndexesReply:
+ description: Reply to the dropIndexes command
+ strict: false
+ fields:
+ nIndexesWas:
+ description: Number of indexes on the collection at start of dropIndexes command
+ (mongod only)
+ type: int
+ optional: true
+ msg:
+ description: Optional message (mongod only)
+ type: string
+ optional: true
+
+commands:
+ dropIndexes:
+ description: "Parser for the dropIndexes command"
+ command_name: dropIndexes
+ command_alias: deleteIndexes
+ namespace: concatenate_with_db
+ cpp_name: dropIndexes
+ strict: true
+ api_version: "1"
+ fields:
+ index:
+ description: An index name, or array of names, or "*" for all indexes, or an index
+ spec (an object).
+ type:
+ variant:
+ - string
+ - array<string>
+ - object
+ reply_type: DropIndexesReply
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index 126a51eae0c..251153830c5 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -910,34 +910,30 @@ const StringMap<ApplyOpMetadata> kOpsMap = {
// deleteIndex(es) is deprecated but still works as of April 10, 2015
{"deleteIndex",
{[](OperationContext* opCtx, const OplogEntry& entry, OplogApplication::Mode mode) -> Status {
- BSONObjBuilder resultWeDontCareAbout;
const auto& cmd = entry.getObject();
return dropIndexesForApplyOps(
- opCtx, extractNsFromUUID(opCtx, entry.getUuid().get()), cmd, &resultWeDontCareAbout);
+ opCtx, extractNsFromUUID(opCtx, entry.getUuid().get()), cmd);
},
{ErrorCodes::NamespaceNotFound, ErrorCodes::IndexNotFound}}},
{"deleteIndexes",
{[](OperationContext* opCtx, const OplogEntry& entry, OplogApplication::Mode mode) -> Status {
- BSONObjBuilder resultWeDontCareAbout;
const auto& cmd = entry.getObject();
return dropIndexesForApplyOps(
- opCtx, extractNsFromUUID(opCtx, entry.getUuid().get()), cmd, &resultWeDontCareAbout);
+ opCtx, extractNsFromUUID(opCtx, entry.getUuid().get()), cmd);
},
{ErrorCodes::NamespaceNotFound, ErrorCodes::IndexNotFound}}},
{"dropIndex",
{[](OperationContext* opCtx, const OplogEntry& entry, OplogApplication::Mode mode) -> Status {
- BSONObjBuilder resultWeDontCareAbout;
const auto& cmd = entry.getObject();
return dropIndexesForApplyOps(
- opCtx, extractNsFromUUID(opCtx, entry.getUuid().get()), cmd, &resultWeDontCareAbout);
+ opCtx, extractNsFromUUID(opCtx, entry.getUuid().get()), cmd);
},
{ErrorCodes::NamespaceNotFound, ErrorCodes::IndexNotFound}}},
{"dropIndexes",
{[](OperationContext* opCtx, const OplogEntry& entry, OplogApplication::Mode mode) -> Status {
- BSONObjBuilder resultWeDontCareAbout;
const auto& cmd = entry.getObject();
return dropIndexesForApplyOps(
- opCtx, extractNsFromUUID(opCtx, entry.getUuid().get()), cmd, &resultWeDontCareAbout);
+ opCtx, extractNsFromUUID(opCtx, entry.getUuid().get()), cmd);
},
{ErrorCodes::NamespaceNotFound, ErrorCodes::IndexNotFound}}},
{"renameCollection",