| 599 | } |
| 600 | |
| 601 | QueryTreeNodePtr buildQueryTreeForShard(const PlannerContextPtr & planner_context, QueryTreeNodePtr query_tree_to_modify, bool allow_global_join_for_right_table) |
| 602 | { |
| 603 | CollectColumnSourceToColumnsVisitor collect_column_source_to_columns_visitor; |
| 604 | collect_column_source_to_columns_visitor.visit(query_tree_to_modify); |
| 605 | |
| 606 | const auto & column_source_to_columns = collect_column_source_to_columns_visitor.getColumnSourceToColumns(); |
| 607 | |
| 608 | DistributedProductModeRewriteInJoinVisitor visitor(planner_context->getQueryContext()); |
| 609 | visitor.visit(query_tree_to_modify); |
| 610 | |
| 611 | auto replacement_map = visitor.getReplacementMap(); |
| 612 | const auto & global_in_or_join_nodes = visitor.getGlobalInOrJoinNodes(); |
| 613 | |
| 614 | QueryTreeNodePtrWithHashMap<TableNodePtr> global_in_temporary_tables; |
| 615 | |
| 616 | bool enable_add_distinct_to_in_subqueries = planner_context->getQueryContext()->getSettingsRef()[Setting::enable_add_distinct_to_in_subqueries]; |
| 617 | |
| 618 | for (const auto & global_in_or_join_node : global_in_or_join_nodes) |
| 619 | { |
| 620 | if (auto * join_node = global_in_or_join_node.query_node->as<JoinNode>()) |
| 621 | { |
| 622 | QueryTreeNodePtr join_table_expression; |
| 623 | const auto join_kind = join_node->getKind(); |
| 624 | if (!allow_global_join_for_right_table || join_kind == JoinKind::Left || join_kind == JoinKind::Inner) |
| 625 | { |
| 626 | join_table_expression = join_node->getRightTableExpression(); |
| 627 | } |
| 628 | else if (join_kind == JoinKind::Right) |
| 629 | { |
| 630 | join_table_expression = join_node->getLeftTableExpression(); |
| 631 | } |
| 632 | else |
| 633 | { |
| 634 | throw Exception(ErrorCodes::INCOMPATIBLE_TYPE_OF_JOIN, "Unexpected global join kind: {}", toString(join_kind)); |
| 635 | } |
| 636 | |
| 637 | auto subquery_node = getSubqueryFromTableExpression(join_table_expression, column_source_to_columns, planner_context->getQueryContext()); |
| 638 | |
| 639 | auto temporary_table_expression_node = executeSubqueryNode(subquery_node, |
| 640 | planner_context->getMutableQueryContext(), |
| 641 | global_in_or_join_node.subquery_depth); |
| 642 | temporary_table_expression_node->setAlias(join_table_expression->getAlias()); |
| 643 | |
| 644 | /** When a compound node like ARRAY_JOIN is replaced, its descendants (e.g., the inner TABLE) |
| 645 | * are not traversed by cloneAndReplace. Column nodes that reference these descendants |
| 646 | * as their source would get dangling weak pointers when the original tree is released. |
| 647 | * Map all descendants of the replaced node to the temporary table so that |
| 648 | * weak pointer updates in cloneAndReplace can find them. |
| 649 | */ |
| 650 | std::vector<const IQueryTreeNode *> descendants_to_map; |
| 651 | for (const auto & child : join_table_expression->getChildren()) |
| 652 | if (child) |
| 653 | descendants_to_map.push_back(child.get()); |
| 654 | |
| 655 | while (!descendants_to_map.empty()) |
| 656 | { |
| 657 | const auto * descendant = descendants_to_map.back(); |
| 658 | descendants_to_map.pop_back(); |
no test coverage detected