| 1870 | } |
| 1871 | |
| 1872 | JoinTreeQueryPlan buildQueryPlanForArrayJoinNode(const QueryTreeNodePtr & array_join_table_expression, |
| 1873 | JoinTreeQueryPlan join_tree_query_plan, |
| 1874 | const ColumnIdentifierSet & outer_scope_columns, |
| 1875 | PlannerContextPtr & planner_context) |
| 1876 | { |
| 1877 | auto & array_join_node = array_join_table_expression->as<ArrayJoinNode &>(); |
| 1878 | if (join_tree_query_plan.stage != QueryProcessingStage::FetchColumns) |
| 1879 | throw Exception(ErrorCodes::UNSUPPORTED_METHOD, |
| 1880 | "ARRAY JOIN {} table expression expected to process query to fetch columns stage. Actual {}", |
| 1881 | array_join_node.formatASTForErrorMessage(), |
| 1882 | QueryProcessingStage::toString(join_tree_query_plan.stage)); |
| 1883 | |
| 1884 | auto plan = std::move(join_tree_query_plan.query_plan); |
| 1885 | auto plan_output_columns = plan.getCurrentHeader()->getColumnsWithTypeAndName(); |
| 1886 | |
| 1887 | ActionsDAG array_join_action_dag(plan_output_columns); |
| 1888 | ColumnNodePtrWithHashSet empty_correlated_columns_set; |
| 1889 | PlannerActionsVisitor actions_visitor(planner_context, empty_correlated_columns_set); |
| 1890 | std::unordered_set<std::string> array_join_expressions_output_nodes; |
| 1891 | |
| 1892 | Names array_join_column_names; |
| 1893 | array_join_column_names.reserve(array_join_node.getJoinExpressions().getNodes().size()); |
| 1894 | for (auto & array_join_expression : array_join_node.getJoinExpressions().getNodes()) |
| 1895 | { |
| 1896 | const auto & array_join_column_identifier = planner_context->getColumnNodeIdentifierOrThrow(array_join_expression); |
| 1897 | array_join_column_names.push_back(array_join_column_identifier); |
| 1898 | |
| 1899 | auto & array_join_expression_column = array_join_expression->as<ColumnNode &>(); |
| 1900 | auto [expression_dag_index_nodes, correlated_subtrees] = actions_visitor.visit(array_join_action_dag, array_join_expression_column.getExpressionOrThrow()); |
| 1901 | correlated_subtrees.assertEmpty("in ARRAY JOIN"); |
| 1902 | |
| 1903 | for (auto & expression_dag_index_node : expression_dag_index_nodes) |
| 1904 | { |
| 1905 | const auto * array_join_column_node = &array_join_action_dag.addAlias(*expression_dag_index_node, array_join_column_identifier); |
| 1906 | array_join_action_dag.getOutputs().push_back(array_join_column_node); |
| 1907 | array_join_expressions_output_nodes.insert(array_join_column_node->result_name); |
| 1908 | } |
| 1909 | } |
| 1910 | |
| 1911 | array_join_action_dag.appendInputsForUnusedColumns(*plan.getCurrentHeader()); |
| 1912 | |
| 1913 | auto array_join_actions = std::make_unique<ExpressionStep>(plan.getCurrentHeader(), std::move(array_join_action_dag)); |
| 1914 | array_join_actions->setStepDescription("ARRAY JOIN actions"); |
| 1915 | appendSetsFromActionsDAG(array_join_actions->getExpression(), join_tree_query_plan.useful_sets); |
| 1916 | plan.addStep(std::move(array_join_actions)); |
| 1917 | |
| 1918 | ActionsDAG drop_unused_columns_before_array_join_actions_dag(plan.getCurrentHeader()->getColumnsWithTypeAndName()); |
| 1919 | ActionsDAG::NodeRawConstPtrs drop_unused_columns_before_array_join_actions_dag_updated_outputs; |
| 1920 | std::unordered_set<std::string_view> drop_unused_columns_before_array_join_actions_dag_updated_outputs_names; |
| 1921 | |
| 1922 | auto & drop_unused_columns_before_array_join_actions_dag_outputs = drop_unused_columns_before_array_join_actions_dag.getOutputs(); |
| 1923 | size_t drop_unused_columns_before_array_join_actions_dag_outputs_size = drop_unused_columns_before_array_join_actions_dag_outputs.size(); |
| 1924 | |
| 1925 | for (size_t i = 0; i < drop_unused_columns_before_array_join_actions_dag_outputs_size; ++i) |
| 1926 | { |
| 1927 | const auto & output = drop_unused_columns_before_array_join_actions_dag_outputs[i]; |
| 1928 | |
| 1929 | if (drop_unused_columns_before_array_join_actions_dag_updated_outputs_names.contains(output->result_name)) |
no test coverage detected