SERVER-109096 Move getTargetedShardsForQuery and getTargetedShardsForCanonicalQuery to a query-owned library (#43501)

GitOrigin-RevId: 716c8e66db694bf301b956e4fdc780d921e0c50b
This commit is contained in:
Igor Praznik 2025-12-12 15:14:11 +01:00 committed by MongoDB Bot
parent de4061aae3
commit 87329659fd
23 changed files with 197 additions and 102 deletions

3
.github/CODEOWNERS vendored
View File

@ -3060,7 +3060,6 @@ WORKSPACE.bazel @10gen/devprod-build @svc-auto-approve-bot
/src/mongo/s/**/balancer_configuration* @10gen/server-cluster-scalability @svc-auto-approve-bot
/src/mongo/s/**/cluster_cursor_stats.cpp @10gen/query-execution-router @svc-auto-approve-bot
/src/mongo/s/**/cluster_write* @10gen/query-execution-router @svc-auto-approve-bot
/src/mongo/s/**/shard_targeting_helpers* @10gen/query-optimization @svc-auto-approve-bot
/src/mongo/s/**/append_raw_responses_test.cpp @10gen/server-networking-and-observability @svc-auto-approve-bot
/src/mongo/s/**/async_requests_sender* @10gen/server-networking-and-observability @svc-auto-approve-bot
/src/mongo/s/**/async_rpc_shard* @10gen/server-networking-and-observability @svc-auto-approve-bot
@ -3139,6 +3138,8 @@ WORKSPACE.bazel @10gen/devprod-build @svc-auto-approve-bot
/src/mongo/s/query/**/OWNERS.yml @10gen/query-execution-staff-leads @10gen/query-integration-staff-leads @10gen/query-optimization-staff-leads @svc-auto-approve-bot
/src/mongo/s/query/**/document_source_visitor_docs_needed_bounds* @10gen/query-integration-search @svc-auto-approve-bot
/src/mongo/s/query/**/shard_key_pattern_query_util* @10gen/query-optimization @svc-auto-approve-bot
/src/mongo/s/query/**/shard_targeting_collation_helpers* @10gen/query-optimization @svc-auto-approve-bot
/src/mongo/s/query/**/shard_targeting_helpers* @10gen/query-optimization @svc-auto-approve-bot
# The following patterns are parsed from ./src/mongo/s/query/exec/OWNERS.yml
/src/mongo/s/query/exec/**/* @10gen/query-execution-router @svc-auto-approve-bot

View File

@ -230,9 +230,10 @@ query:
- src/mongo/replay
- src/mongo/scripting/
- src/mongo/s/commands/query_cmd
- src/mongo/s/shard_targeting_helpers*
- src/mongo/s/query/planner
- src/mongo/s/query/shard_key_pattern_query_util*
- src/mongo/s/query/shard_targeting_collation_helpers*
- src/mongo/s/query/shard_targeting_helpers*
- src/mongo/db/namespace_spec.idl # only used by query
- src/mongo/s/commands/*document_shard_key_*
- src/mongo/util/safe_num*

View File

@ -46,7 +46,7 @@
#include "mongo/db/query/collation/collation_index_key.h"
#include "mongo/db/server_feature_flags_gen.h"
#include "mongo/db/sharding_environment/mongod_and_mongos_server_parameters_gen.h"
#include "mongo/s/shard_targeting_helpers.h"
#include "mongo/s/query/shard_targeting_collation_helpers.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/str.h"

View File

@ -1009,6 +1009,7 @@ mongo_cc_library(
"//src/mongo/s:async_requests_sender",
"//src/mongo/s:sharding_router_api",
"//src/mongo/s/query:cluster_query_knobs",
"//src/mongo/s/query:shard_targeting_helpers",
"//src/mongo/s/query/exec:cluster_cursor",
],
)

View File

@ -97,6 +97,7 @@
#include "mongo/s/query/exec/async_results_merger_params_gen.h"
#include "mongo/s/query/exec/document_source_merge_cursors.h"
#include "mongo/s/query/exec/establish_cursors.h"
#include "mongo/s/query/shard_targeting_helpers.h"
#include "mongo/s/query_analysis_sampler_util.h"
#include "mongo/s/transaction_router.h"
#include "mongo/util/assert_util.h"

View File

@ -43,7 +43,7 @@
#include "mongo/db/storage/storage_options.h"
#include "mongo/db/timeseries/timeseries_index_schema_conversion_functions.h"
#include "mongo/s/query/shard_key_pattern_query_util.h"
#include "mongo/s/shard_targeting_helpers.h"
#include "mongo/s/query/shard_targeting_collation_helpers.h"
#include "mongo/util/assert_util.h"
#include <boost/optional/optional.hpp>

View File

@ -182,7 +182,7 @@ mongo_cc_library(
"//src/mongo/db/storage:recovery_unit_base",
"//src/mongo/db/storage/key_string",
"//src/mongo/db/timeseries:bucket_compression",
"//src/mongo/s:sharding_helpers",
"//src/mongo/s/query:sharding_helpers",
"//src/mongo/stdx",
"//src/mongo/util:string_listset",
],

View File

@ -46,7 +46,6 @@
#include "mongo/db/query/client_cursor/cursor_response.h"
#include "mongo/db/query/collation/collator_factory_interface.h"
#include "mongo/db/query/collation/collator_interface.h"
#include "mongo/db/query/query_planner_common.h"
#include "mongo/db/read_concern_support_result.h"
#include "mongo/db/repl/read_concern_args.h"
#include "mongo/db/repl/read_concern_gen.h"
@ -942,67 +941,6 @@ bool appendEmptyResultSet(OperationContext* opCtx,
return true;
}
std::set<ShardId> getTargetedShardsForQuery(boost::intrusive_ptr<ExpressionContext> expCtx,
const CollectionRoutingInfo& cri,
const BSONObj& query,
const BSONObj& collation) {
if (cri.hasRoutingTable()) {
// The collection has a routing table. Use it to decide which shards to target based on the
// query and collation.
std::set<ShardId> shardIds;
getShardIdsForQuery(expCtx, query, collation, cri.getChunkManager(), &shardIds);
return shardIds;
}
// The collection does not have a routing table. Target only the primary shard for the database.
return {cri.getDbPrimaryShardId()};
}
std::set<ShardId> getTargetedShardsForCanonicalQuery(const CanonicalQuery& query,
const CollectionRoutingInfo& cri) {
if (cri.hasRoutingTable()) {
const auto& cm = cri.getChunkManager();
// The collection has a routing table. Use it to decide which shards to target based on the
// query and collation.
// If the query has a hint or geo expression, fall back to re-creating a find command from
// scratch. Hint can interfere with query planning, which we rely on for targeting. Shard
// targeting modifies geo queries and this helper shouldn't have a side effect on 'query'.
const auto& findCommand = query.getFindCommandRequest();
if (!findCommand.getHint().isEmpty() ||
QueryPlannerCommon::hasNode(query.getPrimaryMatchExpression(),
MatchExpression::GEO_NEAR)) {
return getTargetedShardsForQuery(
query.getExpCtx(), cri, findCommand.getFilter(), findCommand.getCollation());
}
query.getExpCtx()->setUUID(cm.getUUID());
// 'getShardIdsForCanonicalQuery' assumes that the ExpressionContext has the appropriate
// collation set. Here, if the query collation is empty, we use the collection default
// collation for targeting.
const auto& collation = query.getFindCommandRequest().getCollation();
if (collation.isEmpty() && cm.getDefaultCollator()) {
auto defaultCollator = cm.getDefaultCollator();
query.getExpCtx()->setCollator(defaultCollator->clone());
}
std::set<ShardId> shardIds;
getShardIdsForCanonicalQuery(query, cm, &shardIds);
return shardIds;
}
// In the event of an untracked collection, we will discover the collection default collation on
// the primary shard. As such, we don't forward the simple collation.
if (query.getFindCommandRequest().getCollation().isEmpty()) {
query.getExpCtx()->setIgnoreCollator();
}
// The collection does not have a routing table. Target only the primary shard for the database.
return {cri.getDbPrimaryShardId()};
}
std::vector<AsyncRequestsSender::Request> getVersionedRequestsForTargetedShards(
OperationContext* opCtx,
const NamespaceString& nss,

View File

@ -456,21 +456,6 @@ bool appendEmptyResultSet(OperationContext* opCtx,
Status status,
const NamespaceString& ns);
/**
* Returns the shards that would be targeted for the given query according to the given routing
* info.
*/
std::set<ShardId> getTargetedShardsForQuery(boost::intrusive_ptr<ExpressionContext> expCtx,
const CollectionRoutingInfo& cri,
const BSONObj& query,
const BSONObj& collation);
/**
* Returns the shards that would be targeted for the given query according to the given routing
* info.
*/
std::set<ShardId> getTargetedShardsForCanonicalQuery(const CanonicalQuery& query,
const CollectionRoutingInfo& cri);
/**
* Determines the shard(s) to which the given query will be targeted, and builds a separate
* versioned copy of the command object for each such shard.

View File

@ -750,6 +750,7 @@ mongo_cc_library(
"//src/mongo/s/commands:cluster_commands_common",
"//src/mongo/s/commands:sharded_cluster_sharding_commands",
"//src/mongo/s/commands/query_cmd:populate_cursor",
"//src/mongo/s/query:shard_targeting_helpers",
],
)

View File

@ -51,19 +51,6 @@ idl_generator(
],
)
mongo_cc_library(
name = "sharding_helpers",
srcs = [
"shard_targeting_helpers.cpp",
],
no_undefined_ref_DO_NOT_USE = False,
deps = [
"//src/mongo:base",
"//src/mongo/db:common",
"//src/mongo/db/query/collation:collator_interface",
],
)
mongo_cc_library(
name = "sharding_router_api",
srcs = [
@ -85,7 +72,6 @@ mongo_cc_library(
":async_requests_sender",
":grid",
":query_analysis_sampler",
":sharding_helpers",
"//src/mongo/db:internal_transactions_feature_flag",
"//src/mongo/db:mongohasher",
"//src/mongo/db:shared_request_handling",
@ -103,6 +89,7 @@ mongo_cc_library(
"//src/mongo/db/stats:transaction_stats",
"//src/mongo/db/timeseries:timeseries_metadata",
"//src/mongo/rpc:command_status",
"//src/mongo/s/query:sharding_helpers",
"//src/mongo/s/query/exec:target_write_op",
"//src/mongo/util/concurrency:spin_lock",
],
@ -349,7 +336,6 @@ mongo_cc_library(
deps = [
":add_shard_idl",
":analyze_shard_key_common",
":sharding_helpers",
"//src/mongo/client:connection_string",
"//src/mongo/client:read_preference",
"//src/mongo/db:common",
@ -372,6 +358,7 @@ mongo_cc_library(
"//src/mongo/executor:async_rpc_error_info",
"//src/mongo/executor:scoped_task_executor",
"//src/mongo/rpc:command_status",
"//src/mongo/s/query:sharding_helpers",
"//src/mongo/util:caching",
],
)

View File

@ -49,9 +49,6 @@ filters:
- "cluster_write*":
approvers:
- 10gen/query-execution-router
- "shard_targeting_helpers*":
approvers:
- 10gen/query-optimization
- "append_raw_responses_test.cpp":
approvers:
- 10gen/server-networking-and-observability

View File

@ -57,6 +57,7 @@
#include "mongo/s/query/exec/cluster_cursor_manager.h"
#include "mongo/s/query/exec/collect_query_stats_mongos.h"
#include "mongo/s/query/planner/cluster_aggregate.h"
#include "mongo/s/query/shard_targeting_helpers.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/modules.h"
#include "mongo/util/timer.h"

View File

@ -61,6 +61,7 @@
#include "mongo/s/commands/query_cmd/cluster_explain.h"
#include "mongo/s/query/planner/cluster_aggregate.h"
#include "mongo/s/query/planner/cluster_find.h"
#include "mongo/s/query/shard_targeting_helpers.h"
#include "mongo/util/modules.h"
#include <boost/optional.hpp>

View File

@ -32,3 +32,26 @@ mongo_cc_library(
"//src/mongo/s/query/exec:router_exec_stage",
],
)
mongo_cc_library(
name = "sharding_helpers",
srcs = [
"shard_targeting_collation_helpers.cpp",
],
no_undefined_ref_DO_NOT_USE = False,
deps = [
"//src/mongo:base",
"//src/mongo/db:common",
"//src/mongo/db/query/collation:collator_interface",
],
)
mongo_cc_library(
name = "shard_targeting_helpers",
srcs = [
"shard_targeting_helpers.cpp",
],
deps = [
"//src/mongo/s:sharding_router_api",
],
)

View File

@ -21,3 +21,9 @@ filters:
- "shard_key_pattern_query_util*":
approvers:
- 10gen/query-optimization
- "shard_targeting_collation_helpers*":
approvers:
- 10gen/query-optimization
- "shard_targeting_helpers*":
approvers:
- 10gen/query-optimization

View File

@ -54,6 +54,7 @@ mongo_cc_library(
"//src/mongo/db/query/util:cluster_find_util",
"//src/mongo/db/shard_role/shard_catalog:collection_uuid_mismatch_info",
"//src/mongo/s:sharding_router_api",
"//src/mongo/s/query:shard_targeting_helpers",
"//src/mongo/s/query/exec:cluster_cursor",
"//src/mongo/util/concurrency:spin_lock",
],

View File

@ -111,6 +111,7 @@
#include "mongo/s/query/exec/cluster_query_result.h"
#include "mongo/s/query/exec/collect_query_stats_mongos.h"
#include "mongo/s/query/exec/establish_cursors.h"
#include "mongo/s/query/shard_targeting_helpers.h"
#include "mongo/s/query_analysis_sampler_util.h"
#include "mongo/s/transaction_router.h"
#include "mongo/stdx/thread.h"

View File

@ -61,7 +61,6 @@
#include "mongo/db/shard_role/shard_catalog/index_descriptor.h"
#include "mongo/db/update/path_support.h"
#include "mongo/logv2/log.h"
#include "mongo/s/shard_targeting_helpers.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/intrusive_counter.h"
#include "mongo/util/transitional_tools_do_not_use/vector_spooling.h"

View File

@ -27,7 +27,7 @@
* it in the license file.
*/
#include "mongo/s/shard_targeting_helpers.h"
#include "mongo/s/query/shard_targeting_collation_helpers.h"
#include "mongo/db/query/collation/collation_index_key.h"

View File

@ -0,0 +1,98 @@
/**
* Copyright (C) 2024-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.
*/
#include "mongo/s/query/shard_targeting_helpers.h"
#include "mongo/db/query/query_planner_common.h"
#include "mongo/s/query/shard_key_pattern_query_util.h"
namespace mongo {
std::set<ShardId> getTargetedShardsForQuery(boost::intrusive_ptr<ExpressionContext> expCtx,
const CollectionRoutingInfo& cri,
const BSONObj& query,
const BSONObj& collation) {
if (cri.hasRoutingTable()) {
// The collection has a routing table. Use it to decide which shards to target based on the
// query and collation.
std::set<ShardId> shardIds;
getShardIdsForQuery(expCtx, query, collation, cri.getChunkManager(), &shardIds);
return shardIds;
}
// The collection does not have a routing table. Target only the primary shard for the database.
return {cri.getDbPrimaryShardId()};
}
std::set<ShardId> getTargetedShardsForCanonicalQuery(const CanonicalQuery& query,
const CollectionRoutingInfo& cri) {
if (cri.hasRoutingTable()) {
const auto& cm = cri.getChunkManager();
// The collection has a routing table. Use it to decide which shards to target based on the
// query and collation.
// If the query has a hint or geo expression, fall back to re-creating a find command from
// scratch. Hint can interfere with query planning, which we rely on for targeting. Shard
// targeting modifies geo queries and this helper shouldn't have a side effect on 'query'.
const auto& findCommand = query.getFindCommandRequest();
if (!findCommand.getHint().isEmpty() ||
QueryPlannerCommon::hasNode(query.getPrimaryMatchExpression(),
MatchExpression::GEO_NEAR)) {
return getTargetedShardsForQuery(
query.getExpCtx(), cri, findCommand.getFilter(), findCommand.getCollation());
}
query.getExpCtx()->setUUID(cm.getUUID());
// 'getShardIdsForCanonicalQuery' assumes that the ExpressionContext has the appropriate
// collation set. Here, if the query collation is empty, we use the collection default
// collation for targeting.
const auto& collation = query.getFindCommandRequest().getCollation();
if (collation.isEmpty() && cm.getDefaultCollator()) {
auto defaultCollator = cm.getDefaultCollator();
query.getExpCtx()->setCollator(defaultCollator->clone());
}
std::set<ShardId> shardIds;
getShardIdsForCanonicalQuery(query, cm, &shardIds);
return shardIds;
}
// In the event of an untracked collection, we will discover the collection default collation on
// the primary shard. As such, we don't forward the simple collation.
if (query.getFindCommandRequest().getCollation().isEmpty()) {
query.getExpCtx()->setIgnoreCollator();
}
// The collection does not have a routing table. Target only the primary shard for the database.
return {cri.getDbPrimaryShardId()};
}
} // namespace mongo

View File

@ -0,0 +1,53 @@
/**
* Copyright (C) 2024-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/db/pipeline/expression_context.h"
#include "mongo/db/router_role/routing_cache/catalog_cache.h"
#include "mongo/db/sharding_environment/shard_id.h"
namespace mongo {
/**
* Returns the shards that would be targeted for the given query according to the given routing
* info.
*/
std::set<ShardId> getTargetedShardsForQuery(boost::intrusive_ptr<ExpressionContext> expCtx,
const CollectionRoutingInfo& cri,
const BSONObj& query,
const BSONObj& collation);
/**
* Returns the shards that would be targeted for the given query according to the given routing
* info.
*/
std::set<ShardId> getTargetedShardsForCanonicalQuery(const CanonicalQuery& query,
const CollectionRoutingInfo& cri);
} // namespace mongo