diff options
40 files changed, 144 insertions, 653 deletions
diff --git a/buildscripts/resmokeconfig/suites/multi_shard_local_read_write_multi_stmt_txn_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/multi_shard_local_read_write_multi_stmt_txn_jscore_passthrough.yml index e830c47cd85..aa9e84dbc1b 100644 --- a/buildscripts/resmokeconfig/suites/multi_shard_local_read_write_multi_stmt_txn_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/multi_shard_local_read_write_multi_stmt_txn_jscore_passthrough.yml @@ -134,7 +134,7 @@ selector: ## Some aggregation stages aren't allowed in a transaction. ## - # $explain (requires read concern local) + # explain (requires read concern local) - jstests/core/agg_hint.js - jstests/core/collation.js - jstests/core/explain_shell_helpers.js @@ -178,7 +178,6 @@ selector: # SERVER-34868 Cannot run a legacy query on a session. - jstests/core/exhaust.js - - jstests/core/validate_cmd_ns.js # SERVER-34772 Tailable Cursors are not allowed in a transaction. - jstests/core/awaitdata_getmore_cmd.js diff --git a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_jscore_passthrough.yml index fead8bf2e92..a2d14686ceb 100644 --- a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_jscore_passthrough.yml @@ -136,7 +136,7 @@ selector: ## Some aggregation stages don't support snapshot readconcern. ## - # $explain (requires read concern local) + # explain (requires read concern local) - jstests/core/agg_hint.js - jstests/core/and.js - jstests/core/collation.js @@ -200,7 +200,6 @@ selector: # SERVER-34868 Cannot run a legacy query on a session. - jstests/core/exhaust.js - - jstests/core/validate_cmd_ns.js # SERVER-34772 Tailable Cursors are not allowed with snapshot readconcern. - jstests/core/awaitdata_getmore_cmd.js diff --git a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_kill_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_kill_primary_jscore_passthrough.yml index 5b68cfbb2b7..b61aed35737 100644 --- a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_kill_primary_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_kill_primary_jscore_passthrough.yml @@ -131,7 +131,7 @@ selector: ## Some aggregation stages don't support snapshot readconcern. ## - # $explain (requires read concern local) + # explain (requires read concern local) - jstests/core/agg_hint.js - jstests/core/and.js - jstests/core/collation.js @@ -188,7 +188,6 @@ selector: # SERVER-34868 Cannot run a legacy query on a session. - jstests/core/exhaust.js - - jstests/core/validate_cmd_ns.js # SERVER-34772 Tailable Cursors are not allowed with snapshot readconcern. - jstests/core/awaitdata_getmore_cmd.js diff --git a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_stepdown_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_stepdown_primary_jscore_passthrough.yml index f3cc72c5a3c..4fe4a9b5343 100644 --- a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_stepdown_primary_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_stepdown_primary_jscore_passthrough.yml @@ -132,7 +132,7 @@ selector: ## Some aggregation stages don't support snapshot readconcern. ## - # $explain (requires read concern local) + # explain (requires read concern local) - jstests/core/agg_hint.js - jstests/core/and.js - jstests/core/collation.js @@ -189,7 +189,6 @@ selector: # SERVER-34868 Cannot run a legacy query on a session. - jstests/core/exhaust.js - - jstests/core/validate_cmd_ns.js # SERVER-34772 Tailable Cursors are not allowed with snapshot readconcern. - jstests/core/awaitdata_getmore_cmd.js diff --git a/buildscripts/resmokeconfig/suites/multi_stmt_txn_jscore_passthrough_with_migration.yml b/buildscripts/resmokeconfig/suites/multi_stmt_txn_jscore_passthrough_with_migration.yml index 108a850e49d..1cb8898a421 100644 --- a/buildscripts/resmokeconfig/suites/multi_stmt_txn_jscore_passthrough_with_migration.yml +++ b/buildscripts/resmokeconfig/suites/multi_stmt_txn_jscore_passthrough_with_migration.yml @@ -144,7 +144,7 @@ selector: ## Some aggregation stages don't support snapshot readconcern. ## - # $explain (requires read concern local) + # explain (requires read concern local) - jstests/core/agg_hint.js - jstests/core/and.js - jstests/core/collation.js @@ -208,7 +208,6 @@ selector: # SERVER-34868 Cannot run a legacy query on a session. - jstests/core/exhaust.js - - jstests/core/validate_cmd_ns.js # SERVER-34772 Tailable Cursors are not allowed with snapshot readconcern. - jstests/core/awaitdata_getmore_cmd.js diff --git a/buildscripts/resmokeconfig/suites/replica_sets_kill_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_kill_primary_jscore_passthrough.yml index 2784b7ee3e6..4d7ac98666e 100644 --- a/buildscripts/resmokeconfig/suites/replica_sets_kill_primary_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/replica_sets_kill_primary_jscore_passthrough.yml @@ -47,7 +47,6 @@ selector: - jstests/core/insert2.js # Creates new mongo connection. - jstests/core/list_collections_filter.js # Temporary collections are dropped on failover. - jstests/core/startup_log.js # Checks pid, which is different on each server. - - jstests/core/validate_cmd_ns.js # Calls _exec() directly, not retryable. # Creates new mongo connection but won't retry connecting. - jstests/core/shell_connection_strings.js diff --git a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_jscore_passthrough.yml index b941a428ed3..f6e153321c3 100644 --- a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_jscore_passthrough.yml @@ -78,7 +78,7 @@ selector: ## Some aggregation stages don't support snapshot readconcern. ## - # $explain (requires read concern local) + # explain (requires read concern local) - jstests/core/agg_hint.js - jstests/core/and.js - jstests/core/collation.js @@ -148,7 +148,6 @@ selector: # SERVER-34868 Cannot run a legacy query on a session. - jstests/core/exhaust.js - - jstests/core/validate_cmd_ns.js # SERVER-34772 Tailable Cursors are not allowed with snapshot readconcern. - jstests/core/awaitdata_getmore_cmd.js diff --git a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_kill_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_kill_primary_jscore_passthrough.yml index 2d8f1367138..658df1cca30 100644 --- a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_kill_primary_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_kill_primary_jscore_passthrough.yml @@ -73,7 +73,7 @@ selector: ## Some aggregation stages don't support snapshot readconcern. ## - # $explain (requires read concern local) + # explain (requires read concern local) - jstests/core/agg_hint.js - jstests/core/and.js - jstests/core/collation.js @@ -136,7 +136,6 @@ selector: # SERVER-34868 Cannot run a legacy query on a session. - jstests/core/exhaust.js - - jstests/core/validate_cmd_ns.js # SERVER-34772 Tailable Cursors are not allowed with snapshot readconcern. - jstests/core/awaitdata_getmore_cmd.js diff --git a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_stepdown_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_stepdown_jscore_passthrough.yml index b75d012a07f..13227f2f413 100644 --- a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_stepdown_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_stepdown_jscore_passthrough.yml @@ -72,7 +72,7 @@ selector: ## Some aggregation stages don't support snapshot readconcern. ## - # $explain (requires read concern local) + # explain (requires read concern local) - jstests/core/agg_hint.js - jstests/core/and.js - jstests/core/collation.js @@ -135,7 +135,6 @@ selector: # SERVER-34868 Cannot run a legacy query on a session. - jstests/core/exhaust.js - - jstests/core/validate_cmd_ns.js # SERVER-34772 Tailable Cursors are not allowed with snapshot readconcern. - jstests/core/awaitdata_getmore_cmd.js diff --git a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_terminate_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_terminate_primary_jscore_passthrough.yml index c4f70cafc08..a0a30f7a18b 100644 --- a/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_terminate_primary_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/replica_sets_multi_stmt_txn_terminate_primary_jscore_passthrough.yml @@ -70,7 +70,7 @@ selector: ## Some aggregation stages don't support snapshot readconcern. ## - # $explain (requires read concern local) + # explain (requires read concern local) - jstests/core/agg_hint.js - jstests/core/and.js - jstests/core/collation.js @@ -133,7 +133,6 @@ selector: # SERVER-34868 Cannot run a legacy query on a session. - jstests/core/exhaust.js - - jstests/core/validate_cmd_ns.js # SERVER-34772 Tailable Cursors are not allowed with snapshot readconcern. - jstests/core/awaitdata_getmore_cmd.js diff --git a/buildscripts/resmokeconfig/suites/replica_sets_reconfig_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_reconfig_jscore_passthrough.yml index e6318e6bd0a..a12f9273ee6 100644 --- a/buildscripts/resmokeconfig/suites/replica_sets_reconfig_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/replica_sets_reconfig_jscore_passthrough.yml @@ -19,7 +19,6 @@ selector: # These test run commands using legacy queries, which are not supported on sessions. - jstests/core/comment_field.js - jstests/core/exhaust.js - - jstests/core/validate_cmd_ns.js # Unacknowledged writes prohibited in an explicit session. - jstests/core/batch_write_command_w0.js diff --git a/buildscripts/resmokeconfig/suites/replica_sets_reconfig_jscore_stepdown_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_reconfig_jscore_stepdown_passthrough.yml index b2f526f9170..f0187167f88 100644 --- a/buildscripts/resmokeconfig/suites/replica_sets_reconfig_jscore_stepdown_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/replica_sets_reconfig_jscore_stepdown_passthrough.yml @@ -34,7 +34,6 @@ selector: # These test run commands using legacy queries, which are not supported on sessions. - jstests/core/comment_field.js - jstests/core/exhaust.js - - jstests/core/validate_cmd_ns.js # Stepdown commands during fsync lock will fail. - jstests/core/currentop.js @@ -62,7 +61,6 @@ selector: - jstests/core/list_collections_filter.js # Temporary collections are dropped on failover. - jstests/core/top.js # Tests read commands (including getMore) against the secondary - jstests/core/drop3.js # getMore is not causally consistent if collection is dropped - - jstests/core/validate_cmd_ns.js # Calls _exec() directly, not retryable. - jstests/core/list_collections_filter.js # Temporary collections are dropped on failover. - jstests/core/explain_large_bounds.js # Stepdown can timeout waiting for global lock. diff --git a/buildscripts/resmokeconfig/suites/replica_sets_reconfig_kill_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_reconfig_kill_primary_jscore_passthrough.yml index 92db4edf639..7462c89afb2 100644 --- a/buildscripts/resmokeconfig/suites/replica_sets_reconfig_kill_primary_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/replica_sets_reconfig_kill_primary_jscore_passthrough.yml @@ -35,7 +35,6 @@ selector: # These test run commands using legacy queries, which are not supported on sessions. - jstests/core/comment_field.js - jstests/core/exhaust.js - - jstests/core/validate_cmd_ns.js # Stepdown commands during fsync lock will fail. - jstests/core/currentop.js @@ -63,7 +62,6 @@ selector: - jstests/core/list_collections_filter.js # Temporary collections are dropped on failover. - jstests/core/top.js # Tests read commands (including getMore) against the secondary - jstests/core/drop3.js # getMore is not causally consistent if collection is dropped - - jstests/core/validate_cmd_ns.js # Calls _exec() directly, not retryable. - jstests/core/list_collections_filter.js # Temporary collections are dropped on failover. - jstests/core/explain_large_bounds.js # Stepdown can timeout waiting for global lock. diff --git a/buildscripts/resmokeconfig/suites/replica_sets_terminate_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/replica_sets_terminate_primary_jscore_passthrough.yml index 0decf8530d8..22e53534b16 100644 --- a/buildscripts/resmokeconfig/suites/replica_sets_terminate_primary_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/replica_sets_terminate_primary_jscore_passthrough.yml @@ -47,7 +47,6 @@ selector: - jstests/core/insert2.js # Creates new mongo connection. - jstests/core/list_collections_filter.js # Temporary collections are dropped on failover. - jstests/core/startup_log.js # Checks pid, which is different on each server. - - jstests/core/validate_cmd_ns.js # Calls _exec() directly, not retryable. # Creates new mongo connection but won't retry connecting. - jstests/core/shell_connection_strings.js diff --git a/buildscripts/resmokeconfig/suites/retryable_writes_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/retryable_writes_jscore_passthrough.yml index 101b4295dfa..6a16af8357c 100644 --- a/buildscripts/resmokeconfig/suites/retryable_writes_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/retryable_writes_jscore_passthrough.yml @@ -19,7 +19,6 @@ selector: # These test run commands using legacy queries, which are not supported on sessions. - jstests/core/comment_field.js - jstests/core/exhaust.js - - jstests/core/validate_cmd_ns.js # TODO SERVER-31242: findAndModify no-op retry should respect the fields option. - jstests/core/crud_api.js diff --git a/buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml b/buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml index f81f81d153f..fd1a3c2963a 100644 --- a/buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/retryable_writes_jscore_stepdown_passthrough.yml @@ -51,7 +51,6 @@ selector: - jstests/core/insert2.js # Creates new mongo connection. - jstests/core/list_collections_filter.js # Temporary collections are dropped on failover. - jstests/core/startup_log.js # Checks pid, which is different on each server. - - jstests/core/validate_cmd_ns.js # Calls _exec() directly, not retryable. exclude_with_any_tags: - assumes_standalone_mongod diff --git a/buildscripts/resmokeconfig/suites/session_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/session_jscore_passthrough.yml index 2bb5fdfb37d..9a44de18f12 100644 --- a/buildscripts/resmokeconfig/suites/session_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/session_jscore_passthrough.yml @@ -10,7 +10,6 @@ selector: # These test run commands using legacy queries, which are not supported on sessions. - jstests/core/comment_field.js - jstests/core/exhaust.js - - jstests/core/validate_cmd_ns.js # Unacknowledged writes prohibited in an explicit session. - jstests/core/crud_api.js diff --git a/buildscripts/resmokeconfig/suites/sharded_multi_stmt_txn_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/sharded_multi_stmt_txn_jscore_passthrough.yml index f38fc8934f6..a631b980d9f 100644 --- a/buildscripts/resmokeconfig/suites/sharded_multi_stmt_txn_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/sharded_multi_stmt_txn_jscore_passthrough.yml @@ -104,7 +104,7 @@ selector: ## Some aggregation stages don't support snapshot readconcern. ## - # $explain (requires read concern local) + # explain (requires read concern local) - jstests/core/agg_hint.js - jstests/core/and.js - jstests/core/collation.js @@ -172,7 +172,6 @@ selector: # SERVER-34868 Cannot run a legacy query on a session. - jstests/core/exhaust.js - - jstests/core/validate_cmd_ns.js # SERVER-34772 Tailable Cursors are not allowed with snapshot readconcern. - jstests/core/awaitdata_getmore_cmd.js diff --git a/buildscripts/resmokeconfig/suites/tenant_migration_causally_consistent_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/tenant_migration_causally_consistent_jscore_passthrough.yml index cc0c454e223..f5aaf2f72b5 100644 --- a/buildscripts/resmokeconfig/suites/tenant_migration_causally_consistent_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/tenant_migration_causally_consistent_jscore_passthrough.yml @@ -144,7 +144,6 @@ selector: # These test run commands using legacy queries, which are not supported on sessions. - jstests/core/comment_field.js - jstests/core/exhaust.js - - jstests/core/validate_cmd_ns.js # Unacknowledged writes prohibited in an explicit session. - jstests/core/crud_api.js diff --git a/buildscripts/resmokeconfig/suites/tenant_migration_kill_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/tenant_migration_kill_primary_jscore_passthrough.yml index afa3606c245..3b00933e879 100644 --- a/buildscripts/resmokeconfig/suites/tenant_migration_kill_primary_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/tenant_migration_kill_primary_jscore_passthrough.yml @@ -144,7 +144,6 @@ selector: - jstests/core/insert2.js # Creates new mongo connection. - jstests/core/list_collections_filter.js # Temporary collections are dropped on failover. - jstests/core/startup_log.js # Checks pid, which is different on each server. - - jstests/core/validate_cmd_ns.js # Calls _exec() directly, not retryable. # # Denylists specific to this suite diff --git a/buildscripts/resmokeconfig/suites/tenant_migration_multi_stmt_txn_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/tenant_migration_multi_stmt_txn_jscore_passthrough.yml index d0555fc4e6d..5c813fd7a53 100644 --- a/buildscripts/resmokeconfig/suites/tenant_migration_multi_stmt_txn_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/tenant_migration_multi_stmt_txn_jscore_passthrough.yml @@ -193,7 +193,7 @@ selector: ## Some aggregation stages don't support snapshot readconcern. ## - # $explain (requires read concern local) + # explain (requires read concern local) - jstests/core/agg_hint.js - jstests/core/and.js - jstests/core/collation.js @@ -253,9 +253,6 @@ selector: ## Misc. reasons. ## - # SERVER-34868 Cannot run a legacy query on a session. - - jstests/core/validate_cmd_ns.js - # SERVER-34772 Tailable Cursors are not allowed with snapshot readconcern. - jstests/core/awaitdata_getmore_cmd.js - jstests/core/getmore_cmd_maxtimems.js diff --git a/buildscripts/resmokeconfig/suites/tenant_migration_stepdown_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/tenant_migration_stepdown_jscore_passthrough.yml index 8be100ca0f6..be354b863c4 100644 --- a/buildscripts/resmokeconfig/suites/tenant_migration_stepdown_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/tenant_migration_stepdown_jscore_passthrough.yml @@ -144,7 +144,6 @@ selector: - jstests/core/insert2.js # Creates new mongo connection. - jstests/core/list_collections_filter.js # Temporary collections are dropped on failover. - jstests/core/startup_log.js # Checks pid, which is different on each server. - - jstests/core/validate_cmd_ns.js # Calls _exec() directly, not retryable. # # Denylists specific to this suite diff --git a/buildscripts/resmokeconfig/suites/tenant_migration_terminate_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/tenant_migration_terminate_primary_jscore_passthrough.yml index 87679d6a701..dc26c216799 100644 --- a/buildscripts/resmokeconfig/suites/tenant_migration_terminate_primary_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/tenant_migration_terminate_primary_jscore_passthrough.yml @@ -144,7 +144,6 @@ selector: - jstests/core/insert2.js # Creates new mongo connection. - jstests/core/list_collections_filter.js # Temporary collections are dropped on failover. - jstests/core/startup_log.js # Checks pid, which is different on each server. - - jstests/core/validate_cmd_ns.js # Calls _exec() directly, not retryable. # # Denylists specific to this suite diff --git a/jstests/core/exists7.js b/jstests/core/exists7.js index 6ca55a42286..285559e82f8 100644 --- a/jstests/core/exists7.js +++ b/jstests/core/exists7.js @@ -1,6 +1,6 @@ // @tags: [requires_non_retryable_writes] -// Test that non boolean value types are allowed with $explain spec. SERVER-2322 +// Test that non boolean value types are allowed with $exists spec. SERVER-2322 t = db.jstests_exists7; t.drop(); diff --git a/jstests/core/validate_cmd_ns.js b/jstests/core/validate_cmd_ns.js deleted file mode 100644 index f5f706335ad..00000000000 --- a/jstests/core/validate_cmd_ns.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Tests that query against the $cmd namespace will error out when the request has - * a number to return value other than 1 or -1. Note that users cannot have - * collections named $cmd since $ is an illegal character. - */ - -// Note: _exec gives you the raw response from the server. -var res = db.$cmd.find({whatsmyuri: 1})._exec().next(); -assert.commandFailed(res); -assert(res.errmsg.indexOf('Bad numberToReturn') > -1); - -res = db.$cmd.find({whatsmyuri: 1}).limit(0)._exec().next(); -assert.commandFailed(res); -assert(res.errmsg.indexOf('Bad numberToReturn') > -1); - -res = db.$cmd.find({whatsmyuri: 1}).limit(-2)._exec().next(); -assert.commandFailed(res); -assert(res.errmsg.indexOf('Bad numberToReturn') > -1); - -res = db.$cmd.find({whatsmyuri: 1}).limit(1).next(); -assert.commandWorked(res); - -res = db.$cmd.find({whatsmyuri: 1}).limit(-1).next(); -assert.commandWorked(res); diff --git a/jstests/noPassthrough/exhaust_option_disallowed_in_session.js b/jstests/noPassthrough/exhaust_option_disallowed_in_session.js deleted file mode 100644 index 1ba1014dc2f..00000000000 --- a/jstests/noPassthrough/exhaust_option_disallowed_in_session.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Make sure the 'exhaust' query option is not able to be used in a session. - */ -(function() { -"use strict"; - -let conn = MongoRunner.runMongod(); - -const dbName = 'test'; -const collName = 'coll'; - -const session = conn.startSession(); -const sessionColl = session.getDatabase(dbName).getCollection(collName); -const testColl = conn.getDB(dbName).getCollection(collName); - -testColl.drop(); - -// Create a collection to query. -assert.commandWorked(testColl.insert({_id: 1})); - -// Exhaust outside of session should work. -let docs = testColl.find().addOption(DBQuery.Option.exhaust).toArray(); -assert.docEq([{_id: 1}], docs); - -// Exhaust in session should fail. -assert.throws(() => { - sessionColl.find().addOption(DBQuery.Option.exhaust).toArray(); -}); - -session.endSession(); -MongoRunner.stopMongod(conn); -}()); diff --git a/jstests/noPassthrough/max_time_ms.js b/jstests/noPassthrough/max_time_ms.js index 050b85ac648..a780b21cbbb 100644 --- a/jstests/noPassthrough/max_time_ms.js +++ b/jstests/noPassthrough/max_time_ms.js @@ -320,20 +320,9 @@ function executeTest(db, isMongos) { ErrorCodes.BadValue); assert.commandFailedWithCode(db.runCommand({ping: 1, maxTimeMS: {}}), ErrorCodes.BadValue); - // Verify that the maxTimeMS command argument can be sent with $query-wrapped commands. - cursor = t.getDB().$cmd.find({ping: 1, maxTimeMS: 0}).limit(-1); - cursor._ensureSpecial(); - assert.eq(1, cursor.next().ok); - // Verify that the server rejects invalid command argument $maxTimeMS. - cursor = t.getDB().$cmd.find({ping: 1, $maxTimeMS: 0}).limit(-1); - cursor._ensureSpecial(); - assert.commandFailed(cursor.next()); - - // Verify that the $maxTimeMS query option can't be sent with $query-wrapped commands. - cursor = t.getDB().$cmd.find({ping: 1}).limit(-1).maxTimeMS(0); - cursor._ensureSpecial(); - assert.commandFailed(cursor.next()); + assert.commandFailed(t.getDB().runCommand({ping: 1, $maxTimeMS: 0}), + [ErrorCodes.InvalidOptions, 40415]); })(); // diff --git a/jstests/sharding/query_sharded.js b/jstests/sharding/query_sharded.js deleted file mode 100644 index a043f257d6c..00000000000 --- a/jstests/sharding/query_sharded.js +++ /dev/null @@ -1,25 +0,0 @@ -// -// Tests mongos-only query behavior -// - -var st = new ShardingTest({shards: 1, mongos: 1, verbose: 0}); - -var mongos = st.s0; -var coll = mongos.getCollection("foo.bar"); - -// -// -// Ensure we can't trick mongos by inserting exhaust option on a command through mongos -coll.remove({}); -assert.commandWorked(coll.insert({a: 'b'})); -var cmdColl = mongos.getCollection(coll.getDB().toString() + ".$cmd"); -var cmdQuery = cmdColl.find({ping: 1}).limit(1); -assert.commandWorked(cmdQuery.next()); -cmdQuery = cmdColl.find({ping: 1}).limit(1).addOption(DBQuery.Option.exhaust); -assert.throws(function() { - assert.commandWorked(cmdQuery.next()); -}); - -jsTest.log("DONE!"); - -st.stop(); diff --git a/src/mongo/client/dbclient_cursor.cpp b/src/mongo/client/dbclient_cursor.cpp index db9cc55d6f3..96a509da122 100644 --- a/src/mongo/client/dbclient_cursor.cpp +++ b/src/mongo/client/dbclient_cursor.cpp @@ -103,106 +103,72 @@ Message DBClientCursor::_assembleInit() { } // If we haven't gotten a cursorId yet, we need to issue a new query or command. - if (_isCommand) { - // HACK: - // Unfortunately, this code is used by the shell to run commands, - // so we need to allow the shell to send invalid options so that we can - // test that the server rejects them. Thus, to allow generating commands with - // invalid options, we validate them here, and fall back to generating an OP_QUERY - // through makeDeprecatedQueryMessage() if the options are invalid. - bool hasValidNToReturnForCommand = (nToReturn == 1 || nToReturn == -1); - bool hasValidFlagsForCommand = !(opts & mongo::QueryOption_Exhaust); - bool hasInvalidMaxTimeMs = query.hasField("$maxTimeMS"); - - if (hasValidNToReturnForCommand && hasValidFlagsForCommand && !hasInvalidMaxTimeMs) { - return assembleCommandRequest(_client, ns.db(), opts, query); - } - } else if (_useFindCommand) { - // The caller supplies a 'query' object which may have $-prefixed directives in the format - // expected for a legacy OP_QUERY. Therefore, we use the legacy parsing code supplied by - // query_request_helper. When actually issuing the request to the remote node, we will - // assemble a find command. - bool explain = false; - auto findCommand = - query_request_helper::fromLegacyQuery(_nsOrUuid, - query, - fieldsToReturn ? *fieldsToReturn : BSONObj(), - nToSkip, - nextBatchSize(), - opts, - &explain); - if (findCommand.isOK() && !explain) { - if (query.getBoolField("$readOnce")) { - // Legacy queries don't handle readOnce. - findCommand.getValue()->setReadOnce(true); - } - if (query.getBoolField(FindCommandRequest::kRequestResumeTokenFieldName)) { - // Legacy queries don't handle requestResumeToken. - findCommand.getValue()->setRequestResumeToken(true); - } - if (query.hasField(FindCommandRequest::kResumeAfterFieldName)) { - // Legacy queries don't handle resumeAfter. - findCommand.getValue()->setResumeAfter( - query.getObjectField(FindCommandRequest::kResumeAfterFieldName)); - } - if (auto replTerm = query[FindCommandRequest::kTermFieldName]) { - // Legacy queries don't handle term. - findCommand.getValue()->setTerm(replTerm.numberLong()); - } - // Legacy queries don't handle readConcern. - // We prioritize the readConcern parsed from the query object over '_readConcernObj'. - if (auto readConcern = query[repl::ReadConcernArgs::kReadConcernFieldName]) { - findCommand.getValue()->setReadConcern(readConcern.Obj()); - } else if (_readConcernObj) { - findCommand.getValue()->setReadConcern(_readConcernObj); - } - BSONObj cmd = findCommand.getValue()->toBSON(BSONObj()); - - if (auto readPref = query["$readPreference"]) { - // FindCommandRequest doesn't handle $readPreference. - cmd = BSONObjBuilder(std::move(cmd)).append(readPref).obj(); - } - return assembleCommandRequest(_client, ns.db(), opts, std::move(cmd)); - } - // else use legacy OP_QUERY request. - // Legacy OP_QUERY request does not support UUIDs. - if (_nsOrUuid.uuid()) { - // If there was a problem building the query request, report that. - uassertStatusOK(findCommand.getStatus()); - // Otherwise it must have been explain. - uasserted(50937, "Query by UUID is not supported for explain queries."); - } + // The caller supplies a 'query' object which may have $-prefixed directives in the format + // expected for a legacy OP_QUERY. Therefore, we use the legacy parsing code supplied by + // query_request_helper. When actually issuing the request to the remote node, we will + // assemble a find command. + auto findCommand = + query_request_helper::fromLegacyQuery(_nsOrUuid, + query, + fieldsToReturn ? *fieldsToReturn : BSONObj(), + nToSkip, + nextBatchSize(), + opts); + // If there was a problem building the query request, report that. + uassertStatusOK(findCommand.getStatus()); + + if (query.getBoolField("$readOnce")) { + // Legacy queries don't handle readOnce. + findCommand.getValue()->setReadOnce(true); + } + if (query.getBoolField(FindCommandRequest::kRequestResumeTokenFieldName)) { + // Legacy queries don't handle requestResumeToken. + findCommand.getValue()->setRequestResumeToken(true); + } + if (query.hasField(FindCommandRequest::kResumeAfterFieldName)) { + // Legacy queries don't handle resumeAfter. + findCommand.getValue()->setResumeAfter( + query.getObjectField(FindCommandRequest::kResumeAfterFieldName)); + } + if (auto replTerm = query[FindCommandRequest::kTermFieldName]) { + // Legacy queries don't handle term. + findCommand.getValue()->setTerm(replTerm.numberLong()); + } + // Legacy queries don't handle readConcern. + // We prioritize the readConcern parsed from the query object over '_readConcernObj'. + if (auto readConcern = query[repl::ReadConcernArgs::kReadConcernFieldName]) { + findCommand.getValue()->setReadConcern(readConcern.Obj()); + } else if (_readConcernObj) { + findCommand.getValue()->setReadConcern(_readConcernObj); + } + BSONObj cmd = findCommand.getValue()->toBSON(BSONObj()); + if (auto readPref = query["$readPreference"]) { + // FindCommandRequest doesn't handle $readPreference. + cmd = BSONObjBuilder(std::move(cmd)).append(readPref).obj(); } - _useFindCommand = false; // Make sure we handle the reply correctly. - return makeDeprecatedQueryMessage( - ns.ns(), query, nextBatchSize(), nToSkip, fieldsToReturn, opts); + return assembleCommandRequest(_client, ns.db(), opts, std::move(cmd)); } Message DBClientCursor::_assembleGetMore() { invariant(cursorId); - if (_useFindCommand) { - std::int64_t batchSize = nextBatchSize(); - auto getMoreRequest = GetMoreCommandRequest(cursorId, ns.coll().toString()); - getMoreRequest.setBatchSize(boost::make_optional(batchSize != 0, batchSize)); - getMoreRequest.setMaxTimeMS(boost::make_optional( - tailableAwaitData(), - static_cast<std::int64_t>(durationCount<Milliseconds>(_awaitDataTimeout)))); - if (_term) { - getMoreRequest.setTerm(static_cast<std::int64_t>(*_term)); - } - getMoreRequest.setLastKnownCommittedOpTime(_lastKnownCommittedOpTime); - auto msg = assembleCommandRequest(_client, ns.db(), opts, getMoreRequest.toBSON({})); + std::int64_t batchSize = nextBatchSize(); + auto getMoreRequest = GetMoreCommandRequest(cursorId, ns.coll().toString()); + getMoreRequest.setBatchSize(boost::make_optional(batchSize != 0, batchSize)); + getMoreRequest.setMaxTimeMS(boost::make_optional( + tailableAwaitData(), + static_cast<std::int64_t>(durationCount<Milliseconds>(_awaitDataTimeout)))); + if (_term) { + getMoreRequest.setTerm(static_cast<std::int64_t>(*_term)); + } + getMoreRequest.setLastKnownCommittedOpTime(_lastKnownCommittedOpTime); + auto msg = assembleCommandRequest(_client, ns.db(), opts, getMoreRequest.toBSON({})); - // Set the exhaust flag if needed. - if (opts & QueryOption_Exhaust && msg.operation() == dbMsg) { - OpMsg::setFlag(&msg, OpMsg::kExhaustSupported); - } - return msg; - } else { - // Assemble a legacy getMore request. - return makeDeprecatedGetMoreMessage(ns.ns(), cursorId, nextBatchSize(), opts); + // Set the exhaust flag if needed. + if (opts & QueryOption_Exhaust && msg.operation() == dbMsg) { + OpMsg::setFlag(&msg, OpMsg::kExhaustSupported); } + return msg; } bool DBClientCursor::init() { @@ -339,87 +305,22 @@ void DBClientCursor::dataReceived(const Message& reply, bool& retry, string& hos batch.objs.clear(); batch.pos = 0; - // If this is a reply to our initial command request. - if (_isCommand && cursorId == 0) { - batch.objs.push_back(commandDataReceived(reply)); - return; - } - - if (_useFindCommand) { - const auto replyObj = commandDataReceived(reply); - cursorId = 0; // Don't try to kill cursor if we get back an error. - auto cr = uassertStatusOK(CursorResponse::parseFromBSON(replyObj)); - cursorId = cr.getCursorId(); - uassert(50935, - "Received a getMore response with a cursor id of 0 and the moreToCome flag set.", - !(_connectionHasPendingReplies && cursorId == 0)); - - ns = cr.getNSS(); // Unlike OP_REPLY, find command can change the ns to use for getMores. - // Store the resume token, if we got one. - _postBatchResumeToken = cr.getPostBatchResumeToken(); - batch.objs = cr.releaseBatch(); - - if (replyObj.hasField(LogicalTime::kOperationTimeFieldName)) { - _operationTime = LogicalTime::fromOperationTime(replyObj).asTimestamp(); - } - return; - } - - QueryResult::View qr = reply.singleData().view2ptr(); - resultFlags = qr.getResultFlags(); - - if (resultFlags & ResultFlag_ErrSet) { - wasError = true; - } - - if (resultFlags & ResultFlag_CursorNotFound) { - // cursor id no longer valid at the server. - invariant(qr.getCursorId() == 0); - - // 0 indicates no longer valid (dead). - cursorId = 0; - - uasserted(ErrorCodes::CursorNotFound, - str::stream() << "cursor id " << cursorId << " didn't exist on server."); - } - - if (cursorId == 0 || !(opts & QueryOption_CursorTailable)) { - // only set initially: we don't want to kill it on end of data - // if it's a tailable cursor - cursorId = qr.getCursorId(); + const auto replyObj = commandDataReceived(reply); + cursorId = 0; // Don't try to kill cursor if we get back an error. + auto cr = uassertStatusOK(CursorResponse::parseFromBSON(replyObj)); + cursorId = cr.getCursorId(); + uassert(50935, + "Received a getMore response with a cursor id of 0 and the moreToCome flag set.", + !(_connectionHasPendingReplies && cursorId == 0)); + + ns = cr.getNSS(); // find command can change the ns to use for getMores. + // Store the resume token, if we got one. + _postBatchResumeToken = cr.getPostBatchResumeToken(); + batch.objs = cr.releaseBatch(); + + if (replyObj.hasField(LogicalTime::kOperationTimeFieldName)) { + _operationTime = LogicalTime::fromOperationTime(replyObj).asTimestamp(); } - - if (opts & QueryOption_Exhaust) { - // With exhaust mode, each reply after the first claims to be a reply to the previous one - // rather than the initial request. - _connectionHasPendingReplies = (cursorId != 0); - _lastRequestId = reply.header().getId(); - } - - batch.objs.reserve(qr.getNReturned()); - - BufReader data(qr.data(), qr.dataLen()); - while (static_cast<int>(batch.objs.size()) < qr.getNReturned()) { - if (serverGlobalParams.objcheck) { - batch.objs.push_back(data.read<Validated<BSONObj>>()); - } else { - batch.objs.push_back(data.read<BSONObj>()); - } - batch.objs.back().shareOwnershipWith(reply.sharedBuffer()); - } - uassert(ErrorCodes::InvalidBSON, - "Got invalid reply from external server while reading from cursor", - data.atEof()); - - _client->checkResponse(batch.objs, false, &retry, &host); // watches for "not primary" - - tassert(5262101, - "Deprecated ShardConfigStale flag encountered in query result", - !(resultFlags & ResultFlag_ShardConfigStaleDeprecated)); - - /* this assert would fire the way we currently work: - verify( nReturned || cursorId == 0 ); - */ } /** If true, safe to call next(). Requests more from server if necessary. */ @@ -583,7 +484,6 @@ DBClientCursor::DBClientCursor(DBClientBase* client, _originalHost(_client->getServerAddress()), _nsOrUuid(nsOrUuid), ns(nsOrUuid.nss() ? *nsOrUuid.nss() : NamespaceString(nsOrUuid.dbname())), - _isCommand(ns.isCommand()), query(query), nToReturn(nToReturn), haveLimit(nToReturn > 0 && !(queryOptions & QueryOption_CursorTailable)), @@ -639,14 +539,7 @@ DBClientCursor::~DBClientCursor() { void DBClientCursor::kill() { DESTRUCTOR_GUARD({ if (cursorId && _ownCursor && !globalInShutdownDeprecated()) { - auto killCursor = [&](auto&& conn) { - if (_useFindCommand) { - conn->killCursor(ns, cursorId); - } else { - auto toSend = makeDeprecatedKillCursorsMessage(cursorId); - conn->say(toSend); - } - }; + auto killCursor = [&](auto&& conn) { conn->killCursor(ns, cursorId); }; // We only need to kill the cursor if there aren't pending replies. Pending replies // indicates that this is an exhaust cursor, so the connection must be closed and the diff --git a/src/mongo/client/dbclient_cursor.h b/src/mongo/client/dbclient_cursor.h index 9fd0139254c..c3555a698e6 100644 --- a/src/mongo/client/dbclient_cursor.h +++ b/src/mongo/client/dbclient_cursor.h @@ -299,7 +299,6 @@ private: // After a successful 'find' command, 'ns' is updated to contain the namespace returned by that // command. NamespaceString ns; - const bool _isCommand; BSONObj query; int nToReturn; bool haveLimit; @@ -314,7 +313,6 @@ private: std::string _scopedHost; std::string _lazyHost; bool wasError; - bool _useFindCommand = true; bool _connectionHasPendingReplies = false; int _lastRequestId = 0; Milliseconds _awaitDataTimeout = Milliseconds{0}; diff --git a/src/mongo/client/query.cpp b/src/mongo/client/query.cpp index 6f8ae2e3615..9aa28e92711 100644 --- a/src/mongo/client/query.cpp +++ b/src/mongo/client/query.cpp @@ -146,9 +146,6 @@ BSONObj Query::getHint() const { return BSONObj(); return obj.getObjectField("$hint"); } -bool Query::isExplain() const { - return isComplex() && obj.getBoolField("$explain"); -} string Query::toString() const { return obj.toString(); diff --git a/src/mongo/client/query.h b/src/mongo/client/query.h index f295873d98e..6ef2b2531c0 100644 --- a/src/mongo/client/query.h +++ b/src/mongo/client/query.h @@ -131,7 +131,6 @@ public: BSONObj getFilter() const; BSONObj getSort() const; BSONObj getHint() const; - bool isExplain() const; /** * @return true if the query object contains a read preference specification object. diff --git a/src/mongo/client/query_spec.h b/src/mongo/client/query_spec.h deleted file mode 100644 index 534a841842f..00000000000 --- a/src/mongo/client/query_spec.h +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Copyright (C) 2018-present MongoDB, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the Server Side Public License, version 1, - * as published by MongoDB, Inc. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * Server Side Public License for more details. - * - * You should have received a copy of the Server Side Public License - * along with this program. If not, see - * <http://www.mongodb.com/licensing/server-side-public-license>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the Server Side Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#pragma once - -#include "mongo/bson/bsonobj.h" -#include "mongo/client/query.h" -#include "mongo/util/str.h" - -namespace mongo { -/** - * Represents a full query description, including all options required for the query to be passed on - * to other hosts - */ -class QuerySpec { - std::string _ns; - int _ntoskip; - int _ntoreturn; - int _options; - BSONObj _query; - BSONObj _fields; - Query _queryObj; - -public: - QuerySpec(const std::string& ns, - const BSONObj& query, - const BSONObj& fields, - int ntoskip, - int ntoreturn, - int options) - : _ns(ns), - _ntoskip(ntoskip), - _ntoreturn(ntoreturn), - _options(options), - _query(query.getOwned()), - _fields(fields.getOwned()), - _queryObj(_query) {} - - QuerySpec() {} - - bool isEmpty() const { - return _ns.size() == 0; - } - - bool isExplain() const { - return _queryObj.isExplain(); - } - BSONObj filter() const { - return _queryObj.getFilter(); - } - - BSONObj hint() const { - return _queryObj.getHint(); - } - BSONObj sort() const { - return _queryObj.getSort(); - } - BSONObj query() const { - return _query; - } - BSONObj fields() const { - return _fields; - } - BSONObj* fieldsData() { - return &_fields; - } - - // don't love this, but needed downstrem - const BSONObj* fieldsPtr() const { - return &_fields; - } - - std::string ns() const { - return _ns; - } - int ntoskip() const { - return _ntoskip; - } - int ntoreturn() const { - return _ntoreturn; - } - int options() const { - return _options; - } - - void setFields(BSONObj& o) { - _fields = o.getOwned(); - } - - std::string toString() const { - return str::stream() << "QSpec " - << BSON("ns" << _ns << "n2skip" << _ntoskip << "n2return" << _ntoreturn - << "options" << _options << "query" << _query << "fields" - << _fields); - } -}; - -} // namespace mongo diff --git a/src/mongo/db/query/query_request_helper.cpp b/src/mongo/db/query/query_request_helper.cpp index b466781d5a3..5f5ce186be8 100644 --- a/src/mongo/db/query/query_request_helper.cpp +++ b/src/mongo/db/query/query_request_helper.cpp @@ -92,7 +92,7 @@ void addMetaProjection(FindCommandRequest* findCommand) { } } -Status initFullQuery(const BSONObj& top, FindCommandRequest* findCommand, bool* explain) { +Status initFullQuery(const BSONObj& top, FindCommandRequest* findCommand) { BSONObjIterator i(top); while (i.more()) { @@ -140,8 +140,8 @@ Status initFullQuery(const BSONObj& top, FindCommandRequest* findCommand, bool* } else if (name.startsWith("$")) { name = name.substr(1); // chop first char if (name == "explain") { - // Won't throw. - *explain = e.trueValue(); + return Status(ErrorCodes::Error(5856600), + "the $explain OP_QUERY flag is no longer supported"); } else if (name == "min") { if (!e.isABSONObj()) { return Status(ErrorCodes::BadValue, "$min must be a BSONObj"); @@ -191,8 +191,7 @@ Status initFindCommandRequest(int ntoskip, const BSONObj& queryObj, const BSONObj& proj, bool fromQueryMessage, - FindCommandRequest* findCommand, - bool* explain) { + FindCommandRequest* findCommand) { if (!proj.isEmpty()) { findCommand->setProjection(proj.getOwned()); } @@ -228,7 +227,7 @@ Status initFindCommandRequest(int ntoskip, } if (queryField.isABSONObj()) { findCommand->setFilter(queryField.embeddedObject().getOwned()); - Status status = initFullQuery(queryObj, findCommand, explain); + Status status = initFullQuery(queryObj, findCommand); if (!status.isOK()) { return status; } @@ -418,36 +417,16 @@ void validateCursorResponse(const BSONObj& outputAsBson) { // Old QueryRequest parsing code: SOON TO BE DEPRECATED. // -StatusWith<std::unique_ptr<FindCommandRequest>> fromLegacyQueryMessage(const QueryMessage& qm, - bool* explain) { - auto findCommand = std::make_unique<FindCommandRequest>(NamespaceString(qm.ns)); - - Status status = initFindCommandRequest(qm.ntoskip, - qm.ntoreturn, - qm.queryOptions, - qm.query, - qm.fields, - true, - findCommand.get(), - explain); - if (!status.isOK()) { - return status; - } - - return std::move(findCommand); -} - StatusWith<std::unique_ptr<FindCommandRequest>> fromLegacyQuery(NamespaceStringOrUUID nssOrUuid, const BSONObj& queryObj, const BSONObj& proj, int ntoskip, int ntoreturn, - int queryOptions, - bool* explain) { + int queryOptions) { auto findCommand = std::make_unique<FindCommandRequest>(std::move(nssOrUuid)); Status status = initFindCommandRequest( - ntoskip, ntoreturn, queryOptions, queryObj, proj, true, findCommand.get(), explain); + ntoskip, ntoreturn, queryOptions, queryObj, proj, true, findCommand.get()); if (!status.isOK()) { return status; } diff --git a/src/mongo/db/query/query_request_helper.h b/src/mongo/db/query/query_request_helper.h index 2617c9231d4..14409c62e39 100644 --- a/src/mongo/db/query/query_request_helper.h +++ b/src/mongo/db/query/query_request_helper.h @@ -148,13 +148,6 @@ void validateCursorResponse(const BSONObj& outputAsBson); // /** - * Parse the provided QueryMessage and return a heap constructed FindCommandRequest, which - * represents it or an error. - */ -StatusWith<std::unique_ptr<FindCommandRequest>> fromLegacyQueryMessage(const QueryMessage& qm, - bool* explain); - -/** * Parse the provided legacy query object and parameters to construct a FindCommandRequest. */ StatusWith<std::unique_ptr<FindCommandRequest>> fromLegacyQuery(NamespaceStringOrUUID nsOrUuid, @@ -162,8 +155,7 @@ StatusWith<std::unique_ptr<FindCommandRequest>> fromLegacyQuery(NamespaceStringO const BSONObj& proj, int ntoskip, int ntoreturn, - int queryOptions, - bool* explain); + int queryOptions); } // namespace query_request_helper } // namespace mongo diff --git a/src/mongo/db/query/query_request_test.cpp b/src/mongo/db/query/query_request_test.cpp index 8518c0e4661..2e92a48f4e9 100644 --- a/src/mongo/db/query/query_request_test.cpp +++ b/src/mongo/db/query/query_request_test.cpp @@ -1562,17 +1562,14 @@ TEST(QueryRequestTest, ParseFromLegacyQuery) { query: {query: 1}, orderby: {sort: 1}, $hint: {hint: 1}, - $explain: false, $min: {x: 'min'}, $max: {x: 'max'} })"); - bool explain = false; unique_ptr<FindCommandRequest> findCommand(assertGet(query_request_helper::fromLegacyQuery( - nss, queryObj, BSON("proj" << 1), kSkip, kNToReturn, QueryOption_Exhaust, &explain))); + nss, queryObj, BSON("proj" << 1), kSkip, kNToReturn, QueryOption_Exhaust))); ASSERT_EQ(*findCommand->getNamespaceOrUUID().nss(), nss); - ASSERT_EQ(explain, false); ASSERT_BSONOBJ_EQ(findCommand->getFilter(), fromjson("{query: 1}")); ASSERT_BSONOBJ_EQ(findCommand->getProjection(), fromjson("{proj: 1}")); ASSERT_BSONOBJ_EQ(findCommand->getSort(), fromjson("{sort: 1}")); @@ -1597,9 +1594,8 @@ TEST(QueryRequestTest, ParseFromLegacyQueryOplogReplayFlagAllowed) { // Test that parsing succeeds even if the oplog replay bit is set in the OP_QUERY message. This // flag may be set by old clients. auto options = QueryOption_OplogReplay_DEPRECATED; - bool explain = false; unique_ptr<FindCommandRequest> findCommand(assertGet(query_request_helper::fromLegacyQuery( - nss, queryObj, projectionObj, nToSkip, nToReturn, options, &explain))); + nss, queryObj, projectionObj, nToSkip, nToReturn, options))); // Verify that if we reserialize the find command, the 'oplogReplay' field // does not appear. @@ -1619,9 +1615,8 @@ TEST(QueryRequestTest, ParseFromLegacyQueryUnwrapped) { foo: 1 })"); const NamespaceString nss("test.testns"); - bool explain = false; unique_ptr<FindCommandRequest> findCommand(assertGet(query_request_helper::fromLegacyQuery( - nss, queryObj, BSONObj(), 0, 0, QueryOption_Exhaust, &explain))); + nss, queryObj, BSONObj(), 0, 0, QueryOption_Exhaust))); ASSERT_EQ(*findCommand->getNamespaceOrUUID().nss(), nss); ASSERT_BSONOBJ_EQ(findCommand->getFilter(), fromjson("{foo: 1}")); @@ -1647,15 +1642,24 @@ TEST(QueryRequestTest, ParseFromLegacyQueryTooNegativeNToReturn) { })"); const NamespaceString nss("test.testns"); - bool explain = false; - ASSERT_NOT_OK(query_request_helper::fromLegacyQuery(nss, - queryObj, - BSONObj(), - 0, - std::numeric_limits<int>::min(), - QueryOption_Exhaust, - &explain) - .getStatus()); + ASSERT_NOT_OK( + query_request_helper::fromLegacyQuery( + nss, queryObj, BSONObj(), 0, std::numeric_limits<int>::min(), QueryOption_Exhaust) + .getStatus()); +} + +TEST(QueryRequestTest, ParseFromLegacyQueryExplainError) { + BSONObj queryObj = fromjson(R"({ + query: {query: 1}, + $explain: false + })"); + + const NamespaceString nss("test.testns"); + ASSERT_EQUALS( + query_request_helper::fromLegacyQuery(nss, queryObj, BSONObj(), 0, -1, QueryOption_Exhaust) + .getStatus() + .code(), + static_cast<ErrorCodes::Error>(5856600)); } class QueryRequestTest : public ServiceContextTest {}; diff --git a/src/mongo/s/commands/cluster_explain_cmd.cpp b/src/mongo/s/commands/cluster_explain_cmd.cpp index 287ec9902d7..9ee65bdbc49 100644 --- a/src/mongo/s/commands/cluster_explain_cmd.cpp +++ b/src/mongo/s/commands/cluster_explain_cmd.cpp @@ -40,15 +40,6 @@ namespace { /** * Implements the explain command on mongos. - * - * "Old-style" explains (i.e. queries which have the $explain flag set), do not run - * through this path. Such explains will be supported for backwards compatibility, - * and must succeed in multiversion clusters. - * - * "New-style" explains use the explain command. When the explain command is routed - * through mongos, it is forwarded to all relevant shards. If *any* shard does not - * support a new-style explain, then the entire explain will fail (i.e. new-style - * explains cannot be used in multiversion clusters). */ class ClusterExplainCmd final : public Command { diff --git a/src/mongo/shell/explain_query.js b/src/mongo/shell/explain_query.js index b4935fd07d4..453751d88de 100644 --- a/src/mongo/shell/explain_query.js +++ b/src/mongo/shell/explain_query.js @@ -9,37 +9,6 @@ var DBExplainQuery = (function() { // /** - * In 2.6 and before, .explain(), .explain(false), or .explain(<falsy value>) instructed the - * shell to reduce the explain verbosity by removing certain fields from the output. This - * is implemented here for backwards compatibility. - */ - function removeVerboseFields(obj) { - if (typeof (obj) !== "object") { - return; - } - - delete obj.allPlans; - delete obj.oldPlan; - delete obj.stats; - - if (typeof (obj.length) === "number") { - for (var i = 0; i < obj.length; i++) { - removeVerboseFields(obj[i]); - } - } - - if (obj.shards) { - for (var key in obj.shards) { - removeVerboseFields(obj.shards[key]); - } - } - - if (obj.clauses) { - removeVerboseFields(obj.clauses); - } - } - - /** * Many of the methods of an explain query just pass through to the underlying * non-explained DBQuery. Use this to generate a function which calls function 'name' on * 'destObj' and then returns this. @@ -51,28 +20,6 @@ var DBExplainQuery = (function() { }; } - /** - * Where possible, the explain query will be sent to the server as an explain command. - * However, if one of the nodes we are talking to (either a standalone or a shard in - * a sharded cluster) is of a version that doesn't have the explain command, we will - * use this function to fall back on the $explain query option. - */ - function explainWithLegacyQueryOption(explainQuery) { - // The wire protocol version indicates that the server does not have the explain - // command. Add $explain to the query and send it to the server. - var clone = explainQuery._query.clone(); - clone._addSpecial("$explain", true); - var result = clone.next(); - - // Remove some fields from the explain if verbosity is - // just "queryPlanner". - if ("queryPlanner" === explainQuery._verbosity) { - removeVerboseFields(result); - } - - return Explainable.throwOrReturn(result); - } - function constructor(query, verbosity) { // // Private vars. @@ -136,47 +83,35 @@ var DBExplainQuery = (function() { // Explain always gets pretty printed. this._query._prettyShell = true; - if (this._mongo.hasExplainCommand()) { - // The wire protocol version indicates that the server has the explain command. - // Convert this explain query into an explain command, and send the command to - // the server. - var innerCmd; - if (this._isCount) { - // True means to always apply the skip and limit values. - innerCmd = this._query._convertToCountCmd(this._applySkipLimit); - } else { - var canAttachReadPref = false; - innerCmd = this._query._convertToCommand(canAttachReadPref); - } - - var explainCmd = {explain: innerCmd}; - explainCmd["verbosity"] = this._verbosity; - // If "maxTimeMS" is set on innerCmd, it needs to be propagated to the top-level - // of explainCmd so that it has the intended effect. - if (innerCmd.hasOwnProperty("maxTimeMS")) { - explainCmd.maxTimeMS = innerCmd.maxTimeMS; - } - - var explainDb = this._query._db; - - if ("$readPreference" in this._query._query) { - var prefObj = this._query._query.$readPreference; - explainCmd = explainDb._attachReadPreferenceToCommand(explainCmd, prefObj); - } - - var explainResult = - explainDb.runReadCommand(explainCmd, null, this._query._options); - - if (!explainResult.ok && explainResult.code === ErrorCodes.CommandNotFound) { - // One of the shards doesn't have the explain command available. Retry using - // the legacy $explain format, which should be supported by all shards. - return explainWithLegacyQueryOption(this); - } - - return Explainable.throwOrReturn(explainResult); + // Convert this explain query into an explain command, and send the command to + // the server. + var innerCmd; + if (this._isCount) { + // True means to always apply the skip and limit values. + innerCmd = this._query._convertToCountCmd(this._applySkipLimit); } else { - return explainWithLegacyQueryOption(this); + var canAttachReadPref = false; + innerCmd = this._query._convertToCommand(canAttachReadPref); } + + var explainCmd = {explain: innerCmd}; + explainCmd["verbosity"] = this._verbosity; + // If "maxTimeMS" is set on innerCmd, it needs to be propagated to the top-level + // of explainCmd so that it has the intended effect. + if (innerCmd.hasOwnProperty("maxTimeMS")) { + explainCmd.maxTimeMS = innerCmd.maxTimeMS; + } + + var explainDb = this._query._db; + + if ("$readPreference" in this._query._query) { + var prefObj = this._query._query.$readPreference; + explainCmd = explainDb._attachReadPreferenceToCommand(explainCmd, prefObj); + } + + var explainResult = explainDb.runReadCommand(explainCmd, null, this._query._options); + + return Explainable.throwOrReturn(explainResult); }; this.next = function() { diff --git a/src/mongo/shell/mongo.js b/src/mongo/shell/mongo.js index cf05337eead..7146fd8670a 100644 --- a/src/mongo/shell/mongo.js +++ b/src/mongo/shell/mongo.js @@ -418,11 +418,6 @@ connect = function(url, user, pass, apiParameters) { return db; }; -Mongo.prototype.hasExplainCommand = function() { - var hasExplain = (this.getMinWireVersion() <= 3 && 3 <= this.getMaxWireVersion()); - return hasExplain; -}; - // // Write Concern can be set at the connection level, and is used for all write operations unless // overridden at the collection level. diff --git a/src/mongo/transport/service_state_machine.cpp b/src/mongo/transport/service_state_machine.cpp index f1deac76b13..bd96331bd50 100644 --- a/src/mongo/transport/service_state_machine.cpp +++ b/src/mongo/transport/service_state_machine.cpp @@ -68,61 +68,12 @@ namespace { MONGO_FAIL_POINT_DEFINE(doNotSetMoreToCome); MONGO_FAIL_POINT_DEFINE(beforeCompressingExhaustResponse); /** - * Creates and returns a legacy exhaust message, if exhaust is allowed. The returned message is to - * be used as the subsequent 'synthetic' exhaust request. Returns an empty message if exhaust is not - * allowed. Any messages that do not have an opcode of OP_MSG are considered legacy. - */ -Message makeLegacyExhaustMessage(Message* m, const DbResponse& dbresponse) { - // OP_QUERY responses are always of type OP_REPLY. - invariant(dbresponse.response.operation() == opReply); - - if (!dbresponse.shouldRunAgainForExhaust) { - return Message(); - } - - // Legacy find operations via the OP_QUERY/OP_GET_MORE network protocol never provide the next - // invocation for exhaust. - invariant(!dbresponse.nextInvocation); - - DbMessage dbmsg(*m); - invariant(dbmsg.messageShouldHaveNs()); - const char* ns = dbmsg.getns(); - - MsgData::View header = dbresponse.response.header(); - QueryResult::View qr = header.view2ptr(); - long long cursorid = qr.getCursorId(); - - if (cursorid == 0) { - return Message(); - } - - // Generate a message that will act as the subsequent 'synthetic' exhaust request. - BufBuilder b(512); - b.appendNum(static_cast<int>(0)); // size set later in setLen() - b.appendNum(header.getId()); // message id - b.appendNum(header.getResponseToMsgId()); // in response to - b.appendNum(static_cast<int>(dbGetMore)); // opCode is OP_GET_MORE - b.appendNum(static_cast<int>(0)); // Must be ZERO (reserved) - b.appendStr(StringData(ns)); // Namespace - b.appendNum(static_cast<int>(0)); // ntoreturn - b.appendNum(cursorid); // cursor id from the OP_REPLY - - MsgData::View(b.buf()).setLen(b.len()); - - return Message(b.release()); -} - -/** * Given a request and its already generated response, checks for exhaust flags. If exhaust is * allowed, produces the subsequent request message, and modifies the response message to indicate * it is part of an exhaust stream. Returns the subsequent request message, which is known as a * 'synthetic' exhaust request. Returns an empty message if exhaust is not allowed. */ Message makeExhaustMessage(Message requestMsg, DbResponse* dbresponse) { - if (requestMsg.operation() == dbQuery) { - return makeLegacyExhaustMessage(&requestMsg, *dbresponse); - } - if (!OpMsgRequest::isFlagSet(requestMsg, OpMsg::kExhaustSupported)) { return Message(); } |