| 624 | } |
| 625 | |
| 626 | QueryPipeline InterpreterExplainQuery::executeImpl() |
| 627 | { |
| 628 | const auto & ast = query->as<const ASTExplainQuery &>(); |
| 629 | |
| 630 | Block sample_block = getSampleBlock(ast.getKind()); |
| 631 | MutableColumns res_columns = sample_block.cloneEmptyColumns(); |
| 632 | |
| 633 | WriteBufferFromOwnString buf; |
| 634 | bool single_line = false; |
| 635 | bool insert_buf = true; |
| 636 | |
| 637 | ContextPtr query_context = getContext(); |
| 638 | |
| 639 | options.setExplain(); |
| 640 | options.max_step_description_length = query_context->getSettingsRef()[Setting::query_plan_max_step_description_length]; |
| 641 | |
| 642 | /// https://github.com/ClickHouse/ClickHouse/issues/88467 |
| 643 | /// EXPLAIN is to get a good picture of how the query will execute after *static* planning. |
| 644 | /// Hence disable any optimizations that stagger the planning or introduce variablility due to caches. |
| 645 | auto explain_query_context = Context::createCopy(query_context); |
| 646 | explain_query_context->setSetting("use_skip_indexes_on_data_read", false); |
| 647 | explain_query_context->setSetting("use_query_condition_cache", false); |
| 648 | InterpreterSetQuery::applySettingsFromQuery(query, explain_query_context); |
| 649 | query_context = std::move(explain_query_context); |
| 650 | |
| 651 | switch (ast.getKind()) |
| 652 | { |
| 653 | case ASTExplainQuery::ParsedAST: |
| 654 | { |
| 655 | auto settings = checkAndGetSettings<QueryASTSettings>(ast.getSettings()); |
| 656 | if (settings.optimize) |
| 657 | { |
| 658 | ExplainAnalyzedSyntaxVisitor::Data data(query_context); |
| 659 | ExplainAnalyzedSyntaxVisitor(data).visit(query); |
| 660 | } |
| 661 | |
| 662 | if (settings.graph) |
| 663 | dumpASTInDotFormat(*ast.getExplainedQuery(), buf); |
| 664 | else |
| 665 | dumpAST(*ast.getExplainedQuery(), buf); |
| 666 | break; |
| 667 | } |
| 668 | case ASTExplainQuery::AnalyzedSyntax: |
| 669 | { |
| 670 | auto settings = checkAndGetSettings<QuerySyntaxSettings>(ast.getSettings()); |
| 671 | |
| 672 | /// Inline any parameterized view calls with their parameter-substituted inner queries, |
| 673 | /// so EXPLAIN SYNTAX shows what the view actually expands to. |
| 674 | ExpandParameterizedViewsMatcher::Data expand_views_data(query_context); |
| 675 | ExpandParameterizedViewsVisitor(expand_views_data).visit(query); |
| 676 | |
| 677 | if (query_context->getSettingsRef()[Setting::allow_experimental_analyzer]) |
| 678 | { |
| 679 | bool explain_ok = explainQueryTree(ast.getExplainedQuery(), query_context, QueryTreeSettings{ |
| 680 | .run_passes = settings.run_query_tree_passes, |
| 681 | .dump_tree = false, |
| 682 | .dump_passes = false, |
| 683 | .dump_ast = true, |
nothing calls this directly
no test coverage detected