| 1940 | } |
| 1941 | |
| 1942 | void Planner::buildPlanForUnionNode() |
| 1943 | { |
| 1944 | const auto & union_node = query_tree->as<UnionNode &>(); |
| 1945 | auto union_mode = union_node.getUnionMode(); |
| 1946 | if (union_mode == SelectUnionMode::UNION_DEFAULT || union_mode == SelectUnionMode::EXCEPT_DEFAULT |
| 1947 | || union_mode == SelectUnionMode::INTERSECT_DEFAULT) |
| 1948 | throw Exception(ErrorCodes::BAD_ARGUMENTS, "UNION mode must be initialized"); |
| 1949 | |
| 1950 | if (union_node.hasRecursiveCTETable()) |
| 1951 | { |
| 1952 | const auto & recursive_cte_table = *union_node.getRecursiveCTETable(); |
| 1953 | |
| 1954 | ColumnsWithTypeAndName recursive_cte_columns; |
| 1955 | recursive_cte_columns.reserve(recursive_cte_table.columns.size()); |
| 1956 | for (const auto & recursive_cte_table_column : recursive_cte_table.columns) |
| 1957 | recursive_cte_columns.emplace_back(recursive_cte_table_column.type, recursive_cte_table_column.name); |
| 1958 | |
| 1959 | auto read_from_recursive_cte_step = std::make_unique<ReadFromRecursiveCTEStep>(std::make_shared<const Block>(Block(std::move(recursive_cte_columns))), query_tree); |
| 1960 | read_from_recursive_cte_step->setStepDescription(query_tree->toAST()->formatForErrorMessage(), select_query_options.max_step_description_length); |
| 1961 | query_plan.addStep(std::move(read_from_recursive_cte_step)); |
| 1962 | return; |
| 1963 | } |
| 1964 | |
| 1965 | const auto & union_queries_nodes = union_node.getQueries().getNodes(); |
| 1966 | size_t queries_size = union_queries_nodes.size(); |
| 1967 | |
| 1968 | std::vector<std::unique_ptr<QueryPlan>> query_plans; |
| 1969 | query_plans.reserve(queries_size); |
| 1970 | |
| 1971 | SharedHeaders query_plans_headers; |
| 1972 | query_plans_headers.reserve(queries_size); |
| 1973 | |
| 1974 | for (const auto & query_node : union_queries_nodes) |
| 1975 | { |
| 1976 | Planner query_planner(query_node, select_query_options, planner_context->getGlobalPlannerContext()); |
| 1977 | |
| 1978 | query_planner.buildQueryPlanIfNeeded(); |
| 1979 | for (const auto & row_policy : query_planner.getUsedRowPolicies()) |
| 1980 | used_row_policies.insert(row_policy); |
| 1981 | const auto & mapping = query_planner.getQueryNodeToPlanStepMapping(); |
| 1982 | query_node_to_plan_step_mapping.insert(mapping.begin(), mapping.end()); |
| 1983 | auto query_node_plan = std::make_unique<QueryPlan>(std::move(query_planner).extractQueryPlan()); |
| 1984 | query_plans_headers.push_back(query_node_plan->getCurrentHeader()); |
| 1985 | query_plans.push_back(std::move(query_node_plan)); |
| 1986 | } |
| 1987 | |
| 1988 | Block union_common_header = buildCommonHeaderForUnion( |
| 1989 | query_plans_headers, union_mode, union_node.getContext()->getSettingsRef()[Setting::use_variant_as_common_type]); |
| 1990 | const auto & query_context = planner_context->getQueryContext(); |
| 1991 | addConvertingToCommonHeaderActionsIfNeeded(query_plans, union_common_header, query_plans_headers, query_context); |
| 1992 | const auto & settings = query_context->getSettingsRef(); |
| 1993 | auto max_threads = getMaxThreadsForAvailableMemory( |
| 1994 | settings[Setting::max_threads], settings[Setting::max_threads_min_free_memory_per_thread]); |
| 1995 | |
| 1996 | bool is_distinct = union_mode == SelectUnionMode::UNION_DISTINCT || union_mode == SelectUnionMode::INTERSECT_DISTINCT |
| 1997 | || union_mode == SelectUnionMode::EXCEPT_DISTINCT; |
| 1998 | |
| 1999 | if (union_mode == SelectUnionMode::UNION_ALL || union_mode == SelectUnionMode::UNION_DISTINCT) |
nothing calls this directly
no test coverage detected