2019-02-11 19:53:55 +00:00
|
|
|
#include <Interpreters/InterpreterExplainQuery.h>
|
2018-09-21 15:20:23 +00:00
|
|
|
|
|
|
|
#include <DataStreams/BlockIO.h>
|
2019-02-11 19:53:55 +00:00
|
|
|
#include <DataStreams/OneBlockInputStream.h>
|
2018-09-21 15:20:23 +00:00
|
|
|
#include <DataTypes/DataTypeString.h>
|
2020-02-05 08:22:25 +00:00
|
|
|
#include <Interpreters/InDepthNodeVisitor.h>
|
2020-02-06 00:30:14 +00:00
|
|
|
#include <Interpreters/IdentifierSemantic.h>
|
|
|
|
#include <Interpreters/getTableExpressions.h>
|
2019-02-11 19:53:55 +00:00
|
|
|
#include <Interpreters/InterpreterSelectWithUnionQuery.h>
|
2018-10-09 14:32:11 +00:00
|
|
|
#include <Parsers/DumpASTNode.h>
|
2020-02-05 08:22:25 +00:00
|
|
|
#include <Parsers/ASTSubquery.h>
|
2019-02-11 19:53:55 +00:00
|
|
|
#include <Parsers/queryToString.h>
|
2020-02-06 00:30:14 +00:00
|
|
|
#include <Parsers/ASTIdentifier.h>
|
2020-02-05 08:22:25 +00:00
|
|
|
#include <Parsers/ASTExplainQuery.h>
|
|
|
|
#include <Parsers/ASTTablesInSelectQuery.h>
|
|
|
|
#include <Parsers/ASTSelectWithUnionQuery.h>
|
2020-02-06 00:30:14 +00:00
|
|
|
|
2019-10-04 17:46:36 +00:00
|
|
|
#include <Core/Field.h>
|
2020-02-06 00:30:14 +00:00
|
|
|
#include <Common/typeid_cast.h>
|
2020-02-05 08:22:25 +00:00
|
|
|
#include <Storages/StorageView.h>
|
2019-02-11 19:53:55 +00:00
|
|
|
#include <sstream>
|
2018-09-21 15:20:23 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2020-02-05 08:22:25 +00:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
struct ExplainAnalyzedSyntaxMatcher
|
|
|
|
{
|
|
|
|
struct Data
|
|
|
|
{
|
|
|
|
bool analyzed = false;
|
|
|
|
const Context & context;
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool needChildVisit(ASTPtr &, ASTPtr &) { return true; }
|
|
|
|
|
|
|
|
static void visit(ASTPtr & ast, Data & data)
|
|
|
|
{
|
|
|
|
if (auto * select_query = ast->as<ASTSelectQuery>())
|
|
|
|
visit(*select_query, ast, data);
|
|
|
|
if (auto * union_select_query = ast->as<ASTSelectWithUnionQuery>())
|
|
|
|
visit(*union_select_query, ast, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void visit(ASTSelectQuery & select_query, ASTPtr &, Data & data)
|
|
|
|
{
|
2020-02-06 00:30:14 +00:00
|
|
|
if (!select_query.tables())
|
|
|
|
return;
|
|
|
|
|
2020-02-05 08:22:25 +00:00
|
|
|
for (const auto & child : select_query.tables()->children)
|
|
|
|
{
|
|
|
|
auto * tables_element = child->as<ASTTablesInSelectQueryElement>();
|
|
|
|
|
|
|
|
if (tables_element && tables_element->table_expression)
|
|
|
|
visit(*tables_element->table_expression->as<ASTTableExpression>(), select_query, data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void visit(ASTSelectWithUnionQuery &, ASTPtr & node, Data & data)
|
|
|
|
{
|
|
|
|
if (!data.analyzed)
|
|
|
|
{
|
|
|
|
data.analyzed = true;
|
|
|
|
InterpreterSelectWithUnionQuery interpreter(
|
|
|
|
node, data.context, SelectQueryOptions(QueryProcessingStage::FetchColumns).analyze().modify());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void visit(ASTTableExpression & expression, ASTSelectQuery & select_query, Data & data)
|
|
|
|
{
|
|
|
|
if (data.context.getSettingsRef().enable_optimize_predicate_expression && expression.database_and_table_name)
|
|
|
|
{
|
|
|
|
if (const auto * identifier = expression.database_and_table_name->as<ASTIdentifier>())
|
|
|
|
{
|
2020-03-13 15:41:36 +00:00
|
|
|
auto table_id = data.context.resolveStorageID(*identifier);
|
2020-03-06 20:38:19 +00:00
|
|
|
const auto & storage = DatabaseCatalog::instance().getTable(table_id);
|
2020-02-05 08:22:25 +00:00
|
|
|
|
|
|
|
if (auto * storage_view = dynamic_cast<StorageView *>(storage.get()))
|
|
|
|
storage_view->getRuntimeViewQuery(&select_query, data.context, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
using ExplainAnalyzedSyntaxVisitor = InDepthNodeVisitor<ExplainAnalyzedSyntaxMatcher, true>;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-09-21 15:20:23 +00:00
|
|
|
BlockIO InterpreterExplainQuery::execute()
|
|
|
|
{
|
|
|
|
BlockIO res;
|
|
|
|
res.in = executeImpl();
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Block InterpreterExplainQuery::getSampleBlock()
|
|
|
|
{
|
|
|
|
Block block;
|
|
|
|
|
|
|
|
ColumnWithTypeAndName col;
|
2019-02-11 19:53:55 +00:00
|
|
|
col.name = "explain";
|
2018-09-21 15:20:23 +00:00
|
|
|
col.type = std::make_shared<DataTypeString>();
|
|
|
|
col.column = col.type->createColumn();
|
|
|
|
block.insert(col);
|
|
|
|
|
|
|
|
return block;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BlockInputStreamPtr InterpreterExplainQuery::executeImpl()
|
|
|
|
{
|
2019-03-15 16:14:13 +00:00
|
|
|
const auto & ast = query->as<ASTExplainQuery &>();
|
2019-02-11 19:53:55 +00:00
|
|
|
Block sample_block = getSampleBlock();
|
|
|
|
MutableColumns res_columns = sample_block.cloneEmptyColumns();
|
2018-09-21 15:20:23 +00:00
|
|
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
2019-02-11 19:53:55 +00:00
|
|
|
if (ast.getKind() == ASTExplainQuery::ParsedAST)
|
|
|
|
{
|
|
|
|
dumpAST(ast, ss);
|
|
|
|
}
|
|
|
|
else if (ast.getKind() == ASTExplainQuery::AnalyzedSyntax)
|
|
|
|
{
|
2020-02-05 08:22:25 +00:00
|
|
|
ExplainAnalyzedSyntaxVisitor::Data data{.context = context};
|
|
|
|
ExplainAnalyzedSyntaxVisitor(data).visit(query);
|
|
|
|
|
|
|
|
ast.children.at(0)->format(IAST::FormatSettings(ss, false));
|
2019-02-11 19:53:55 +00:00
|
|
|
}
|
|
|
|
|
2018-09-21 15:20:23 +00:00
|
|
|
res_columns[0]->insert(ss.str());
|
|
|
|
|
|
|
|
return std::make_shared<OneBlockInputStream>(sample_block.cloneWithColumns(std::move(res_columns)));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|