Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions jstests/aggregation/bugs/explain_options_helper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Test that the explain helper does not modify the options document passed to it.
// This test was designed to reproduce SERVER-32300".

(function() {
"use strict";

const coll = db.explain_options;
coll.drop();

for (let i = 0; i < 10; ++i) {
assert.writeOK(coll.insert({_id: i}));
}

const collation = {collation: {locale: "zh", backwards: false}};

const firstResults = coll.aggregate([{$sort: {_id: 1}}], collation).toArray();
// Issue an explain in order to verify that 'collation' is not modified to include the explain
// flag.
assert.commandWorked(coll.explain().aggregate([], collation));

const secondResults = coll.aggregate([{$sort: {_id: 1}}], collation).toArray();
// Assert that the result didn't change after an explain helper is issued.
assert.eq(firstResults, secondResults);
}());
12 changes: 6 additions & 6 deletions src/mongo/shell/explainable.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,22 +100,22 @@ var Explainable = (function() {
}

// Add the explain option.
extraOpts = extraOpts || {};
let extraOptsCopy = Object.extend({}, (extraOpts || {}));

// For compatibility with 3.4 and older versions, when the verbosity is "queryPlanner",
// we use the explain option to the aggregate command. Otherwise we issue an explain
// command wrapping the agg command, which is supported by newer versions of the server.
if (this._verbosity === "queryPlanner") {
extraOpts.explain = true;
return this._collection.aggregate(pipeline, extraOpts);
extraOptsCopy.explain = true;
return this._collection.aggregate(pipeline, extraOptsCopy);
} else {
// The aggregate command requires a cursor field.
if (!extraOpts.hasOwnProperty("cursor")) {
extraOpts = Object.extend(extraOpts, {cursor: {}});
if (!extraOptsCopy.hasOwnProperty("cursor")) {
extraOptsCopy = Object.extend(extraOptsCopy, {cursor: {}});
}

let aggCmd = Object.extend(
{"aggregate": this._collection.getName(), "pipeline": pipeline}, extraOpts);
{"aggregate": this._collection.getName(), "pipeline": pipeline}, extraOptsCopy);
let explainCmd = {"explain": aggCmd, "verbosity": this._verbosity};
let explainResult = this._collection.runReadCommand(explainCmd);
return throwOrReturn(explainResult);
Expand Down