#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int INCORRECT_QUERY; } namespace { struct ExplainAnalyzedSyntaxMatcher { struct Data { const Context & context; }; static bool needChildVisit(ASTPtr & node, ASTPtr &) { return !node->as(); } static void visit(ASTPtr & ast, Data & data) { if (auto * select = ast->as()) visit(*select, ast, data); } static void visit(ASTSelectQuery & select, ASTPtr & node, Data & data) { InterpreterSelectQuery interpreter( node, data.context, SelectQueryOptions(QueryProcessingStage::FetchColumns).analyze().modify()); const SelectQueryInfo & query_info = interpreter.getQueryInfo(); if (query_info.view_query) { ASTPtr tmp; StorageView::replaceWithSubquery(select, query_info.view_query->clone(), tmp); } } }; using ExplainAnalyzedSyntaxVisitor = InDepthNodeVisitor; } BlockIO InterpreterExplainQuery::execute() { BlockIO res; res.in = executeImpl(); return res; } Block InterpreterExplainQuery::getSampleBlock() { Block block; ColumnWithTypeAndName col; col.name = "explain"; col.type = std::make_shared(); col.column = col.type->createColumn(); block.insert(col); return block; } static void fillColumn(IColumn & column, const std::string & str) { size_t start = 0; size_t end = 0; size_t size = str.size(); while (end < size) { if (str[end] == '\n') { column.insertData(str.data() + start, end - start); start = end + 1; } ++end; } if (start < end) column.insertData(str.data() + start, end - start); } BlockInputStreamPtr InterpreterExplainQuery::executeImpl() { const auto & ast = query->as(); Block sample_block = getSampleBlock(); MutableColumns res_columns = sample_block.cloneEmptyColumns(); std::stringstream ss; if (ast.getKind() == ASTExplainQuery::ParsedAST) { dumpAST(ast, ss); } else if (ast.getKind() == ASTExplainQuery::AnalyzedSyntax) { ExplainAnalyzedSyntaxVisitor::Data data{.context = context}; ExplainAnalyzedSyntaxVisitor(data).visit(query); ast.children.at(0)->format(IAST::FormatSettings(ss, false)); } else if (ast.getKind() == ASTExplainQuery::QueryPlan) { if (!dynamic_cast(ast.getExplainedQuery().get())) throw Exception("Only SELECT is supported for EXPLAIN query", ErrorCodes::INCORRECT_QUERY); QueryPlan plan; InterpreterSelectWithUnionQuery interpreter(ast.getExplainedQuery(), context, SelectQueryOptions()); interpreter.buildQueryPlan(plan); WriteBufferFromOStream buffer(ss); plan.explain(buffer); } fillColumn(*res_columns[0], ss.str()); return std::make_shared(sample_block.cloneWithColumns(std::move(res_columns))); } }