summaryrefslogtreecommitdiff
path: root/src/mongo/db/commands/explain_cmd.cpp
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2014-09-03 16:39:56 -0400
committerDavid Storch <david.storch@10gen.com>2014-09-11 15:18:48 -0400
commitf5f42d6c684b8e779aef6889b800235d7417afcb (patch)
tree489e7394d816246b1a8496beaf5919c34fb81ca4 /src/mongo/db/commands/explain_cmd.cpp
parent3e5710a29505883143feb0b0883321830c989820 (diff)
downloadmongo-f5f42d6c684b8e779aef6889b800235d7417afcb.tar.gz
SERVER-14101 explain for update
Diffstat (limited to 'src/mongo/db/commands/explain_cmd.cpp')
-rw-r--r--src/mongo/db/commands/explain_cmd.cpp39
1 files changed, 35 insertions, 4 deletions
diff --git a/src/mongo/db/commands/explain_cmd.cpp b/src/mongo/db/commands/explain_cmd.cpp
index a895769453f..5fc492edb4d 100644
--- a/src/mongo/db/commands/explain_cmd.cpp
+++ b/src/mongo/db/commands/explain_cmd.cpp
@@ -30,10 +30,12 @@
#include "mongo/db/commands/explain_cmd.h"
+#include "mongo/client/dbclientinterface.h"
#include "mongo/db/catalog/database.h"
#include "mongo/db/client.h"
#include "mongo/db/commands.h"
#include "mongo/db/query/explain.h"
+#include "mongo/db/repl/repl_coordinator_global.h"
#include "mongo/util/mongoutils/str.h"
namespace mongo {
@@ -65,6 +67,14 @@ namespace mongo {
string& errmsg,
BSONObjBuilder& result,
bool fromRepl) {
+ // Should never get explain commands issued from replication.
+ if (fromRepl) {
+ Status commandStat(ErrorCodes::IllegalOperation,
+ "explain command should not be from repl");
+ appendCommandStatus(result, commandStat);
+ return false;
+ }
+
// Get the verbosity.
Explain::Verbosity verbosity = Explain::QUERY_PLANNER;
if (!cmdObj["verbosity"].eoo()) {
@@ -79,14 +89,18 @@ namespace mongo {
verbosity = Explain::FULL;
}
else if (!mongoutils::str::equals(verbStr, "queryPlanner")) {
- errmsg = "verbosity string must be one of "
- "{'queryPlanner', 'executionStats', 'allPlansExecution'}";
- return false;
+ Status commandStat(ErrorCodes::BadValue,
+ "verbosity string must be one of "
+ "{'queryPlanner', 'executionStats', 'allPlansExecution'}");
+ appendCommandStatus(result, commandStat);
+ return false;
}
}
if (Object != cmdObj.firstElement().type()) {
- errmsg = "explain command requires a nested object";
+ Status commandStat(ErrorCodes::BadValue,
+ "explain command requires a nested object");
+ appendCommandStatus(result, commandStat);
return false;
}
@@ -101,6 +115,23 @@ namespace mongo {
return appendCommandStatus(result, explainStatus);
}
+ // Check whether the child command is allowed to run here. TODO: this logic is
+ // copied from Command::execCommand and should be abstracted. Until then, make
+ // sure to keep it up to date.
+ repl::ReplicationCoordinator* replCoord = repl::getGlobalReplicationCoordinator();
+ bool canRunHere =
+ replCoord->canAcceptWritesForDatabase(dbname) ||
+ commToExplain->slaveOk() ||
+ (commToExplain->slaveOverrideOk() && (options & QueryOption_SlaveOk));
+
+ if (!canRunHere) {
+ mongoutils::str::stream ss;
+ ss << "Explain's child command cannot run on this node. "
+ << "Are you explaining a write command on a secondary?";
+ appendCommandStatus(result, false, ss);
+ return false;
+ }
+
// Actually call the nested command's explain(...) method.
Status explainStatus = commToExplain->explain(txn, dbname, explainObj, verbosity, &result);
if (!explainStatus.isOK()) {