Execute subquery node and put result in mutable context temporary table. * Returns table node that is initialized with temporary table storage. */
| 414 | * Returns table node that is initialized with temporary table storage. |
| 415 | */ |
| 416 | TableNodePtr executeSubqueryNode(const QueryTreeNodePtr & subquery_node, |
| 417 | ContextMutablePtr & mutable_context, |
| 418 | size_t subquery_depth) |
| 419 | { |
| 420 | const auto subquery_hash = subquery_node->getTreeHash(); |
| 421 | const auto temporary_table_name = fmt::format("_data_{}", toString(subquery_hash)); |
| 422 | |
| 423 | const auto & external_tables = mutable_context->getExternalTables(); |
| 424 | auto external_table_it = external_tables.find(temporary_table_name); |
| 425 | if (external_table_it != external_tables.end()) |
| 426 | { |
| 427 | auto temporary_table_expression_node = std::make_shared<TableNode>(external_table_it->second, mutable_context); |
| 428 | temporary_table_expression_node->setTemporaryTableName(temporary_table_name); |
| 429 | return temporary_table_expression_node; |
| 430 | } |
| 431 | |
| 432 | auto subquery_options = SelectQueryOptions(QueryProcessingStage::Complete, subquery_depth, true /*is_subquery*/); |
| 433 | /// Force materialization of CTEs in subqueries, if they used in the subquery. |
| 434 | subquery_options.forceMaterializeCTE(); |
| 435 | auto context_copy = Context::createCopy(mutable_context); |
| 436 | updateContextForSubqueryExecution(context_copy); |
| 437 | |
| 438 | InterpreterSelectQueryAnalyzer interpreter(subquery_node, context_copy, subquery_options); |
| 439 | auto & query_plan = interpreter.getQueryPlan(); |
| 440 | |
| 441 | auto sample_block_with_unique_names = *query_plan.getCurrentHeader(); |
| 442 | makeUniqueColumnNamesInBlock(sample_block_with_unique_names); |
| 443 | |
| 444 | if (!blocksHaveEqualStructure(sample_block_with_unique_names, *query_plan.getCurrentHeader())) |
| 445 | { |
| 446 | auto actions_dag = ActionsDAG::makeConvertingActions( |
| 447 | query_plan.getCurrentHeader()->getColumnsWithTypeAndName(), |
| 448 | sample_block_with_unique_names.getColumnsWithTypeAndName(), |
| 449 | ActionsDAG::MatchColumnsMode::Position, |
| 450 | context_copy); |
| 451 | auto converting_step = std::make_unique<ExpressionStep>(query_plan.getCurrentHeader(), std::move(actions_dag)); |
| 452 | query_plan.addStep(std::move(converting_step)); |
| 453 | } |
| 454 | |
| 455 | auto sample = interpreter.getSampleBlock(); |
| 456 | NamesAndTypesList columns = sample->getNamesAndTypesList(); |
| 457 | |
| 458 | auto external_storage_holder = TemporaryTableHolder( |
| 459 | mutable_context, |
| 460 | ColumnsDescription(columns), |
| 461 | ConstraintsDescription{}, |
| 462 | nullptr /*query*/, |
| 463 | true /*create_for_global_subquery*/); |
| 464 | |
| 465 | StoragePtr external_storage = external_storage_holder.getTable(); |
| 466 | auto temporary_table_expression_node = std::make_shared<TableNode>(external_storage, mutable_context); |
| 467 | temporary_table_expression_node->setTemporaryTableName(temporary_table_name); |
| 468 | |
| 469 | QueryPlanOptimizationSettings optimization_settings(mutable_context); |
| 470 | BuildQueryPipelineSettings build_pipeline_settings(mutable_context); |
| 471 | auto builder = query_plan.buildQueryPipeline(optimization_settings, build_pipeline_settings); |
| 472 | |
| 473 | size_t min_block_size_rows = mutable_context->getSettingsRef()[Setting::min_external_table_block_size_rows]; |
no test coverage detected