diff options
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); }; |