Repository: ClickHouse/ClickHouse
File: src/Storages/buildQueryTreeForShard.cpp (C++)

Code before:
                    }
                }
            }

            for (const auto & child : current->getChildren())
            {
                if (child)
                    nodes_to_visit.push(child);
            }
        }

        if (subquery_projection_nodes.empty())
        {
            auto constant_data_type = std::make_shared<DataTypeUInt64>();
            subquery_projection_nodes.push_back(std::make_shared<ConstantNode>(1UL, constant_data_type));
            projection_columns.push_back({"1", std::move(constant_data_type)});
        }

        auto context_copy = Context::createCopy(context);
        updateContextForSubqueryExecution(context_copy);

        auto query_node = std::make_shared<QueryNode>(std::move(context_copy));
        query_node->getProjection().getNodes() = std::move(subquery_projection_nodes);
        query_node->resolveProjectionColumns(std::move(projection_columns));
        query_node->getJoinTree() = join_table_expression;
        query_node->setIsSubquery(true);

        subquery_node = query_node;
    }
    else
    {
        throw Exception(
            ErrorCodes::LOGICAL_ERROR,
            "Expected JOIN table expression to be table, table function, query or union node. Actual {}",
            join_table_expression->formatASTForErrorMessage());
    }

    return subquery_node;
}

}

QueryTreeNodePtr buildQueryTreeForShard(const PlannerContextPtr & planner_context, QueryTreeNodePtr query_tree_to_modify, bool allow_global_join_for_right_table)
{
    CollectColumnSourceToColumnsVisitor collect_column_source_to_columns_visitor;
    collect_column_source_to_columns_visitor.visit(query_tree_to_modify);

    const auto & column_source_to_columns = collect_column_source_to_columns_visitor.getColumnSourceToColumns();

    DistributedProductModeRewriteInJoinVisitor visitor(planner_context->getQueryContext());
    visitor.visit(query_tree_to_modify);

Review comment (suggestion):
It looks like we just need to call `buildSubqueryToReadColumnsFromTableExpression` as we do for tables and table functions.

Code after:
                }
            }

            for (const auto & child : current->getChildren())
                if (child)
                    nodes_to_visit.push_back(child);
        }

        if (subquery_projection_nodes.empty())
        {
            auto constant_data_type = std::make_shared<DataTypeUInt64>();
            subquery_projection_nodes.push_back(std::make_shared<ConstantNode>(1UL, constant_data_type));
            projection_columns.push_back({"1", std::move(constant_data_type)});
        }

        auto context_copy = Context::createCopy(context);
        updateContextForSubqueryExecution(context_copy);

        auto query_node = std::make_shared<QueryNode>(std::move(context_copy));
        query_node->getProjection().getNodes() = std::move(subquery_projection_nodes);
        query_node->resolveProjectionColumns(std::move(projection_columns));
        query_node->getJoinTree() = join_table_expression;
        query_node->setIsSubquery(true);

        subquery_node = query_node;
    }
    else
    {
        throw Exception(
            ErrorCodes::LOGICAL_ERROR,
            "Expected JOIN table expression to be table, table function, query or union node. Actual {}",
            join_table_expression->formatASTForErrorMessage());
    }

    return subquery_node;
}

}

QueryTreeNodePtr buildQueryTreeForShard(const PlannerContextPtr & planner_context, QueryTreeNodePtr query_tree_to_modify, bool allow_global_join_for_right_table)
{
    CollectColumnSourceToColumnsVisitor collect_column_source_to_columns_visitor;
    collect_column_source_to_columns_visitor.visit(query_tree_to_modify);

    const auto & column_source_to_columns = collect_column_source_to_columns_visitor.getColumnSourceToColumns();

    DistributedProductModeRewriteInJoinVisitor visitor(planner_context->getQueryContext());
    visitor.visit(query_tree_to_modify);

    auto replacement_map = visitor.getReplacementMap();
    const auto & global_in_or_join_nodes = visitor.getGlobalInOrJoinNodes();