summaryrefslogtreecommitdiff
path: root/src/mongo/shell
diff options
context:
space:
mode:
authorYoonsoo Kim <yoonsoo.kim@mongodb.com>2021-07-20 11:07:58 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-07-20 11:47:23 +0000
commit14a176dd6a3359266ac0bb79725b7cb13b7c214d (patch)
treeb43751dd9508f34f15c5fc54a15d9dfd2ddc4f03 /src/mongo/shell
parentd587a23122d5e64a828eb182bbe3f311541d89a2 (diff)
downloadmongo-14a176dd6a3359266ac0bb79725b7cb13b7c214d.tar.gz
Revert "SERVER-58566 Clean up remaining OP_QUERY code" due to a wrong author info
This reverts commit 3b293a78b0e24c5497464c3979daddfa0792bb55.
Diffstat (limited to 'src/mongo/shell')
-rw-r--r--src/mongo/shell/explain_query.js119
-rw-r--r--src/mongo/shell/mongo.js5
2 files changed, 97 insertions, 27 deletions
diff --git a/src/mongo/shell/explain_query.js b/src/mongo/shell/explain_query.js
index 453751d88de..b4935fd07d4 100644
--- a/src/mongo/shell/explain_query.js
+++ b/src/mongo/shell/explain_query.js
@@ -9,6 +9,37 @@ var DBExplainQuery = (function() {
//
/**
+ * In 2.6 and before, .explain(), .explain(false), or .explain(<falsy value>) instructed the
+ * shell to reduce the explain verbosity by removing certain fields from the output. This
+ * is implemented here for backwards compatibility.
+ */
+ function removeVerboseFields(obj) {
+ if (typeof (obj) !== "object") {
+ return;
+ }
+
+ delete obj.allPlans;
+ delete obj.oldPlan;
+ delete obj.stats;
+
+ if (typeof (obj.length) === "number") {
+ for (var i = 0; i < obj.length; i++) {
+ removeVerboseFields(obj[i]);
+ }
+ }
+
+ if (obj.shards) {
+ for (var key in obj.shards) {
+ removeVerboseFields(obj.shards[key]);
+ }
+ }
+
+ if (obj.clauses) {
+ removeVerboseFields(obj.clauses);
+ }
+ }
+
+ /**
* Many of the methods of an explain query just pass through to the underlying
* non-explained DBQuery. Use this to generate a function which calls function 'name' on
* 'destObj' and then returns this.
@@ -20,6 +51,28 @@ var DBExplainQuery = (function() {
};
}
+ /**
+ * Where possible, the explain query will be sent to the server as an explain command.
+ * However, if one of the nodes we are talking to (either a standalone or a shard in
+ * a sharded cluster) is of a version that doesn't have the explain command, we will
+ * use this function to fall back on the $explain query option.
+ */
+ function explainWithLegacyQueryOption(explainQuery) {
+ // The wire protocol version indicates that the server does not have the explain
+ // command. Add $explain to the query and send it to the server.
+ var clone = explainQuery._query.clone();
+ clone._addSpecial("$explain", true);
+ var result = clone.next();
+
+ // Remove some fields from the explain if verbosity is
+ // just "queryPlanner".
+ if ("queryPlanner" === explainQuery._verbosity) {
+ removeVerboseFields(result);
+ }
+
+ return Explainable.throwOrReturn(result);
+ }
+
function constructor(query, verbosity) {
//
// Private vars.
@@ -83,35 +136,47 @@ var DBExplainQuery = (function() {
// Explain always gets pretty printed.
this._query._prettyShell = true;
- // Convert this explain query into an explain command, and send the command to
- // the server.
- var innerCmd;
- if (this._isCount) {
- // True means to always apply the skip and limit values.
- innerCmd = this._query._convertToCountCmd(this._applySkipLimit);
+ if (this._mongo.hasExplainCommand()) {
+ // The wire protocol version indicates that the server has the explain command.
+ // Convert this explain query into an explain command, and send the command to
+ // the server.
+ var innerCmd;
+ if (this._isCount) {
+ // True means to always apply the skip and limit values.
+ innerCmd = this._query._convertToCountCmd(this._applySkipLimit);
+ } else {
+ var canAttachReadPref = false;
+ innerCmd = this._query._convertToCommand(canAttachReadPref);
+ }
+
+ var explainCmd = {explain: innerCmd};
+ explainCmd["verbosity"] = this._verbosity;
+ // If "maxTimeMS" is set on innerCmd, it needs to be propagated to the top-level
+ // of explainCmd so that it has the intended effect.
+ if (innerCmd.hasOwnProperty("maxTimeMS")) {
+ explainCmd.maxTimeMS = innerCmd.maxTimeMS;
+ }
+
+ var explainDb = this._query._db;
+
+ if ("$readPreference" in this._query._query) {
+ var prefObj = this._query._query.$readPreference;
+ explainCmd = explainDb._attachReadPreferenceToCommand(explainCmd, prefObj);
+ }
+
+ var explainResult =
+ explainDb.runReadCommand(explainCmd, null, this._query._options);
+
+ if (!explainResult.ok && explainResult.code === ErrorCodes.CommandNotFound) {
+ // One of the shards doesn't have the explain command available. Retry using
+ // the legacy $explain format, which should be supported by all shards.
+ return explainWithLegacyQueryOption(this);
+ }
+
+ return Explainable.throwOrReturn(explainResult);
} else {
- var canAttachReadPref = false;
- innerCmd = this._query._convertToCommand(canAttachReadPref);
+ return explainWithLegacyQueryOption(this);
}
-
- var explainCmd = {explain: innerCmd};
- explainCmd["verbosity"] = this._verbosity;
- // If "maxTimeMS" is set on innerCmd, it needs to be propagated to the top-level
- // of explainCmd so that it has the intended effect.
- if (innerCmd.hasOwnProperty("maxTimeMS")) {
- explainCmd.maxTimeMS = innerCmd.maxTimeMS;
- }
-
- var explainDb = this._query._db;
-
- if ("$readPreference" in this._query._query) {
- var prefObj = this._query._query.$readPreference;
- explainCmd = explainDb._attachReadPreferenceToCommand(explainCmd, prefObj);
- }
-
- var explainResult = explainDb.runReadCommand(explainCmd, null, this._query._options);
-
- return Explainable.throwOrReturn(explainResult);
};
this.next = function() {
diff --git a/src/mongo/shell/mongo.js b/src/mongo/shell/mongo.js
index 7146fd8670a..cf05337eead 100644
--- a/src/mongo/shell/mongo.js
+++ b/src/mongo/shell/mongo.js
@@ -418,6 +418,11 @@ connect = function(url, user, pass, apiParameters) {
return db;
};
+Mongo.prototype.hasExplainCommand = function() {
+ var hasExplain = (this.getMinWireVersion() <= 3 && 3 <= this.getMaxWireVersion());
+ return hasExplain;
+};
+
//
// Write Concern can be set at the connection level, and is used for all write operations unless
// overridden at the collection level.