From 4057fb4127a569286d8e342d9bbdd7a7f75806b5 Mon Sep 17 00:00:00 2001 From: Jason Zhang Date: Thu, 15 Sep 2022 00:19:45 +0000 Subject: SERVER-69623 Add _clusterQueryWithoutShardKey command stub --- jstests/auth/lib/commands_lib.js | 25 ++++++ jstests/core/views/views_all_commands.js | 1 + .../db_reads_while_recovering_all_commands.js | 1 + .../sharding/database_versioning_all_commands.js | 2 + jstests/sharding/libs/last_lts_mongos_commands.js | 1 + .../read_write_concern_defaults_application.js | 1 + .../sharding/safe_secondary_reads_drop_recreate.js | 1 + ...eads_single_migration_suspend_range_deletion.js | 1 + ...condary_reads_single_migration_waitForDelete.js | 1 + .../cluster_query_without_shard_key_basic.js | 19 +++++ .../db/internal_transactions_feature_flag.idl | 2 +- src/mongo/s/SConscript | 1 + src/mongo/s/commands/SConscript | 1 + .../cluster_query_without_shard_key_cmd.cpp | 98 ++++++++++++++++++++++ .../cluster_commands_without_shard_key.idl | 54 ++++++++++++ 15 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 jstests/sharding/updateOne_without_shard_key/cluster_query_without_shard_key_basic.js create mode 100644 src/mongo/s/commands/cluster_query_without_shard_key_cmd.cpp create mode 100644 src/mongo/s/request_types/cluster_commands_without_shard_key.idl diff --git a/jstests/auth/lib/commands_lib.js b/jstests/auth/lib/commands_lib.js index e1ded111f49..8e7fe629ea1 100644 --- a/jstests/auth/lib/commands_lib.js +++ b/jstests/auth/lib/commands_lib.js @@ -222,6 +222,31 @@ var authCommandsLib = { }, ] }, + { + testname: "_clusterQueryWithoutShardKey", + command: {_clusterQueryWithoutShardKey: 1, writeCmd: {}, stmtId: NumberInt(1)}, + skipUnlessSharded: true, + skipTest: (conn) => { + return !TestData.setParameters.featureFlagUpdateOneWithoutShardKey; + }, + testcases: [ + { + runOnDb: adminDbName, + roles: {__system: 1}, + privileges: [{resource: {cluster: true}, actions: ["internal"]}], + }, + { + runOnDb: firstDbName, + roles: {__system: 1}, + privileges: [{resource: {cluster: true}, actions: ["internal"]}], + }, + { + runOnDb: secondDbName, + roles: {__system: 1}, + privileges: [{resource: {cluster: true}, actions: ["internal"]}], + } + ] + }, { testname: "_configsvrAbortReshardCollection", command: {_configsvrAbortReshardCollection: "test.x"}, diff --git a/jstests/core/views/views_all_commands.js b/jstests/core/views/views_all_commands.js index b912d157314..c766d18287d 100644 --- a/jstests/core/views/views_all_commands.js +++ b/jstests/core/views/views_all_commands.js @@ -81,6 +81,7 @@ let viewsCommandTests = { _addShard: {skip: isAnInternalCommand}, _cloneCatalogData: {skip: isAnInternalCommand}, _cloneCollectionOptionsFromPrimaryShard: {skip: isAnInternalCommand}, + _clusterQueryWithoutShardKey: {skip: isAnInternalCommand}, _configsvrAbortReshardCollection: {skip: isAnInternalCommand}, _configsvrAddShard: {skip: isAnInternalCommand}, _configsvrAddShardToZone: {skip: isAnInternalCommand}, diff --git a/jstests/replsets/db_reads_while_recovering_all_commands.js b/jstests/replsets/db_reads_while_recovering_all_commands.js index 2614dcf008f..b8179f145a1 100644 --- a/jstests/replsets/db_reads_while_recovering_all_commands.js +++ b/jstests/replsets/db_reads_while_recovering_all_commands.js @@ -25,6 +25,7 @@ const isPrimaryOnly = "primary only"; const allCommands = { _addShard: {skip: isPrimaryOnly}, _cloneCollectionOptionsFromPrimaryShard: {skip: isPrimaryOnly}, + _clusterQueryWithoutShardKey: {skip: isAnInternalCommand}, _configsvrAbortReshardCollection: {skip: isPrimaryOnly}, _configsvrAddShard: {skip: isPrimaryOnly}, _configsvrAddShardToZone: {skip: isPrimaryOnly}, diff --git a/jstests/sharding/database_versioning_all_commands.js b/jstests/sharding/database_versioning_all_commands.js index e0ca698bc7a..0a0a21d3112 100644 --- a/jstests/sharding/database_versioning_all_commands.js +++ b/jstests/sharding/database_versioning_all_commands.js @@ -242,6 +242,8 @@ function testCommandAfterDropRecreateDatabase(testCase, st) { } let testCases = { + _clusterQueryWithoutShardKey: + {skip: "executed locally on a mongos (not sent to any remote node)"}, _getAuditConfigGeneration: {skip: "not on a user database", conditional: true}, _hashBSONElement: {skip: "executes locally on mongos (not sent to any remote node)"}, _isSelf: {skip: "executes locally on mongos (not sent to any remote node)"}, diff --git a/jstests/sharding/libs/last_lts_mongos_commands.js b/jstests/sharding/libs/last_lts_mongos_commands.js index e9f91bd2f85..354e693b5ef 100644 --- a/jstests/sharding/libs/last_lts_mongos_commands.js +++ b/jstests/sharding/libs/last_lts_mongos_commands.js @@ -14,6 +14,7 @@ const commandsRemovedFromMongosSinceLastLTS = [ // listCommands output of a last LTS version mongos. We will allow these commands to have a test // defined without always existing on the mongos being used. const commandsAddedToMongosSinceLastLTS = [ + "_clusterQueryWithoutShardKey", "abortReshardCollection", "analyze", "analyzeShardKey", // TODO (SERVER-68977): Remove upgrade/downgrade for PM-1858. diff --git a/jstests/sharding/read_write_concern_defaults_application.js b/jstests/sharding/read_write_concern_defaults_application.js index bdfb865b297..7c20c896381 100644 --- a/jstests/sharding/read_write_concern_defaults_application.js +++ b/jstests/sharding/read_write_concern_defaults_application.js @@ -78,6 +78,7 @@ let validateTestCase = function(test) { let testCases = { _addShard: {skip: "internal command"}, _cloneCollectionOptionsFromPrimaryShard: {skip: "internal command"}, + _clusterQueryWithoutShardKey: {skip: "internal command"}, _configsvrAbortReshardCollection: {skip: "internal command"}, _configsvrAddShard: {skip: "internal command"}, _configsvrAddShardToZone: {skip: "internal command"}, diff --git a/jstests/sharding/safe_secondary_reads_drop_recreate.js b/jstests/sharding/safe_secondary_reads_drop_recreate.js index 24a9c46a50b..282615a2a40 100644 --- a/jstests/sharding/safe_secondary_reads_drop_recreate.js +++ b/jstests/sharding/safe_secondary_reads_drop_recreate.js @@ -43,6 +43,7 @@ let validateTestCase = function(test) { let testCases = { _addShard: {skip: "primary only"}, _shardsvrCloneCatalogData: {skip: "primary only"}, + _clusterQueryWithoutShardKey: {skip: "internal command"}, _configsvrAddShard: {skip: "primary only"}, _configsvrAddShardToZone: {skip: "primary only"}, _configsvrBalancerCollectionStatus: {skip: "primary only"}, diff --git a/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js b/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js index bdb89b73d79..5076859044f 100644 --- a/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js +++ b/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js @@ -48,6 +48,7 @@ let validateTestCase = function(test) { let testCases = { _addShard: {skip: "primary only"}, _shardsvrCloneCatalogData: {skip: "primary only"}, + _clusterQueryWithoutShardKey: {skip: "internal command"}, _configsvrAddShard: {skip: "primary only"}, _configsvrAddShardToZone: {skip: "primary only"}, _configsvrBalancerCollectionStatus: {skip: "primary only"}, diff --git a/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js b/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js index db64ea86ed9..4d831df75ec 100644 --- a/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js +++ b/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js @@ -40,6 +40,7 @@ let validateTestCase = function(test) { let testCases = { _addShard: {skip: "primary only"}, _shardsvrCloneCatalogData: {skip: "primary only"}, + _clusterQueryWithoutShardKey: {skip: "internal command"}, _configsvrAddShard: {skip: "primary only"}, _configsvrAddShardToZone: {skip: "primary only"}, _configsvrBalancerCollectionStatus: {skip: "primary only"}, diff --git a/jstests/sharding/updateOne_without_shard_key/cluster_query_without_shard_key_basic.js b/jstests/sharding/updateOne_without_shard_key/cluster_query_without_shard_key_basic.js new file mode 100644 index 00000000000..90d748ad225 --- /dev/null +++ b/jstests/sharding/updateOne_without_shard_key/cluster_query_without_shard_key_basic.js @@ -0,0 +1,19 @@ +/** + * Tests the internal command _clusterQueryWithoutShardKey. + * + * @tags: [requires_fcv_62, featureFlagUpdateOneWithoutShardKey] + */ +(function() { +"use strict"; + +let st = new ShardingTest({shards: 1, rs: {nodes: 1}}); +let dbName = "test"; +let mongosConn = st.s.getDB(dbName); +let shardConn = st.shard0.getDB(dbName); +let cmdObj = {_clusterQueryWithoutShardKey: 1, writeCmd: {}, stmtId: NumberInt(1)}; + +assert.commandWorked(mongosConn.runCommand(cmdObj)); +assert.commandFailedWithCode(shardConn.runCommand(cmdObj), ErrorCodes.CommandNotFound); + +st.stop(); +})(); diff --git a/src/mongo/db/internal_transactions_feature_flag.idl b/src/mongo/db/internal_transactions_feature_flag.idl index 6740092ed83..97b0bcd927a 100644 --- a/src/mongo/db/internal_transactions_feature_flag.idl +++ b/src/mongo/db/internal_transactions_feature_flag.idl @@ -47,5 +47,5 @@ feature_flags: featureFlagUpdateOneWithoutShardKey: description: Feature flag to enable updateOne, deleteOne, and findAndModify without a shard key or _id equality in their filter against a sharded collection. - cpp_varname: gfeatureFlagUpdateOneWithoutShardKey + cpp_varname: gFeatureFlagUpdateOneWithoutShardKey default: false diff --git a/src/mongo/s/SConscript b/src/mongo/s/SConscript index d8ed42e46d1..f7746d9b4be 100644 --- a/src/mongo/s/SConscript +++ b/src/mongo/s/SConscript @@ -168,6 +168,7 @@ env.Library( 'request_types/balancer_collection_status.idl', 'request_types/cleanup_reshard_collection.idl', 'request_types/clone_catalog_data.idl', + 'request_types/cluster_commands_without_shard_key.idl', 'request_types/commit_reshard_collection.idl', 'request_types/configure_collection_balancing.idl', 'request_types/drop_collection_if_uuid_not_matching.idl', diff --git a/src/mongo/s/commands/SConscript b/src/mongo/s/commands/SConscript index a37bee825c2..7dd1f0bc554 100644 --- a/src/mongo/s/commands/SConscript +++ b/src/mongo/s/commands/SConscript @@ -76,6 +76,7 @@ env.Library( 'cluster_pipeline_cmd_s.cpp', 'cluster_plan_cache_clear_cmd.cpp', 'cluster_profile_cmd.cpp', + 'cluster_query_without_shard_key_cmd.cpp', 'cluster_refine_collection_shard_key_cmd.cpp', 'cluster_rename_collection_cmd.cpp', 'cluster_repair_sharded_collection_chunks_history_cmd.cpp', diff --git a/src/mongo/s/commands/cluster_query_without_shard_key_cmd.cpp b/src/mongo/s/commands/cluster_query_without_shard_key_cmd.cpp new file mode 100644 index 00000000000..8b2cfcf2560 --- /dev/null +++ b/src/mongo/s/commands/cluster_query_without_shard_key_cmd.cpp @@ -0,0 +1,98 @@ +/** + * Copyright (C) 2022-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 + * . + * + * 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. + */ + +#include "mongo/db/auth/authorization_session.h" +#include "mongo/db/commands.h" +#include "mongo/db/internal_transactions_feature_flag_gen.h" +#include "mongo/logv2/log.h" +#include "mongo/s/is_mongos.h" +#include "mongo/s/request_types/cluster_commands_without_shard_key_gen.h" + +#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kCommand + +namespace mongo { +namespace { + +class ClusterQueryWithoutShardKeyCmd : public TypedCommand { +public: + using Request = ClusterQueryWithoutShardKey; + using Response = ClusterQueryWithoutShardKeyResponse; + + class Invocation final : public InvocationBase { + public: + using InvocationBase::InvocationBase; + + Response typedRun(OperationContext* opCtx) { + uassert(ErrorCodes::IllegalOperation, + "_clusterQueryWithoutShardKey can only be run on Mongos", + isMongos()); + + LOGV2(6962400, + "Running read phase for a write without a shard key.", + "clientWriteRequest"_attr = request().getWriteCmd(), + "stmtIdInBatch"_attr = request().getStmtId()); + return {}; + } + + private: + NamespaceString ns() const override { + return NamespaceString(request().getDbName()); + } + + bool supportsWriteConcern() const override { + return false; + } + + void doCheckAuthorization(OperationContext* opCtx) const override { + uassert(ErrorCodes::Unauthorized, + "Unauthorized", + AuthorizationSession::get(opCtx->getClient()) + ->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(), + ActionType::internal)); + } + }; + + AllowedOnSecondary secondaryAllowed(ServiceContext*) const final { + return AllowedOnSecondary::kNever; + } + + bool supportsRetryableWrite() const final { + return true; + } + + bool allowedInTransactions() const final { + return true; + } +}; + +MONGO_REGISTER_FEATURE_FLAGGED_COMMAND(ClusterQueryWithoutShardKeyCmd, + feature_flags::gFeatureFlagUpdateOneWithoutShardKey); + +} // namespace +} // namespace mongo diff --git a/src/mongo/s/request_types/cluster_commands_without_shard_key.idl b/src/mongo/s/request_types/cluster_commands_without_shard_key.idl new file mode 100644 index 00000000000..0b08e9abc9b --- /dev/null +++ b/src/mongo/s/request_types/cluster_commands_without_shard_key.idl @@ -0,0 +1,54 @@ +# Copyright (C) 2022-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 +# . +# +# 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. +# + +global: + cpp_namespace: "mongo" + +imports: + - "mongo/db/basic_types.idl" + - "mongo/s/sharding_types.idl" +structs: + clusterQueryWithoutShardKeyResponse: + description: "The response for the '_clusterQueryWithoutShardKeyFind' command." + +commands: + _clusterQueryWithoutShardKey: + command_name: _clusterQueryWithoutShardKey + cpp_name: ClusterQueryWithoutShardKey + description: "An internal command used to broadcast a query to all shards for updates/deletes/findAndModifies that do not provide a shard key." + namespace: ignored + api_version: "" + reply_type: clusterQueryWithoutShardKeyResponse + fields: + writeCmd: + description: "The original write command." + type: object + stmtId: + description: "The stmtId of the write statement in the original batch write." + type: int + -- cgit v1.2.1