summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough.yml4
-rw-r--r--buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml4
-rw-r--r--buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml1
-rw-r--r--buildscripts/resmokeconfig/suites/sharded_causally_consistent_jscore_passthrough.yml2
-rw-r--r--jstests/concurrency/fsm_workloads/explain_find.js5
-rw-r--r--jstests/core/explain_shell_helpers.js6
-rw-r--r--jstests/core/find1.js56
-rw-r--r--jstests/core/or4.js173
-rw-r--r--jstests/core/profile_find.js4
-rw-r--r--jstests/core/snapshot_queries.js59
-rw-r--r--jstests/mmap_v1/explain_snapshot.js23
-rw-r--r--jstests/sharding/printShardingStatus.js2
-rw-r--r--src/mongo/db/exec/subplan.cpp5
-rw-r--r--src/mongo/db/matcher/expression_optimize_test.cpp10
-rw-r--r--src/mongo/db/query/canonical_query.cpp5
-rw-r--r--src/mongo/db/query/get_executor.cpp7
-rw-r--r--src/mongo/db/query/plan_cache.cpp5
-rw-r--r--src/mongo/db/query/plan_cache_test.cpp19
-rw-r--r--src/mongo/db/query/query_planner.cpp37
-rw-r--r--src/mongo/db/query/query_planner_params.h5
-rw-r--r--src/mongo/db/query/query_planner_test.cpp78
-rw-r--r--src/mongo/db/query/query_planner_test_fixture.cpp20
-rw-r--r--src/mongo/db/query/query_planner_test_fixture.h8
-rw-r--r--src/mongo/db/query/query_request.cpp28
-rw-r--r--src/mongo/db/query/query_request.h9
-rw-r--r--src/mongo/db/query/query_request_test.cpp42
-rw-r--r--src/mongo/dbtests/query_stage_subplan.cpp10
-rw-r--r--src/mongo/shell/explain_query.js2
-rw-r--r--src/mongo/shell/query.js9
29 files changed, 107 insertions, 531 deletions
diff --git a/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough.yml
index bd11c6383c9..2b19aa1ff61 100644
--- a/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough.yml
@@ -112,10 +112,6 @@ selector:
- jstests/core/or4.js
- jstests/core/recursion.js
- jstests/core/temp_cleanup.js
- # Tests that use $snapshot and expect documents to arrive in some implicit sort order are not
- # causally consistent.
- - jstests/core/snapshot_queries.js
- - jstests/core/find1.js
# An index drop does not necessarily cause cursors to be killed on the secondary.
- jstests/core/ord.js
# plan_cache tests does not work because they check the plan_cache on the primary while the
diff --git a/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml b/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml
index 17e9f15f0d5..29d0387caa8 100644
--- a/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml
+++ b/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml
@@ -127,10 +127,6 @@ selector:
- jstests/core/or4.js
- jstests/core/recursion.js
- jstests/core/temp_cleanup.js
- # Tests that use $snapshot and expect documents to arrive in some implicit sort order are not
- # causally consistent.
- - jstests/core/snapshot_queries.js
- - jstests/core/find1.js
# An index drop does not necessarily cause cursors to be killed on the secondary.
- jstests/core/ord.js
# plan_cache tests does not work because they check the plan_cache on the primary while the
diff --git a/buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml b/buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml
index 3e23d979685..eb9debf750c 100644
--- a/buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml
@@ -50,7 +50,6 @@ selector:
# Expect results to return in a certain order, secondaries may apply ops out of order.
- jstests/core/coveredIndex1.js
- - jstests/core/find1.js
- jstests/core/sortc.js
# Assert on the ismaster field of an isMaster response. If a primary steps down after accepting
diff --git a/buildscripts/resmokeconfig/suites/sharded_causally_consistent_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/sharded_causally_consistent_jscore_passthrough.yml
index 42d31f308c8..92f3a07be32 100644
--- a/buildscripts/resmokeconfig/suites/sharded_causally_consistent_jscore_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/sharded_causally_consistent_jscore_passthrough.yml
@@ -148,7 +148,6 @@ selector:
- jstests/core/coveredIndex1.js
- jstests/core/distinct1.js
- jstests/core/elemMatchProjection.js
- - jstests/core/find1.js
- jstests/core/find4.js
- jstests/core/find5.js
- jstests/core/fts1.js
@@ -162,7 +161,6 @@ selector:
- jstests/core/nan.js
- jstests/core/null2.js
- jstests/core/not2.js
- - jstests/core/snapshot_queries.js
- jstests/core/sorta.js
- jstests/core/sortc.js
- jstests/core/sort3.js
diff --git a/jstests/concurrency/fsm_workloads/explain_find.js b/jstests/concurrency/fsm_workloads/explain_find.js
index 3798a426d38..949dd7a43b3 100644
--- a/jstests/concurrency/fsm_workloads/explain_find.js
+++ b/jstests/concurrency/fsm_workloads/explain_find.js
@@ -47,11 +47,6 @@ var $config = extendWorkload($config, function($config, $super) {
var res = db[collName].find().maxTimeMS(2000).explain();
assertAlways.commandWorked(res);
},
- explainSnapshot: function explainSnapshot(db, collName) {
- var res = db[collName].find().snapshot().explain();
- assertAlways.commandWorked(res);
- assertWhenOwnColl(isIxscan(db, res.queryPlanner.winningPlan));
- }
},
$super.states);
diff --git a/jstests/core/explain_shell_helpers.js b/jstests/core/explain_shell_helpers.js
index ab06b8042e0..ac630008247 100644
--- a/jstests/core/explain_shell_helpers.js
+++ b/jstests/core/explain_shell_helpers.js
@@ -176,12 +176,6 @@ assert.commandWorked(explain);
explain = t.find().comment("test .comment").explain();
assert.commandWorked(explain);
-// .snapshot()
-explain = t.explain().find().snapshot().finish();
-assert.commandWorked(explain);
-explain = t.find().snapshot().explain();
-assert.commandWorked(explain);
-
// .next()
explain = t.explain().find().next();
assert.commandWorked(explain);
diff --git a/jstests/core/find1.js b/jstests/core/find1.js
deleted file mode 100644
index e43b54dd398..00000000000
--- a/jstests/core/find1.js
+++ /dev/null
@@ -1,56 +0,0 @@
-// This test makes assumptions about the order of collection scans using the snapshot query option.
-// This order can change when the collection is sharded.
-// @tags: [assumes_unsharded_collection]
-t = db.find1;
-t.drop();
-lookAtDocumentMetrics = false;
-
-// QUERY MIGRATION
-// New system is still not connected to server status
-if (db.serverStatus().metrics) {
- // var ss = db.serverStatus();
- // lookAtDocumentMetrics = ss.metrics.document != null && ss.metrics.queryExecutor.scanned !=
- // null;
-}
-
-print("lookAtDocumentMetrics: " + lookAtDocumentMetrics);
-
-if (lookAtDocumentMetrics) {
- // ignore mongos
- nscannedStart = db.serverStatus().metrics.queryExecutor.scanned;
-}
-
-t.save({a: 1, b: "hi"});
-t.save({a: 2, b: "hi"});
-
-// Basic test of .snapshot().
-assert(t.find().snapshot()[0].a == 1, ".snapshot() simple test 1");
-var q = t.findOne();
-q.c =
- "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz";
-t.save(q); // will move a:1 object to after a:2 in the file
-assert(t.find().snapshot()[0].a == 1, ".snapshot() simple test 2");
-
-assert(t.findOne({a: 1}).b != null, "A");
-assert(t.findOne({a: 1}, {a: 1}).b == null, "B");
-
-assert(t.find({a: 1})[0].b != null, "C");
-assert(t.find({a: 1}, {a: 1})[0].b == null, "D");
-assert(t.find({a: 1}, {a: 1}).sort({a: 1})[0].b == null, "D");
-
-id = t.findOne()._id;
-
-assert(t.findOne(id), "E");
-assert(t.findOne(id).a, "F");
-assert(t.findOne(id).b, "G");
-
-assert(t.findOne(id, {a: 1}).a, "H");
-assert(!t.findOne(id, {a: 1}).b, "I");
-
-assert(t.validate().valid, "not valid");
-
-if (lookAtDocumentMetrics) {
- // ignore mongos
- nscannedEnd = db.serverStatus().metrics.queryExecutor.scanned;
- assert.lte(nscannedStart + 16, nscannedEnd);
-}
diff --git a/jstests/core/or4.js b/jstests/core/or4.js
index 91876c601ab..700bb7d336f 100644
--- a/jstests/core/or4.js
+++ b/jstests/core/or4.js
@@ -2,94 +2,85 @@
// collection.
// @tags: [assumes_unsharded_collection, does_not_support_stepdowns, requires_getmore,
// requires_non_retryable_writes]
-
-t = db.jstests_or4;
-t.drop();
-
-checkArrs = function(a, b) {
- m = "[" + a + "] != [" + b + "]";
- a = eval(a);
- b = eval(b);
- assert.eq(a.length, b.length, m);
- aStr = [];
- bStr = [];
- a.forEach(function(x) {
- aStr.push(tojson(x));
- });
- b.forEach(function(x) {
- bStr.push(tojson(x));
- });
- for (i = 0; i < aStr.length; ++i) {
- assert(-1 != bStr.indexOf(aStr[i]), m);
- }
-};
-
-t.ensureIndex({a: 1});
-t.ensureIndex({b: 1});
-
-t.save({a: 2});
-t.save({b: 3});
-t.save({b: 3});
-t.save({a: 2, b: 3});
-
-assert.eq.automsg("4", "t.count( {$or:[{a:2},{b:3}]} )");
-assert.eq.automsg("2", "t.count( {$or:[{a:2},{a:2}]} )");
-
-assert.eq.automsg("2", "t.find( {} ).skip( 2 ).count( true )");
-assert.eq.automsg("2", "t.find( {$or:[{a:2},{b:3}]} ).skip( 2 ).count( true )");
-assert.eq.automsg("1", "t.find( {$or:[{a:2},{b:3}]} ).skip( 3 ).count( true )");
-
-assert.eq.automsg("2", "t.find( {} ).limit( 2 ).count( true )");
-assert.eq.automsg("1", "t.find( {$or:[{a:2},{b:3}]} ).limit( 1 ).count( true )");
-assert.eq.automsg("2", "t.find( {$or:[{a:2},{b:3}]} ).limit( 2 ).count( true )");
-assert.eq.automsg("3", "t.find( {$or:[{a:2},{b:3}]} ).limit( 3 ).count( true )");
-assert.eq.automsg("4", "t.find( {$or:[{a:2},{b:3}]} ).limit( 4 ).count( true )");
-
-t.remove({$or: [{a: 2}, {b: 3}]});
-assert.eq.automsg("0", "t.count()");
-
-t.save({b: 3});
-t.remove({$or: [{a: 2}, {b: 3}]});
-assert.eq.automsg("0", "t.count()");
-
-t.save({a: 2});
-t.save({b: 3});
-t.save({a: 2, b: 3});
-
-t.update({$or: [{a: 2}, {b: 3}]}, {$set: {z: 1}}, false, true);
-assert.eq.automsg("3", "t.count( {z:1} )");
-
-assert.eq.automsg("3", "t.find( {$or:[{a:2},{b:3}]} ).toArray().length");
-checkArrs("t.find().toArray()", "t.find( {$or:[{a:2},{b:3}]} ).toArray()");
-assert.eq.automsg("2", "t.find( {$or:[{a:2},{b:3}]} ).skip(1).toArray().length");
-
-assert.eq.automsg("3", "t.find( {$or:[{a:2},{b:3}]} ).batchSize( 2 ).toArray().length");
-
-t.save({a: 1});
-t.save({b: 4});
-t.save({a: 2});
-
-assert.eq.automsg("4", "t.find( {$or:[{a:2},{b:3}]} ).batchSize( 2 ).toArray().length");
-assert.eq.automsg("4", "t.find( {$or:[{a:2},{b:3}]} ).snapshot().toArray().length");
-
-t.save({a: 1, b: 3});
-assert.eq.automsg("4", "t.find( {$or:[{a:2},{b:3}]} ).limit(4).toArray().length");
-
-assert.eq.automsg("[1,2]", "Array.sort( t.distinct( 'a', {$or:[{a:2},{b:3}]} ) )");
-
-assert.eq.automsg(
- "[{a:2},{a:null},{a:1}]",
- "t.group( {key:{a:1}, cond:{$or:[{a:2},{b:3}]}, reduce:function( x, y ) { }, initial:{} } )");
-assert.eq.automsg(
- "5",
- "t.mapReduce( function() { emit( 'a', this.a ); }, function( key, vals ) { return vals.length; }, {out:{inline:true},query:{$or:[{a:2},{b:3}]}} ).counts.input");
-
-t.remove({});
-
-t.save({a: [1, 2]});
-assert.eq.automsg("1", "t.find( {$or:[{a:1},{a:2}]} ).toArray().length");
-assert.eq.automsg("1", "t.count( {$or:[{a:1},{a:2}]} )");
-assert.eq.automsg("1", "t.find( {$or:[{a:2},{a:1}]} ).toArray().length");
-assert.eq.automsg("1", "t.count( {$or:[{a:2},{a:1}]} )");
-
-t.remove({});
+(function() {
+ "use strict";
+
+ const coll = db.or4;
+ coll.drop();
+
+ coll.ensureIndex({a: 1});
+ coll.ensureIndex({b: 1});
+
+ assert.writeOK(coll.insert({a: 2}));
+ assert.writeOK(coll.insert({b: 3}));
+ assert.writeOK(coll.insert({b: 3}));
+ assert.writeOK(coll.insert({a: 2, b: 3}));
+
+ assert.eq(4, coll.count({$or: [{a: 2}, {b: 3}]}));
+ assert.eq(2, coll.count({$or: [{a: 2}, {a: 2}]}));
+
+ assert.eq(2, coll.find({}).skip(2).count(true));
+ assert.eq(2, coll.find({$or: [{a: 2}, {b: 3}]}).skip(2).count(true));
+ assert.eq(1, coll.find({$or: [{a: 2}, {b: 3}]}).skip(3).count(true));
+
+ assert.eq(2, coll.find({}).limit(2).count(true));
+ assert.eq(1, coll.find({$or: [{a: 2}, {b: 3}]}).limit(1).count(true));
+ assert.eq(2, coll.find({$or: [{a: 2}, {b: 3}]}).limit(2).count(true));
+ assert.eq(3, coll.find({$or: [{a: 2}, {b: 3}]}).limit(3).count(true));
+ assert.eq(4, coll.find({$or: [{a: 2}, {b: 3}]}).limit(4).count(true));
+
+ coll.remove({$or: [{a: 2}, {b: 3}]});
+ assert.eq(0, coll.count());
+
+ assert.writeOK(coll.insert({b: 3}));
+ coll.remove({$or: [{a: 2}, {b: 3}]});
+ assert.eq(0, coll.count());
+
+ assert.writeOK(coll.insert({a: 2}));
+ assert.writeOK(coll.insert({b: 3}));
+ assert.writeOK(coll.insert({a: 2, b: 3}));
+
+ coll.update({$or: [{a: 2}, {b: 3}]}, {$set: {z: 1}}, false, true);
+ assert.eq(3, coll.count({z: 1}));
+
+ assert.eq(3, coll.find({$or: [{a: 2}, {b: 3}]}).toArray().length);
+ assert.eq(coll.find().sort({_id: 1}).toArray(),
+ coll.find({$or: [{a: 2}, {b: 3}]}).sort({_id: 1}).toArray());
+ assert.eq(2, coll.find({$or: [{a: 2}, {b: 3}]}).skip(1).toArray().length);
+
+ assert.eq(3, coll.find({$or: [{a: 2}, {b: 3}]}).batchSize(2).toArray().length);
+
+ assert.writeOK(coll.insert({a: 1}));
+ assert.writeOK(coll.insert({b: 4}));
+ assert.writeOK(coll.insert({a: 2}));
+
+ assert.eq(4, coll.find({$or: [{a: 2}, {b: 3}]}).batchSize(2).toArray().length);
+
+ assert.writeOK(coll.insert({a: 1, b: 3}));
+ assert.eq(4, coll.find({$or: [{a: 2}, {b: 3}]}).limit(4).toArray().length);
+
+ assert.eq([1, 2], Array.sort(coll.distinct('a', {$or: [{a: 2}, {b: 3}]})));
+
+ assert.eq(
+ [{a: 2}, {a: null}, {a: 1}],
+ coll.group(
+ {key: {a: 1}, cond: {$or: [{a: 2}, {b: 3}]}, reduce: function(x, y) {}, initial: {}}));
+ assert.eq(5,
+ coll.mapReduce(
+ function() {
+ emit('a', this.a);
+ },
+ function(key, vals) {
+ return vals.length;
+ },
+ {out: {inline: true}, query: {$or: [{a: 2}, {b: 3}]}})
+ .counts.input);
+
+ coll.remove({});
+
+ assert.writeOK(coll.insert({a: [1, 2]}));
+ assert.eq(1, coll.find({$or: [{a: 1}, {a: 2}]}).toArray().length);
+ assert.eq(1, coll.count({$or: [{a: 1}, {a: 2}]}));
+ assert.eq(1, coll.find({$or: [{a: 2}, {a: 1}]}).toArray().length);
+ assert.eq(1, coll.count({$or: [{a: 2}, {a: 1}]}));
+})();
diff --git a/jstests/core/profile_find.js b/jstests/core/profile_find.js
index 98834a9fc31..60a430161ee 100644
--- a/jstests/core/profile_find.js
+++ b/jstests/core/profile_find.js
@@ -153,10 +153,6 @@
profileObj = getLatestProfilerEntry(testDB, profileEntryFilter);
assert.eq(profileObj.command.returnKey, true, tojson(profileObj));
- assert.eq(coll.find().snapshot().itcount(), 1);
- profileObj = getLatestProfilerEntry(testDB, profileEntryFilter);
- assert.eq(profileObj.command.snapshot, true, tojson(profileObj));
-
//
// Confirm that queries are truncated in the profiler as { $truncated: <string>, comment:
// <string> }
diff --git a/jstests/core/snapshot_queries.js b/jstests/core/snapshot_queries.js
deleted file mode 100644
index 87364105d6d..00000000000
--- a/jstests/core/snapshot_queries.js
+++ /dev/null
@@ -1,59 +0,0 @@
-// This test uses multiple batches to pause a cursors progress, so requires getMores. This test uses
-// a delete without a limit which is not retryable. It also makes assumptions about the order of
-// collection scans using the snapshot query option. This order can change when the collection is
-// sharded.
-// @tags: [requires_getmore, requires_non_retryable_writes, assumes_unsharded_collection]
-
-// Regression test for edge cases in which .snapshot() queries could historically miss documents or
-// return the same document twice.
-(function() {
- 'use strict';
-
- var cursor;
- var coll = db.snapshot_queries;
- coll.drop();
-
- //
- // Test that a large update to the document we just returned won't cause us to return it again.
- //
-
- for (var i = 0; i < 3; i++) {
- assert.writeOK(coll.insert({_id: i}));
- }
-
- cursor = coll.find().batchSize(2).snapshot();
- assert.eq(0, cursor.next()["_id"]);
- assert.eq(1, cursor.next()["_id"]);
-
- // Force a document move (on MMAP) while the query is yielded for a getMore.
- var bigString = Array(1024 * 1024).toString();
- assert.writeOK(coll.update({_id: 1}, {$set: {padding: bigString}}));
-
- assert.eq(2, cursor.next()["_id"]);
- assert(!cursor.hasNext());
-
- //
- // Test that a large update to the document we are about to return won't cause us to skip that
- // doc.
- //
-
- coll.drop();
- assert.writeOK(coll.insert({_id: 0, padding: Array(1000).toString()}));
- for (var i = 1; i <= 3; i++) {
- assert.writeOK(coll.insert({_id: i}));
- }
-
- // On MMAP, this will leave space at the beginning of the collection. A document can be moved
- // into this free space.
- assert.writeOK(coll.remove({_id: 0}));
-
- cursor = coll.find().snapshot().batchSize(2);
- assert.eq(1, cursor.next()["_id"]);
- assert.eq(2, cursor.next()["_id"]);
-
- // Force a document move (on MMAP) while the query is yielded for a getMore.
- assert.writeOK(coll.update({_id: 3}, {$set: {padding: Array(100).toString()}}));
-
- assert.eq(3, cursor.next()["_id"]);
- assert(!cursor.hasNext());
-})();
diff --git a/jstests/mmap_v1/explain_snapshot.js b/jstests/mmap_v1/explain_snapshot.js
deleted file mode 100644
index 1d1859ebe71..00000000000
--- a/jstests/mmap_v1/explain_snapshot.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * This test ensures that .snapshot() performs an index scan on mmap_v1.
- */
-(function() {
- 'use strict';
-
- load("jstests/libs/analyze_plan.js");
-
- var coll = db.jstests_explain_snapshot;
- coll.drop();
-
- assert.writeOK(coll.insert({}));
-
- var explain = coll.explain().find().snapshot().finish();
- assert.commandWorked(explain);
- assert(isIxscan(db, explain.queryPlanner.winningPlan));
-
- explain = coll.find().snapshot().explain();
- assert.commandWorked(explain);
- assert(isIxscan(db, explain.queryPlanner.winningPlan));
-
- coll.drop();
-})();
diff --git a/jstests/sharding/printShardingStatus.js b/jstests/sharding/printShardingStatus.js
index cdc36999e51..cf2b8d454a0 100644
--- a/jstests/sharding/printShardingStatus.js
+++ b/jstests/sharding/printShardingStatus.js
@@ -95,7 +95,7 @@
// Create collection with options.
assert.commandWorked(configCopy.createCollection(c.name, c.options));
// Clone the docs.
- config.getCollection(c.name).find().snapshot().forEach(function(d) {
+ config.getCollection(c.name).find().hint({_id: 1}).forEach(function(d) {
assert.writeOK(configCopy.getCollection(c.name).insert(d));
});
// Build the indexes.
diff --git a/src/mongo/db/exec/subplan.cpp b/src/mongo/db/exec/subplan.cpp
index caa80dd1461..e75f19aae33 100644
--- a/src/mongo/db/exec/subplan.cpp
+++ b/src/mongo/db/exec/subplan.cpp
@@ -100,11 +100,6 @@ bool SubplanStage::canUseSubplanning(const CanonicalQuery& query) {
return false;
}
- // Snapshot is really a hint.
- if (query.getQueryRequest().isSnapshot()) {
- return false;
- }
-
// We can only subplan rooted $or queries.
return MatchExpression::OR == expr->matchType();
}
diff --git a/src/mongo/db/matcher/expression_optimize_test.cpp b/src/mongo/db/matcher/expression_optimize_test.cpp
index b6405b86822..9091ad48e93 100644
--- a/src/mongo/db/matcher/expression_optimize_test.cpp
+++ b/src/mongo/db/matcher/expression_optimize_test.cpp
@@ -279,16 +279,6 @@ TEST(ExpressionOptimizeTest, IsValidGeoNearNaturalHint) {
ASSERT_NOT_OK(isValid("{a: {$near: {$geometry: {type: 'Point', coordinates: [0, 0]}}}}", *qr));
}
-TEST(ExpressionOptimizeTest, IsValidTextAndSnapshot) {
- // Filter inside QueryRequest is not used.
- auto qr = stdx::make_unique<QueryRequest>(nss);
- qr->setSnapshot(true);
- ASSERT_OK(qr->validate());
-
- // Invalid: TEXT and snapshot.
- ASSERT_NOT_OK(isValid("{$text: {$search: 's'}}", *qr));
-}
-
TEST(ExpressionOptimizeTest, IsValidNaturalSortIndexHint) {
const bool isExplain = false;
auto qr = assertGet(QueryRequest::makeFromFindCommand(
diff --git a/src/mongo/db/query/canonical_query.cpp b/src/mongo/db/query/canonical_query.cpp
index 14255955c34..d498367fd50 100644
--- a/src/mongo/db/query/canonical_query.cpp
+++ b/src/mongo/db/query/canonical_query.cpp
@@ -408,11 +408,6 @@ Status CanonicalQuery::isValid(MatchExpression* root, const QueryRequest& parsed
return Status(ErrorCodes::BadValue, "text and hint not allowed in same query");
}
- // TEXT and snapshot cannot both be in the query.
- if (numText > 0 && parsed.isSnapshot()) {
- return Status(ErrorCodes::BadValue, "text and snapshot not allowed in same query");
- }
-
// TEXT and tailable are incompatible.
if (numText > 0 && parsed.isTailable()) {
return Status(ErrorCodes::BadValue, "text and tailable cursor not allowed in same query");
diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp
index 4074dab4ca4..6c05f758c6a 100644
--- a/src/mongo/db/query/get_executor.cpp
+++ b/src/mongo/db/query/get_executor.cpp
@@ -207,13 +207,6 @@ void fillOutPlannerParams(OperationContext* opCtx,
} else {
plannerParams->options |= QueryPlannerParams::KEEP_MUTATIONS;
}
-
- // MMAPv1 storage engine should have snapshot() perform an index scan on _id rather than a
- // collection scan since a collection scan on the MMAP storage engine can return duplicates
- // or miss documents.
- if (isMMAPV1()) {
- plannerParams->options |= QueryPlannerParams::SNAPSHOT_USE_ID;
- }
}
namespace {
diff --git a/src/mongo/db/query/plan_cache.cpp b/src/mongo/db/query/plan_cache.cpp
index 37de1384fcd..0d501a8212d 100644
--- a/src/mongo/db/query/plan_cache.cpp
+++ b/src/mongo/db/query/plan_cache.cpp
@@ -355,11 +355,6 @@ bool PlanCache::shouldCacheQuery(const CanonicalQuery& query) {
return false;
}
- // Snapshot is really a hint.
- if (query.getQueryRequest().isSnapshot()) {
- return false;
- }
-
return true;
}
diff --git a/src/mongo/db/query/plan_cache_test.cpp b/src/mongo/db/query/plan_cache_test.cpp
index 44cce150808..2caa24c5f6c 100644
--- a/src/mongo/db/query/plan_cache_test.cpp
+++ b/src/mongo/db/query/plan_cache_test.cpp
@@ -155,7 +155,6 @@ unique_ptr<CanonicalQuery> canonicalize(const char* queryStr,
const char* hintStr,
const char* minStr,
const char* maxStr,
- bool snapshot,
bool explain) {
QueryTestServiceContext serviceContext;
auto opCtx = serviceContext.makeOperationContext();
@@ -173,7 +172,6 @@ unique_ptr<CanonicalQuery> canonicalize(const char* queryStr,
qr->setHint(fromjson(hintStr));
qr->setMin(fromjson(minStr));
qr->setMax(fromjson(maxStr));
- qr->setSnapshot(snapshot);
qr->setExplain(explain);
const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
@@ -412,9 +410,8 @@ TEST(PlanCacheTest, ShouldNotCacheQueryExplain) {
0,
"{}",
"{}",
- "{}", // min, max
- false, // snapshot
- true // explain
+ "{}", // min, max
+ true // explain
));
const QueryRequest& qr = cq->getQueryRequest();
ASSERT_TRUE(qr.isExplain());
@@ -534,7 +531,7 @@ protected:
const BSONObj& hint,
const BSONObj& minObj,
const BSONObj& maxObj) {
- runQueryFull(query, BSONObj(), BSONObj(), 0, 0, hint, minObj, maxObj, false);
+ runQueryFull(query, BSONObj(), BSONObj(), 0, 0, hint, minObj, maxObj);
}
void runQuerySortProjSkipLimitHint(const BSONObj& query,
@@ -543,11 +540,7 @@ protected:
long long skip,
long long limit,
const BSONObj& hint) {
- runQueryFull(query, sort, proj, skip, limit, hint, BSONObj(), BSONObj(), false);
- }
-
- void runQuerySnapshot(const BSONObj& query) {
- runQueryFull(query, BSONObj(), BSONObj(), 0, 0, BSONObj(), BSONObj(), BSONObj(), true);
+ runQueryFull(query, sort, proj, skip, limit, hint, BSONObj(), BSONObj());
}
void runQueryFull(const BSONObj& query,
@@ -557,8 +550,7 @@ protected:
long long limit,
const BSONObj& hint,
const BSONObj& minObj,
- const BSONObj& maxObj,
- bool snapshot) {
+ const BSONObj& maxObj) {
QueryTestServiceContext serviceContext;
auto opCtx = serviceContext.makeOperationContext();
@@ -578,7 +570,6 @@ protected:
qr->setHint(hint);
qr->setMin(minObj);
qr->setMax(maxObj);
- qr->setSnapshot(snapshot);
const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
CanonicalQuery::canonicalize(opCtx.get(),
diff --git a/src/mongo/db/query/query_planner.cpp b/src/mongo/db/query/query_planner.cpp
index b9f2e9eb3bd..b0e046fe98b 100644
--- a/src/mongo/db/query/query_planner.cpp
+++ b/src/mongo/db/query/query_planner.cpp
@@ -124,9 +124,6 @@ string optionString(size_t options) {
case QueryPlannerParams::CANNOT_TRIM_IXISECT:
ss << "CANNOT_TRIM_IXISECT ";
break;
- case QueryPlannerParams::SNAPSHOT_USE_ID:
- ss << "SNAPSHOT_USE_ID ";
- break;
case QueryPlannerParams::NO_UNCOVERED_PROJECTIONS:
ss << "NO_UNCOVERED_PROJECTIONS ";
break;
@@ -597,40 +594,6 @@ StatusWith<std::vector<std::unique_ptr<QuerySolution>>> QueryPlanner::plan(
hintIndex = query.getQueryRequest().getHint();
}
- // If snapshot is set, default to collscanning. If the query param SNAPSHOT_USE_ID is set,
- // snapshot is a form of a hint, so try to use _id index to make a real plan. If that fails,
- // just scan the _id index.
- //
- // Don't do this if the query is a geonear or text as as text search queries must be answered
- // using full text indices and geoNear queries must be answered using geospatial indices.
- if (query.getQueryRequest().isSnapshot()) {
- RARELY {
- warning() << "The snapshot option is deprecated. See "
- "http://dochub.mongodb.org/core/snapshot-deprecation";
- }
-
- if (!QueryPlannerCommon::hasNode(query.root(), MatchExpression::GEO_NEAR) &&
- !QueryPlannerCommon::hasNode(query.root(), MatchExpression::TEXT)) {
- const bool useIXScan = params.options & QueryPlannerParams::SNAPSHOT_USE_ID;
-
- if (!useIXScan) {
- auto soln = buildCollscanSoln(query, isTailable, params);
- if (soln) {
- out.push_back(std::move(soln));
- }
- return {std::move(out)};
- } else {
- // Find the ID index in indexKeyPatterns. It's our hint.
- for (size_t i = 0; i < params.indices.size(); ++i) {
- if (isIdIndex(params.indices[i].keyPattern)) {
- hintIndex = params.indices[i].keyPattern;
- break;
- }
- }
- }
- }
- }
-
boost::optional<size_t> hintIndexNumber;
if (hintIndex.isEmpty()) {
diff --git a/src/mongo/db/query/query_planner_params.h b/src/mongo/db/query/query_planner_params.h
index 80df2b0c3ba..f54bab70458 100644
--- a/src/mongo/db/query/query_planner_params.h
+++ b/src/mongo/db/query/query_planner_params.h
@@ -87,11 +87,6 @@ struct QueryPlannerParams {
// implicitly via exact index bounds for index intersection solutions.
CANNOT_TRIM_IXISECT = 1 << 8,
- // Set this if snapshot() should scan the _id index rather than performing a
- // collection scan. The MMAPv1 storage engine sets this option since it cannot
- // guarantee that a collection scan won't miss documents or return duplicates.
- SNAPSHOT_USE_ID = 1 << 9,
-
// Set this if you don't want any plans with a non-covered projection stage. All projections
// must be provided/covered by an index.
NO_UNCOVERED_PROJECTIONS = 1 << 10,
diff --git a/src/mongo/db/query/query_planner_test.cpp b/src/mongo/db/query/query_planner_test.cpp
index fe9af7b381c..5b650d6db21 100644
--- a/src/mongo/db/query/query_planner_test.cpp
+++ b/src/mongo/db/query/query_planner_test.cpp
@@ -1141,8 +1141,7 @@ TEST_F(QueryPlannerTest, MaxMinSort) {
0,
BSONObj(),
fromjson("{a: 2}"),
- fromjson("{a: 8}"),
- false);
+ fromjson("{a: 8}"));
assertNumSolutions(1);
assertSolutionExists("{fetch: {node: {ixscan: {filter: null, pattern: {a: 1}}}}}");
@@ -1159,8 +1158,7 @@ TEST_F(QueryPlannerTest, MaxMinSortEqualityFirstSortSecond) {
0,
BSONObj(),
fromjson("{a: 1, b: 1}"),
- fromjson("{a: 1, b: 2}"),
- false);
+ fromjson("{a: 1, b: 2}"));
assertNumSolutions(1);
assertSolutionExists("{fetch: {node: {ixscan: {filter: null, pattern: {a: 1, b: 1}}}}}");
@@ -1177,8 +1175,7 @@ TEST_F(QueryPlannerTest, MaxMinSortInequalityFirstSortSecond) {
0,
BSONObj(),
fromjson("{a: 1, b: 1}"),
- fromjson("{a: 2, b: 2}"),
- false);
+ fromjson("{a: 2, b: 2}"));
assertNumSolutions(1);
assertSolutionExists(
@@ -1198,8 +1195,7 @@ TEST_F(QueryPlannerTest, MaxMinReverseSort) {
0,
BSONObj(),
fromjson("{a: 2}"),
- fromjson("{a: 8}"),
- false);
+ fromjson("{a: 8}"));
assertNumSolutions(1);
assertSolutionExists("{fetch: {node: {ixscan: {filter: null, dir: -1, pattern: {a: 1}}}}}");
@@ -1216,8 +1212,7 @@ TEST_F(QueryPlannerTest, MaxMinReverseIndexDir) {
0,
BSONObj(),
fromjson("{a: 8}"),
- fromjson("{a: 2}"),
- false);
+ fromjson("{a: 2}"));
assertNumSolutions(1);
assertSolutionExists("{fetch: {node: {ixscan: {filter: null, dir: 1, pattern: {a: -1}}}}}");
@@ -1235,8 +1230,7 @@ TEST_F(QueryPlannerTest, MaxMinReverseIndexDirSort) {
0,
BSONObj(),
fromjson("{a: 8}"),
- fromjson("{a: 2}"),
- false);
+ fromjson("{a: 2}"));
assertNumSolutions(1);
assertSolutionExists(
@@ -1255,30 +1249,16 @@ TEST_F(QueryPlannerTest, MaxMinSelectCorrectlyOrderedIndex) {
addIndex(BSON("a" << -1));
// The ordering of min and max means that we *must* use the descending index.
- runQueryFull(BSONObj(),
- BSONObj(),
- BSONObj(),
- 0,
- 0,
- BSONObj(),
- fromjson("{a: 8}"),
- fromjson("{a: 2}"),
- false);
+ runQueryFull(
+ BSONObj(), BSONObj(), BSONObj(), 0, 0, BSONObj(), fromjson("{a: 8}"), fromjson("{a: 2}"));
assertNumSolutions(1);
assertSolutionExists("{fetch: {node: {ixscan: {filter: null, dir: 1, pattern: {a: -1}}}}}");
// If we switch the ordering, then we use the ascending index.
// The ordering of min and max means that we *must* use the descending index.
- runQueryFull(BSONObj(),
- BSONObj(),
- BSONObj(),
- 0,
- 0,
- BSONObj(),
- fromjson("{a: 2}"),
- fromjson("{a: 8}"),
- false);
+ runQueryFull(
+ BSONObj(), BSONObj(), BSONObj(), 0, 0, BSONObj(), fromjson("{a: 2}"), fromjson("{a: 8}"));
assertNumSolutions(1);
assertSolutionExists("{fetch: {node: {ixscan: {filter: null, dir: 1, pattern: {a: 1}}}}}");
@@ -1298,43 +1278,7 @@ TEST_F(QueryPlannerTest, MaxMinBadHintSelectsReverseIndex) {
0,
fromjson("{a: 1}"),
fromjson("{a: 8}"),
- fromjson("{a: 2}"),
- false);
-}
-
-
-//
-// snapshot
-//
-
-TEST_F(QueryPlannerTest, Snapshot) {
- addIndex(BSON("a" << 1));
- runQuerySnapshot(fromjson("{a: {$gt: 0}}"));
-
- assertNumSolutions(1U);
- assertSolutionExists("{cscan: {filter: {a: {$gt: 0}}, dir: 1}}");
-}
-
-TEST_F(QueryPlannerTest, SnapshotUseId) {
- params.options = QueryPlannerParams::SNAPSHOT_USE_ID;
-
- addIndex(BSON("a" << 1));
- runQuerySnapshot(fromjson("{a: {$gt: 0}}"));
-
- assertNumSolutions(1U);
- assertSolutionExists(
- "{fetch: {filter: {a:{$gt:0}}, node: "
- "{ixscan: {filter: null, pattern: {_id: 1}}}}}");
-}
-
-TEST_F(QueryPlannerTest, CannotSnapshotWithGeoNear) {
- // Snapshot is skipped with geonear queries.
- addIndex(BSON("a"
- << "2d"));
- runQuerySnapshot(fromjson("{a: {$near: [0,0]}}"));
-
- ASSERT_EQUALS(getNumSolutions(), 1U);
- assertSolutionExists("{geoNear2d: {a: '2d'}}");
+ fromjson("{a: 2}"));
}
//
diff --git a/src/mongo/db/query/query_planner_test_fixture.cpp b/src/mongo/db/query/query_planner_test_fixture.cpp
index a4e937a8ca3..63ec2465f56 100644
--- a/src/mongo/db/query/query_planner_test_fixture.cpp
+++ b/src/mongo/db/query/query_planner_test_fixture.cpp
@@ -201,7 +201,7 @@ void QueryPlannerTest::runQueryHintMinMax(const BSONObj& query,
const BSONObj& hint,
const BSONObj& minObj,
const BSONObj& maxObj) {
- runQueryFull(query, BSONObj(), BSONObj(), 0, 0, hint, minObj, maxObj, false);
+ runQueryFull(query, BSONObj(), BSONObj(), 0, 0, hint, minObj, maxObj);
}
void QueryPlannerTest::runQuerySortProjSkipNToReturnHint(const BSONObj& query,
@@ -210,11 +210,7 @@ void QueryPlannerTest::runQuerySortProjSkipNToReturnHint(const BSONObj& query,
long long skip,
long long ntoreturn,
const BSONObj& hint) {
- runQueryFull(query, sort, proj, skip, ntoreturn, hint, BSONObj(), BSONObj(), false);
-}
-
-void QueryPlannerTest::runQuerySnapshot(const BSONObj& query) {
- runQueryFull(query, BSONObj(), BSONObj(), 0, 0, BSONObj(), BSONObj(), BSONObj(), true);
+ runQueryFull(query, sort, proj, skip, ntoreturn, hint, BSONObj(), BSONObj());
}
void QueryPlannerTest::runQueryFull(const BSONObj& query,
@@ -224,8 +220,7 @@ void QueryPlannerTest::runQueryFull(const BSONObj& query,
long long ntoreturn,
const BSONObj& hint,
const BSONObj& minObj,
- const BSONObj& maxObj,
- bool snapshot) {
+ const BSONObj& maxObj) {
// Clean up any previous state from a call to runQueryFull
solns.clear();
cq.reset();
@@ -248,7 +243,6 @@ void QueryPlannerTest::runQueryFull(const BSONObj& query,
qr->setHint(hint);
qr->setMin(minObj);
qr->setMax(maxObj);
- qr->setSnapshot(snapshot);
const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
CanonicalQuery::canonicalize(opCtx.get(),
@@ -290,7 +284,7 @@ void QueryPlannerTest::runInvalidQueryHintMinMax(const BSONObj& query,
const BSONObj& hint,
const BSONObj& minObj,
const BSONObj& maxObj) {
- runInvalidQueryFull(query, BSONObj(), BSONObj(), 0, 0, hint, minObj, maxObj, false);
+ runInvalidQueryFull(query, BSONObj(), BSONObj(), 0, 0, hint, minObj, maxObj);
}
void QueryPlannerTest::runInvalidQuerySortProjSkipNToReturnHint(const BSONObj& query,
@@ -299,7 +293,7 @@ void QueryPlannerTest::runInvalidQuerySortProjSkipNToReturnHint(const BSONObj& q
long long skip,
long long ntoreturn,
const BSONObj& hint) {
- runInvalidQueryFull(query, sort, proj, skip, ntoreturn, hint, BSONObj(), BSONObj(), false);
+ runInvalidQueryFull(query, sort, proj, skip, ntoreturn, hint, BSONObj(), BSONObj());
}
void QueryPlannerTest::runInvalidQueryFull(const BSONObj& query,
@@ -309,8 +303,7 @@ void QueryPlannerTest::runInvalidQueryFull(const BSONObj& query,
long long ntoreturn,
const BSONObj& hint,
const BSONObj& minObj,
- const BSONObj& maxObj,
- bool snapshot) {
+ const BSONObj& maxObj) {
solns.clear();
cq.reset();
@@ -332,7 +325,6 @@ void QueryPlannerTest::runInvalidQueryFull(const BSONObj& query,
qr->setHint(hint);
qr->setMin(minObj);
qr->setMax(maxObj);
- qr->setSnapshot(snapshot);
const boost::intrusive_ptr<ExpressionContext> expCtx;
auto statusWithCQ =
CanonicalQuery::canonicalize(opCtx.get(),
diff --git a/src/mongo/db/query/query_planner_test_fixture.h b/src/mongo/db/query/query_planner_test_fixture.h
index ef7b7f30d7f..2bdd7d5b168 100644
--- a/src/mongo/db/query/query_planner_test_fixture.h
+++ b/src/mongo/db/query/query_planner_test_fixture.h
@@ -104,8 +104,6 @@ protected:
long long ntoreturn,
const BSONObj& hint);
- void runQuerySnapshot(const BSONObj& query);
-
void runQueryFull(const BSONObj& query,
const BSONObj& sort,
const BSONObj& proj,
@@ -113,8 +111,7 @@ protected:
long long ntoreturn,
const BSONObj& hint,
const BSONObj& minObj,
- const BSONObj& maxObj,
- bool snapshot);
+ const BSONObj& maxObj);
//
// Same as runQuery* functions except we expect a failed status from the planning stage.
@@ -151,8 +148,7 @@ protected:
long long ntoreturn,
const BSONObj& hint,
const BSONObj& minObj,
- const BSONObj& maxObj,
- bool snapshot);
+ const BSONObj& maxObj);
/**
* The other runQuery* methods run the query as through it is an OP_QUERY style find. This
diff --git a/src/mongo/db/query/query_request.cpp b/src/mongo/db/query/query_request.cpp
index 512a78f9cb3..16c453f7f2e 100644
--- a/src/mongo/db/query/query_request.cpp
+++ b/src/mongo/db/query/query_request.cpp
@@ -93,7 +93,6 @@ const char kMaxField[] = "max";
const char kMinField[] = "min";
const char kReturnKeyField[] = "returnKey";
const char kShowRecordIdField[] = "showRecordId";
-const char kSnapshotField[] = "snapshot";
const char kTailableField[] = "tailable";
const char kOplogReplayField[] = "oplogReplay";
const char kNoCursorTimeoutField[] = "noCursorTimeout";
@@ -309,13 +308,6 @@ StatusWith<unique_ptr<QueryRequest>> QueryRequest::parseFromFindCommand(unique_p
}
qr->_showRecordId = el.boolean();
- } else if (fieldName == kSnapshotField) {
- Status status = checkFieldType(el, Bool);
- if (!status.isOK()) {
- return status;
- }
-
- qr->_snapshot = el.boolean();
} else if (fieldName == kTailableField) {
Status status = checkFieldType(el, Bool);
if (!status.isOK()) {
@@ -501,10 +493,6 @@ void QueryRequest::asFindCommand(BSONObjBuilder* cmdBuilder) const {
cmdBuilder->append(kShowRecordIdField, true);
}
- if (_snapshot) {
- cmdBuilder->append(kSnapshotField, true);
- }
-
switch (_tailableMode) {
case TailableMode::kTailable: {
cmdBuilder->append(kTailableField, true);
@@ -593,15 +581,6 @@ Status QueryRequest::validate() const {
}
}
- if (_snapshot) {
- if (!_sort.isEmpty()) {
- return Status(ErrorCodes::BadValue, "E12001 can't use sort with snapshot");
- }
- if (!_hint.isEmpty()) {
- return Status(ErrorCodes::BadValue, "E12002 can't use hint with snapshot");
- }
- }
-
if ((_limit || _batchSize) && _ntoreturn) {
return Status(ErrorCodes::BadValue,
"'limit' or 'batchSize' fields can not be set with 'ntoreturn' field.");
@@ -887,9 +866,6 @@ Status QueryRequest::initFullQuery(const BSONObj& top) {
if (str::equals("explain", name)) {
// Won't throw.
_explain = e.trueValue();
- } else if (str::equals("snapshot", name)) {
- // Won't throw.
- _snapshot = e.trueValue();
} else if (str::equals("min", name)) {
if (!e.isABSONObj()) {
return Status(ErrorCodes::BadValue, "$min must be a BSONObj");
@@ -1022,10 +998,6 @@ StatusWith<BSONObj> QueryRequest::asAggregationCommand() const {
str::stream() << "Option " << kShowRecordIdField
<< " not supported in aggregation."};
}
- if (_snapshot) {
- return {ErrorCodes::InvalidPipelineOperator,
- str::stream() << "Option " << kSnapshotField << " not supported in aggregation."};
- }
if (isTailable()) {
return {ErrorCodes::InvalidPipelineOperator,
"Tailable cursors are not supported in aggregation."};
diff --git a/src/mongo/db/query/query_request.h b/src/mongo/db/query/query_request.h
index a12491a14f4..1bca2d3daad 100644
--- a/src/mongo/db/query/query_request.h
+++ b/src/mongo/db/query/query_request.h
@@ -316,14 +316,6 @@ public:
_showRecordId = showRecordId;
}
- bool isSnapshot() const {
- return _snapshot;
- }
-
- void setSnapshot(bool snapshot) {
- _snapshot = snapshot;
- }
-
bool hasReadPref() const {
return _hasReadPref;
}
@@ -509,7 +501,6 @@ private:
bool _returnKey = false;
bool _showRecordId = false;
- bool _snapshot = false;
bool _hasReadPref = false;
// Options that can be specified in the OP_QUERY 'flags' header.
diff --git a/src/mongo/db/query/query_request_test.cpp b/src/mongo/db/query/query_request_test.cpp
index 5fde88e0e22..2192960b859 100644
--- a/src/mongo/db/query/query_request_test.cpp
+++ b/src/mongo/db/query/query_request_test.cpp
@@ -712,17 +712,6 @@ TEST(QueryRequestTest, ParseFromCommandShowRecordIdWrongType) {
ASSERT_NOT_OK(result.getStatus());
}
-TEST(QueryRequestTest, ParseFromCommandSnapshotWrongType) {
- BSONObj cmdObj = fromjson(
- "{find: 'testns',"
- "filter: {a: 1},"
- "snapshot: 3}");
- const NamespaceString nss("test.testns");
- bool isExplain = false;
- auto result = QueryRequest::makeFromFindCommand(nss, cmdObj, isExplain);
- ASSERT_NOT_OK(result.getStatus());
-}
-
TEST(QueryRequestTest, ParseFromCommandTailableWrongType) {
BSONObj cmdObj = fromjson(
"{find: 'testns',"
@@ -924,28 +913,6 @@ TEST(QueryRequestTest, ParseFromCommandMinMaxDifferentFieldsError) {
ASSERT_NOT_OK(result.getStatus());
}
-TEST(QueryRequestTest, ParseFromCommandSnapshotPlusSortError) {
- BSONObj cmdObj = fromjson(
- "{find: 'testns',"
- "sort: {a: 3},"
- "snapshot: true}");
- const NamespaceString nss("test.testns");
- bool isExplain = false;
- auto result = QueryRequest::makeFromFindCommand(nss, cmdObj, isExplain);
- ASSERT_NOT_OK(result.getStatus());
-}
-
-TEST(QueryRequestTest, ParseFromCommandSnapshotPlusHintError) {
- BSONObj cmdObj = fromjson(
- "{find: 'testns',"
- "snapshot: true,"
- "hint: {a: 1}}");
- const NamespaceString nss("test.testns");
- bool isExplain = false;
- auto result = QueryRequest::makeFromFindCommand(nss, cmdObj, isExplain);
- ASSERT_NOT_OK(result.getStatus());
-}
-
TEST(QueryRequestTest, ParseCommandForbidNonMetaSortOnFieldWithMetaProject) {
BSONObj cmdObj;
@@ -1044,7 +1011,6 @@ TEST(QueryRequestTest, DefaultQueryParametersCorrect) {
ASSERT_EQUALS(0, qr->getMaxTimeMS());
ASSERT_EQUALS(false, qr->returnKey());
ASSERT_EQUALS(false, qr->showRecordId());
- ASSERT_EQUALS(false, qr->isSnapshot());
ASSERT_EQUALS(false, qr->hasReadPref());
ASSERT_EQUALS(false, qr->isTailable());
ASSERT_EQUALS(false, qr->isSlaveOk());
@@ -1062,7 +1028,6 @@ TEST(QueryRequestTest, DefaultQueryParametersCorrect) {
TEST(QueryRequestTest, ParseFromCommandForbidExtraField) {
BSONObj cmdObj = fromjson(
"{find: 'testns',"
- "snapshot: true,"
"foo: {a: 1}}");
const NamespaceString nss("test.testns");
bool isExplain = false;
@@ -1073,7 +1038,6 @@ TEST(QueryRequestTest, ParseFromCommandForbidExtraField) {
TEST(QueryRequestTest, ParseFromCommandForbidExtraOption) {
BSONObj cmdObj = fromjson(
"{find: 'testns',"
- "snapshot: true,"
"foo: true}");
const NamespaceString nss("test.testns");
bool isExplain = false;
@@ -1215,12 +1179,6 @@ TEST(QueryRequestTest, ConvertToAggregationWithShowRecordIdFails) {
ASSERT_NOT_OK(qr.asAggregationCommand());
}
-TEST(QueryRequestTest, ConvertToAggregationWithSnapshotFails) {
- QueryRequest qr(testns);
- qr.setSnapshot(true);
- ASSERT_NOT_OK(qr.asAggregationCommand());
-}
-
TEST(QueryRequestTest, ConvertToAggregationWithTailableFails) {
QueryRequest qr(testns);
qr.setTailableMode(TailableMode::kTailable);
diff --git a/src/mongo/dbtests/query_stage_subplan.cpp b/src/mongo/dbtests/query_stage_subplan.cpp
index c15f0fc6e71..bbee92fe89c 100644
--- a/src/mongo/dbtests/query_stage_subplan.cpp
+++ b/src/mongo/dbtests/query_stage_subplan.cpp
@@ -376,16 +376,6 @@ TEST_F(QueryStageSubplanTest, QueryStageSubplanCanUseSubplanning) {
ASSERT_FALSE(SubplanStage::canUseSubplanning(*cq));
}
- // Can't use subplanning with snapshot.
- {
- std::string findCmd =
- "{find: 'testns',"
- "filter: {$or: [{a:1, b:1}, {c:1, d:1}]},"
- "snapshot: true}";
- std::unique_ptr<CanonicalQuery> cq = cqFromFindCommand(findCmd);
- ASSERT_FALSE(SubplanStage::canUseSubplanning(*cq));
- }
-
// Can use subplanning for rooted $or.
{
std::string findCmd =
diff --git a/src/mongo/shell/explain_query.js b/src/mongo/shell/explain_query.js
index 0670734891e..78e57c86e69 100644
--- a/src/mongo/shell/explain_query.js
+++ b/src/mongo/shell/explain_query.js
@@ -106,7 +106,6 @@ var DBExplainQuery = (function() {
"readPref",
"showDiskLoc",
"skip",
- "snapshot",
"sort",
];
@@ -235,7 +234,6 @@ var DBExplainQuery = (function() {
print("\t.readPref(mode, tagSet)");
print("\t.showDiskLoc()");
print("\t.skip(n)");
- print("\t.snapshot()");
print("\t.sort(sortSpec)");
return __magicNoPrint;
};
diff --git a/src/mongo/shell/query.js b/src/mongo/shell/query.js
index 07507454a7e..78e334f0256 100644
--- a/src/mongo/shell/query.js
+++ b/src/mongo/shell/query.js
@@ -43,7 +43,6 @@ DBQuery.prototype.help = function() {
print("\t.maxScan(<n>)");
print("\t.maxTimeMS(<n>)");
print("\t.comment(<comment>)");
- print("\t.snapshot()");
print("\t.tailable(<isAwaitData>)");
print("\t.noCursorTimeout()");
print("\t.allowPartialResults()");
@@ -215,10 +214,6 @@ DBQuery.prototype._convertToCommand = function(canAttachReadPref) {
cmd["showRecordId"] = this._query.$showDiskLoc;
}
- if ("$snapshot" in this._query) {
- cmd["snapshot"] = this._query.$snapshot;
- }
-
if ("readConcern" in this._query) {
cmd["readConcern"] = this._query.readConcern;
}
@@ -518,10 +513,6 @@ DBQuery.prototype.explain = function(verbose) {
return explainQuery.finish();
};
-DBQuery.prototype.snapshot = function() {
- return this._addSpecial("$snapshot", true);
-};
-
DBQuery.prototype.returnKey = function() {
return this._addSpecial("$returnKey", true);
};