diff options
-rw-r--r-- | jstests/aggregation/bugs/server18198.js | 42 | ||||
-rw-r--r-- | src/mongo/shell/collection.js | 4 |
2 files changed, 45 insertions, 1 deletions
diff --git a/jstests/aggregation/bugs/server18198.js b/jstests/aggregation/bugs/server18198.js new file mode 100644 index 00000000000..6d8d827e416 --- /dev/null +++ b/jstests/aggregation/bugs/server18198.js @@ -0,0 +1,42 @@ +// SERVER-18198 check read pref is only applied when there is no $out stage +// in aggregate shell helper +(function() { + "use strict"; + var t = db.server18198; + t.drop(); + + var mongo = db.getMongo(); + + try { + var commandsRan = []; + // hook in our patched mongo + var mockMongo = { + getSlaveOk: function() { return true; }, + runCommand: function(db, cmd, opts) { + commandsRan.push({db: db, cmd: cmd, opts: opts}); + return {ok: 1.0}; + }, + getReadPref: function() { return {mode: "secondaryPreferred"}; }, + getReadPrefMode: function() { return "secondaryPreferred"; } + }; + + db._mongo = mockMongo; + + // this query should not get a read pref + t.aggregate([{$sort: {"x" : 1}}, {$out: "foo"}]); + assert.eq(commandsRan.length, 1); + // check that it doesn't have a read preference + assert(!commandsRan[0].cmd.hasOwnProperty("$readPreference")); + + commandsRan = []; + + t.aggregate([{$sort: {"x" : 1}}]); + // check another command was run + assert.eq(commandsRan.length, 1); + // check that it has a read preference + assert(commandsRan[0].cmd.hasOwnProperty("$readPreference")); + } + finally { + db._mongo = mongo; + } +})(); diff --git a/src/mongo/shell/collection.js b/src/mongo/shell/collection.js index 6bf21087887..5ecfd01cc31 100644 --- a/src/mongo/shell/collection.js +++ b/src/mongo/shell/collection.js @@ -1272,13 +1272,15 @@ DBCollection.prototype.aggregate = function(pipeline, extraOpts) { cmd.cursor = {}; } + // in a well formed pipeline, $out must be the last stage. If it isn't then the server + // will reject the pipeline anyway. var hasOutStage = pipeline.length >= 1 && pipeline[pipeline.length - 1].hasOwnProperty("$out"); var doAgg = function(cmd) { // if we don't have an out stage, we could run on a secondary // so we need to attach readPreference return hasOutStage ? - this.runReadCommand("aggregate", cmd) : this.runCommand("aggregate", cmd); + this.runCommand("aggregate", cmd) : this.runReadCommand("aggregate", cmd); }.bind(this); var res = doAgg(cmd); |