diff options
author | Yoonsoo Kim <yoonsoo.kim@mongodb.com> | 2021-07-20 11:07:58 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-07-20 11:47:23 +0000 |
commit | 14a176dd6a3359266ac0bb79725b7cb13b7c214d (patch) | |
tree | b43751dd9508f34f15c5fc54a15d9dfd2ddc4f03 /src/mongo/shell | |
parent | d587a23122d5e64a828eb182bbe3f311541d89a2 (diff) | |
download | mongo-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.js | 119 | ||||
-rw-r--r-- | src/mongo/shell/mongo.js | 5 |
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. |