mirror of
https://github.com/mongodb/mongo.git
synced 2024-11-30 00:56:44 +01:00
155 lines
6.5 KiB
JavaScript
155 lines
6.5 KiB
JavaScript
// Test the explain command on the primary and on secondaries:
|
|
//
|
|
// 1) Explain of read operations should work on the secondaries iff slaveOk is set.
|
|
//
|
|
// 2) Explain of write operations should
|
|
// --fail on secondaries, even if slaveOk is set,
|
|
// --succeed on primary without applying any writes.
|
|
|
|
var name = "explain_slaveok";
|
|
|
|
print("Start replica set with two nodes");
|
|
var replTest = new ReplSetTest({name: name, nodes: 2});
|
|
var nodes = replTest.startSet();
|
|
replTest.initiate();
|
|
var primary = replTest.getPrimary();
|
|
|
|
// Insert a document and let it sync to the secondary.
|
|
print("Initial sync");
|
|
primary.getDB("test").explain_slaveok.insert({a: 1});
|
|
replTest.awaitReplication();
|
|
|
|
// Check that the document is present on the primary.
|
|
assert.eq(1, primary.getDB("test").explain_slaveok.findOne({a: 1})["a"]);
|
|
|
|
// We shouldn't be able to read from the secondary with slaveOk off.
|
|
var secondary = replTest.getSecondary();
|
|
secondary.getDB("test").getMongo().setSlaveOk(false);
|
|
assert.throws(function() {
|
|
secondary.getDB("test").explain_slaveok.findOne({a: 1});
|
|
});
|
|
|
|
// With slaveOk on, we should be able to read from the secondary.
|
|
secondary.getDB("test").getMongo().setSlaveOk(true);
|
|
assert.eq(1, secondary.getDB("test").explain_slaveok.findOne({a: 1})["a"]);
|
|
|
|
//
|
|
// Test explains on primary.
|
|
//
|
|
|
|
// Explain a count on the primary.
|
|
var explainOut = primary.getDB("test").runCommand(
|
|
{explain: {count: "explain_slaveok", query: {a: 1}}, verbosity: "executionStats"});
|
|
assert.commandWorked(explainOut, "explain read op on primary");
|
|
|
|
// Explain an update on the primary.
|
|
explainOut = primary.getDB("test").runCommand({
|
|
explain: {update: "explain_slaveok", updates: [{q: {a: 1}, u: {$set: {a: 5}}}]},
|
|
verbosity: "executionStats"
|
|
});
|
|
assert.commandWorked(explainOut, "explain write op on primary");
|
|
|
|
// Plan should have an update stage at its root, reporting that it would
|
|
// modify a single document.
|
|
var stages = explainOut.executionStats.executionStages;
|
|
assert.eq("UPDATE", stages.stage);
|
|
assert.eq(1, stages.nWouldModify);
|
|
|
|
// Confirm that the document did not actually get modified on the primary
|
|
// or on the secondary.
|
|
assert.eq(1, primary.getDB("test").explain_slaveok.findOne({a: 1})["a"]);
|
|
secondary.getDB("test").getMongo().setSlaveOk(true);
|
|
assert.eq(1, secondary.getDB("test").explain_slaveok.findOne({a: 1})["a"]);
|
|
|
|
//
|
|
// Test explains on secondary.
|
|
//
|
|
|
|
// Explain a count on the secondary with slaveOk off. Should fail because
|
|
// slaveOk is required for explains on a secondary.
|
|
secondary.getDB("test").getMongo().setSlaveOk(false);
|
|
explainOut = secondary.getDB("test").runCommand(
|
|
{explain: {count: "explain_slaveok", query: {a: 1}}, verbosity: "executionStats"});
|
|
assert.commandFailed(explainOut, "explain read op on secondary, slaveOk false");
|
|
|
|
// Explain of count should succeed once slaveOk is true.
|
|
secondary.getDB("test").getMongo().setSlaveOk(true);
|
|
explainOut = secondary.getDB("test").runCommand(
|
|
{explain: {count: "explain_slaveok", query: {a: 1}}, verbosity: "executionStats"});
|
|
assert.commandWorked(explainOut, "explain read op on secondary, slaveOk true");
|
|
|
|
// Explain .find() on a secondary, setting slaveOk directly on the query.
|
|
secondary.getDB("test").getMongo().setSlaveOk(false);
|
|
assert.throws(function() {
|
|
secondary.getDB("test").explain_slaveok.explain("executionStats").find({a: 1}).finish();
|
|
});
|
|
|
|
secondary.getDB("test").getMongo().setSlaveOk(false);
|
|
explainOut = secondary.getDB("test")
|
|
.explain_slaveok.explain("executionStats")
|
|
.find({a: 1})
|
|
.addOption(DBQuery.Option.slaveOk)
|
|
.finish();
|
|
assert.commandWorked(explainOut, "explain read op on secondary, slaveOk set to true on query");
|
|
|
|
secondary.getDB("test").getMongo().setSlaveOk(true);
|
|
explainOut =
|
|
secondary.getDB("test").explain_slaveok.explain("executionStats").find({a: 1}).finish();
|
|
assert.commandWorked(explainOut, "explain .find() on secondary, slaveOk set to true");
|
|
|
|
// Explain .find() on a secondary, setting slaveOk to false with various read preferences.
|
|
var readPrefModes = ["secondary", "secondaryPreferred", "primaryPreferred", "nearest"];
|
|
readPrefModes.forEach(function(prefString) {
|
|
secondary.getDB("test").getMongo().setSlaveOk(false);
|
|
explainOut = secondary.getDB("test")
|
|
.explain_slaveok.explain("executionStats")
|
|
.find({a: 1})
|
|
.readPref(prefString)
|
|
.finish();
|
|
assert.commandWorked(
|
|
explainOut, "explain .find() on secondary, '" + prefString + "' read preference on query");
|
|
|
|
// Similarly should succeed if a read preference is set on the connection.
|
|
secondary.setReadPref(prefString);
|
|
explainOut =
|
|
secondary.getDB("test").explain_slaveok.explain("executionStats").find({a: 1}).finish();
|
|
assert.commandWorked(
|
|
explainOut,
|
|
"explain .find() on secondary, '" + prefString + "' read preference on connection");
|
|
// Unset read pref on the connection.
|
|
secondary.setReadPref();
|
|
});
|
|
|
|
// Fail explain find() on a secondary, setting slaveOk to false with read preference set to primary.
|
|
var prefStringPrimary = "primary";
|
|
secondary.getDB("test").getMongo().setSlaveOk(false);
|
|
explainOut = secondary.getDB("test").runCommand(
|
|
{explain: {find: "explain_slaveok", query: {a: 1}}, verbosity: "executionStats"});
|
|
assert.commandFailed(explainOut, "not master and slaveOk=false");
|
|
|
|
// Similarly should fail if a read preference is set on the connection.
|
|
secondary.setReadPref(prefStringPrimary);
|
|
explainOut = secondary.getDB("test").runCommand(
|
|
{explain: {find: "explain_slaveok", query: {a: 1}}, verbosity: "executionStats"});
|
|
assert.commandFailed(explainOut, "not master and slaveOk=false");
|
|
// Unset read pref on the connection.
|
|
secondary.setReadPref();
|
|
|
|
// Explain an update on the secondary with slaveOk off. Should fail because
|
|
// slaveOk is required for explains on a secondary.
|
|
secondary.getDB("test").getMongo().setSlaveOk(false);
|
|
explainOut = secondary.getDB("test").runCommand({
|
|
explain: {update: "explain_slaveok", updates: [{q: {a: 1}, u: {$set: {a: 5}}}]},
|
|
verbosity: "executionStats"
|
|
});
|
|
assert.commandFailed(explainOut, "explain write op on secondary, slaveOk false");
|
|
|
|
// Explain of the update should also fail with slaveOk on.
|
|
secondary.getDB("test").getMongo().setSlaveOk(true);
|
|
explainOut = secondary.getDB("test").runCommand({
|
|
explain: {update: "explain_slaveok", updates: [{q: {a: 1}, u: {$set: {a: 5}}}]},
|
|
verbosity: "executionStats"
|
|
});
|
|
assert.commandFailed(explainOut, "explain write op on secondary, slaveOk true");
|
|
replTest.stopSet();
|