Update explain query tree representation

This commit is contained in:
Maksim Kita 2022-07-19 12:54:45 +02:00
parent dd28b58864
commit 603c4febc3
27 changed files with 191 additions and 148 deletions

View File

@ -28,13 +28,18 @@ QueryTreeNodePtr ColumnNode::getColumnSource() const
return lock;
}
void ColumnNode::dumpTree(WriteBuffer & buffer, size_t indent) const
void ColumnNode::dumpTreeImpl(WriteBuffer & buffer, FormatState & state, size_t indent) const
{
buffer << std::string(indent, ' ') << "COLUMN ";
writePointerHex(this, buffer);
buffer << ' ' << column.name << " : " << column.type->getName() << " source ";
buffer << std::string(indent, ' ') << "COLUMN id: " << state.getNodeId(this);
if (hasAlias())
buffer << ", alias: " << getAlias();
buffer << ", column_name: " << column.name << ", result_type: " << column.type->getName();
auto column_source_ptr = column_source.lock();
writePointerHex(column_source_ptr.get(), buffer);
if (column_source_ptr)
buffer << ", source_id: " << state.getNodeId(column_source_ptr.get());
}
bool ColumnNode::isEqualImpl(const IQueryTreeNode & rhs) const

View File

@ -67,8 +67,6 @@ public:
return QueryTreeNodeType::COLUMN;
}
void dumpTree(WriteBuffer & buffer, size_t indent) const override;
String getName() const override
{
return column.name;
@ -79,11 +77,13 @@ public:
return column.type;
}
protected:
void dumpTreeImpl(WriteBuffer & buffer, FormatState & state, size_t indent) const override;
bool isEqualImpl(const IQueryTreeNode & rhs) const override;
void updateTreeHashImpl(HashState & hash_state) const override;
protected:
ASTPtr toASTImpl() const override;
QueryTreeNodePtr cloneImpl() const override;

View File

@ -57,16 +57,15 @@ ApplyColumnTransformerNode::ApplyColumnTransformerNode(QueryTreeNodePtr expressi
children[expression_child_index] = std::move(expression_node_);
}
void ApplyColumnTransformerNode::dumpTree(WriteBuffer & buffer, size_t indent) const
void ApplyColumnTransformerNode::dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const
{
buffer << std::string(indent, ' ') << "APPLY COLUMN TRANSFORMER ";
writePointerHex(this, buffer);
buffer << ' ' << toString(apply_transformer_type) << '\n';
buffer << std::string(indent, ' ') << "APPLY COLUMN TRANSFORMER id: " << format_state.getNodeId(this);
buffer << ", apply_transformer_type: " << toString(apply_transformer_type);
buffer << std::string(indent + 2, ' ') << "EXPRESSION" << '\n';
buffer << '\n' << std::string(indent + 2, ' ') << "EXPRESSION" << '\n';
const auto & expression_node = getExpressionNode();
expression_node->dumpTree(buffer, indent + 4);
expression_node->dumpTreeImpl(buffer, format_state, indent + 4);
}
bool ApplyColumnTransformerNode::isEqualImpl(const IQueryTreeNode & rhs) const
@ -136,25 +135,28 @@ const char * toString(ExceptColumnTransformerType type)
}
}
void ExceptColumnTransformerNode::dumpTree(WriteBuffer & buffer, size_t indent) const
void ExceptColumnTransformerNode::dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const
{
buffer << std::string(indent, ' ') << "EXCEPT COLUMN TRANSFORMER ";
writePointerHex(this, buffer);
buffer << ' ' << toString(except_transformer_type) << ' ';
buffer << std::string(indent, ' ') << "EXCEPT COLUMN TRANSFORMER id: " << format_state.getNodeId(this);
buffer << ", except_transformer_type: " << toString(except_transformer_type);
if (column_matcher)
{
buffer << column_matcher->pattern();
buffer << ", pattern: " << column_matcher->pattern();
return;
}
size_t except_column_names_size = except_column_names.size();
for (size_t i = 0; i < except_column_names_size; ++i)
else
{
buffer << except_column_names[i];
buffer << ", identifiers: ";
if (i + 1 != except_column_names_size)
buffer << ", ";
size_t except_column_names_size = except_column_names.size();
for (size_t i = 0; i < except_column_names_size; ++i)
{
buffer << except_column_names[i];
if (i + 1 != except_column_names_size)
buffer << ", ";
}
}
}
@ -259,15 +261,13 @@ QueryTreeNodePtr ReplaceColumnTransformerNode::findReplacementExpression(const s
return replacement_expressions_nodes[replacement_index];
}
void ReplaceColumnTransformerNode::dumpTree(WriteBuffer & buffer, size_t indent) const
void ReplaceColumnTransformerNode::dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const
{
buffer << std::string(indent, ' ') << "REPLACE TRANSFORMER ";
writePointerHex(this, buffer);
buffer << '\n';
buffer << std::string(indent, ' ') << "REPLACE COLUMN TRANSFORMER id: " << format_state.getNodeId(this);
auto & replacements_nodes = getReplacements().getNodes();
size_t replacements_size = replacements_nodes.size();
buffer << std::string(indent + 2, ' ') << "REPLACEMENTS " << replacements_size << '\n';
buffer << '\n' << std::string(indent + 2, ' ') << "REPLACEMENTS " << replacements_size << '\n';
for (size_t i = 0; i < replacements_size; ++i)
{
@ -275,7 +275,7 @@ void ReplaceColumnTransformerNode::dumpTree(WriteBuffer & buffer, size_t indent)
buffer << std::string(indent + 4, ' ') << "REPLACEMENT NAME " << replacement_name;
buffer << " EXPRESSION" << '\n';
const auto & expression_node = replacements_nodes[i];
expression_node->dumpTree(buffer, indent + 6);
expression_node->dumpTreeImpl(buffer, format_state, indent + 6);
if (i + 1 != replacements_size)
buffer << '\n';

View File

@ -129,13 +129,13 @@ public:
return ColumnTransfomerType::APPLY;
}
void dumpTree(WriteBuffer & buffer, size_t indent) const override;
void dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const override;
protected:
bool isEqualImpl(const IQueryTreeNode & rhs) const override;
void updateTreeHashImpl(IQueryTreeNode::HashState & hash_state) const override;
protected:
ASTPtr toASTImpl() const override;
QueryTreeNodePtr cloneImpl() const override;
@ -218,13 +218,13 @@ public:
return ColumnTransfomerType::EXCEPT;
}
void dumpTree(WriteBuffer & buffer, size_t indent) const override;
void dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const override;
protected:
bool isEqualImpl(const IQueryTreeNode & rhs) const override;
void updateTreeHashImpl(IQueryTreeNode::HashState & hash_state) const override;
protected:
ASTPtr toASTImpl() const override;
QueryTreeNodePtr cloneImpl() const override;
@ -294,13 +294,13 @@ public:
*/
QueryTreeNodePtr findReplacementExpression(const std::string & expression_name);
void dumpTree(WriteBuffer & buffer, size_t indent) const override;
void dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const override;
protected:
bool isEqualImpl(const IQueryTreeNode & rhs) const override;
void updateTreeHashImpl(IQueryTreeNode::HashState & hash_state) const override;
protected:
ASTPtr toASTImpl() const override;
QueryTreeNodePtr cloneImpl() const override;

View File

@ -26,11 +26,15 @@ ConstantNode::ConstantNode(Field value_)
, type(applyVisitor(FieldToDataType(), value))
{}
void ConstantNode::dumpTree(WriteBuffer & buffer, size_t indent) const
void ConstantNode::dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const
{
buffer << std::string(indent, ' ') << "CONSTANT ";
writePointerHex(this, buffer);
buffer << ' ' << value.dump() << " : " << type->getName();
buffer << std::string(indent, ' ') << "CONSTANT id: " << format_state.getNodeId(this);
if (hasAlias())
buffer << ", alias: " << getAlias();
buffer << ", value: " << value.dump();
buffer << ", result_type: " << type->getName();
}
bool ConstantNode::isEqualImpl(const IQueryTreeNode & rhs) const

View File

@ -34,8 +34,6 @@ public:
return QueryTreeNodeType::CONSTANT;
}
void dumpTree(WriteBuffer & buffer, size_t indent) const override;
String getName() const override
{
return value_string_dump;
@ -47,6 +45,8 @@ public:
}
protected:
void dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const override;
bool isEqualImpl(const IQueryTreeNode & rhs) const override;
void updateTreeHashImpl(HashState & hash_state) const override;

View File

@ -30,24 +30,30 @@ void FunctionNode::resolveAsAggregateFunction(AggregateFunctionPtr aggregate_fun
function_name = aggregate_function->getName();
}
void FunctionNode::dumpTree(WriteBuffer & buffer, size_t indent) const
void FunctionNode::dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const
{
buffer << std::string(indent, ' ') << "FUNCTION ";
writePointerHex(this, buffer);
buffer << ' ' << function_name << (result_type ? (" : " + result_type->getName()) : "");
buffer << std::string(indent, ' ') << "FUNCTION id: " << format_state.getNodeId(this);
if (hasAlias())
buffer << ", alias: " << getAlias();
buffer << ", function_name: " << function_name;
if (result_type)
buffer << ", result_type: " + result_type->getName();
const auto & parameters = getParameters();
if (!parameters.getNodes().empty())
{
buffer << '\n' << std::string(indent + 2, ' ') << "PARAMETERS\n";
parameters.dumpTree(buffer, indent + 4);
parameters.dumpTreeImpl(buffer, format_state, indent + 4);
}
const auto & arguments = getArguments();
if (!arguments.getNodes().empty())
{
buffer << '\n' << std::string(indent + 2, ' ') << "ARGUMENTS\n";
arguments.dumpTree(buffer, indent + 4);
arguments.dumpTreeImpl(buffer, format_state, indent + 4);
}
}

View File

@ -152,8 +152,6 @@ public:
return QueryTreeNodeType::FUNCTION;
}
void dumpTree(WriteBuffer & buffer, size_t indent) const override;
DataTypePtr getResultType() const override
{
return result_type;
@ -161,11 +159,13 @@ public:
String getName() const override;
protected:
void dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const override;
bool isEqualImpl(const IQueryTreeNode & rhs) const override;
void updateTreeHashImpl(HashState & hash_state) const override;
protected:
ASTPtr toASTImpl() const override;
QueryTreeNodePtr cloneImpl() const override;

View File

@ -38,10 +38,22 @@ const char * toString(QueryTreeNodeType type)
String IQueryTreeNode::dumpTree() const
{
WriteBufferFromOwnString buff;
dumpTree(buff, 0);
dumpTree(buff);
return buff.str();
}
size_t IQueryTreeNode::FormatState::getNodeId(const IQueryTreeNode * node)
{
auto [it, _] = node_to_id.emplace(node, node_to_id.size());
return it->second;
}
void IQueryTreeNode::dumpTree(WriteBuffer & buffer) const
{
FormatState state;
dumpTreeImpl(buffer, state, 0);
}
bool IQueryTreeNode::isEqual(const IQueryTreeNode & rhs) const
{
if (getNodeType() != rhs.getNodeType())

View File

@ -84,13 +84,7 @@ public:
String dumpTree() const;
/// Dump query tree to buffer
void dumpTree(WriteBuffer & buffer) const
{
dumpTree(buffer, 0);
}
/// Dump query tree to buffer starting with indent
virtual void dumpTree(WriteBuffer & buffer, size_t indent) const = 0;
void dumpTree(WriteBuffer & buffer) const;
/** Is tree equal to other tree with node root.
*
@ -179,7 +173,7 @@ public:
if (original_ast)
return formatOriginalASTForErrorMessage();
return formatConvertedASTForErrorMessage();
return formatConvertedASTForErrorMessage();
}
/// Get query tree node children
@ -194,11 +188,26 @@ public:
return children;
}
class FormatState
{
public:
size_t getNodeId(const IQueryTreeNode * node);
private:
std::unordered_map<const IQueryTreeNode *, size_t> node_to_id;
};
/** Dump query tree to buffer starting with indent.
*
* Node must also dump its children.
*/
virtual void dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const = 0;
/** Subclass must compare its internal state with rhs node and do not compare its children with rhs node children.
* Caller must compare node and rhs node children.
*
* This method is not protected because if subclass node has weak pointers to other query tree nodes it must use it
* as part of its isEqualImpl method. In child classes this method should be protected.
* as part of its isEqualImpl method.
*/
virtual bool isEqualImpl(const IQueryTreeNode & rhs) const = 0;
@ -206,11 +215,12 @@ public:
* Caller must update tree hash for node children.
*
* This method is not protected because if subclass node has weak pointers to other query tree nodes it must use it
* as part of its updateTreeHashImpl method. In child classes this method should be protected.
* as part of its updateTreeHashImpl method.
*/
virtual void updateTreeHashImpl(HashState & hash_state) const = 0;
protected:
/** Subclass node must convert itself to AST.
* Subclass must convert children to AST.
*/

View File

@ -10,11 +10,14 @@
namespace DB
{
void IdentifierNode::dumpTree(WriteBuffer & buffer, size_t indent) const
void IdentifierNode::dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const
{
buffer << std::string(indent, ' ') << "IDENTIFIER ";
writePointerHex(this, buffer);
buffer << ' ' << identifier.getFullName();
buffer << std::string(indent, ' ') << "IDENTIFIER id: " << format_state.getNodeId(this);
if (hasAlias())
buffer << ", alias: " << getAlias();
buffer << ", identifier: " << identifier.getFullName();
}
bool IdentifierNode::isEqualImpl(const IQueryTreeNode & rhs) const

View File

@ -32,18 +32,18 @@ public:
return QueryTreeNodeType::IDENTIFIER;
}
void dumpTree(WriteBuffer & buffer, size_t indent) const override;
String getName() const override
{
return identifier.getFullName();
}
protected:
void dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const override;
bool isEqualImpl(const IQueryTreeNode & rhs) const override;
void updateTreeHashImpl(HashState & state) const override;
protected:
ASTPtr toASTImpl() const override;
QueryTreeNodePtr cloneImpl() const override;

View File

@ -27,21 +27,27 @@ LambdaNode::LambdaNode(Names argument_names_, QueryTreeNodePtr expression_)
children[expression_child_index] = std::move(expression_);
}
void LambdaNode::dumpTree(WriteBuffer & buffer, size_t indent) const
void LambdaNode::dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const
{
auto result_type = getExpression()->getResultType();
buffer << std::string(indent, ' ') << "LAMBDA ";
writePointerHex(this, buffer);
buffer << (result_type ? (" : " + result_type->getName()) : "") << '\n';
buffer << std::string(indent, ' ') << "LAMBDA id: " << format_state.getNodeId(this);
buffer << std::string(indent + 2, ' ') << "ARGUMENTS " << '\n';
getArguments().dumpTree(buffer, indent + 4);
if (hasAlias())
buffer << ", alias: " << getAlias();
buffer << '\n';
if (result_type)
buffer << ", result_type: " << result_type->getName();
buffer << std::string(indent + 2, ' ') << "EXPRESSION " << '\n';
getExpression()->dumpTree(buffer, indent + 4);
const auto & arguments = getArguments();
if (!arguments.getNodes().empty())
{
buffer << '\n' << std::string(indent + 2, ' ') << "ARGUMENTS " << '\n';
getArguments().dumpTreeImpl(buffer, format_state, indent + 4);
}
buffer << '\n' << std::string(indent + 2, ' ') << "EXPRESSION " << '\n';
getExpression()->dumpTreeImpl(buffer, format_state, indent + 4);
}
String LambdaNode::getName() const

View File

@ -88,8 +88,6 @@ public:
return QueryTreeNodeType::LAMBDA;
}
void dumpTree(WriteBuffer & buffer, size_t indent) const override;
String getName() const override;
DataTypePtr getResultType() const override
@ -97,11 +95,13 @@ public:
return getExpression()->getResultType();
}
protected:
void dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const override;
bool isEqualImpl(const IQueryTreeNode & rhs) const override;
void updateTreeHashImpl(HashState & state) const override;
protected:
ASTPtr toASTImpl() const override;
QueryTreeNodePtr cloneImpl() const override;

View File

@ -11,17 +11,17 @@
namespace DB
{
void ListNode::dumpTree(WriteBuffer & buffer, size_t indent) const
void ListNode::dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const
{
buffer << std::string(indent, ' ') << "LIST id: " << format_state.getNodeId(this);
size_t children_size = children.size();
buffer << std::string(indent, ' ') << "LIST ";
writePointerHex(this, buffer);
buffer << ' ' << children_size << '\n';
buffer << ", nodes: " << children_size << '\n';
for (size_t i = 0; i < children_size; ++i)
{
const auto & node = children[i];
node->dumpTree(buffer, indent + 2);
node->dumpTreeImpl(buffer, format_state, indent + 2);
if (i + 1 != children_size)
buffer << '\n';

View File

@ -33,15 +33,15 @@ public:
return QueryTreeNodeType::LIST;
}
void dumpTree(WriteBuffer & buffer, size_t indent) const override;
String getName() const override;
protected:
void dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const override;
bool isEqualImpl(const IQueryTreeNode & rhs) const override;
void updateTreeHashImpl(HashState &) const override;
protected:
ASTPtr toASTImpl() const override;
QueryTreeNodePtr cloneImpl() const override;

View File

@ -119,23 +119,22 @@ bool MatcherNode::isMatchingColumn(const std::string & column_name)
return columns_identifiers_set.find(column_name) != columns_identifiers_set.end();
}
void MatcherNode::dumpTree(WriteBuffer & buffer, size_t indent) const
void MatcherNode::dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const
{
buffer << std::string(indent, ' ') << "MATCHER ";
writePointerHex(this, buffer);
buffer << std::string(indent, ' ') << "MATCHER id: " << format_state.getNodeId(this);
buffer << ", matcher_type: " << toString(matcher_type);
if (!qualified_identifier.empty())
buffer << ' ' << qualified_identifier.getFullName();
buffer << ' ' << toString(matcher_type);
buffer << ", qualified_identifier: " << qualified_identifier.getFullName();
if (columns_matcher)
{
buffer << ' ' << columns_matcher->pattern();
buffer << ", columns_pattern: " << columns_matcher->pattern();
}
else if (matcher_type == MatcherNodeType::COLUMNS_LIST)
{
buffer << ' ';
buffer << ", columns_identifiers: ";
size_t columns_identifiers_size = columns_identifiers.size();
for (size_t i = 0; i < columns_identifiers_size; ++i)
{
@ -150,7 +149,7 @@ void MatcherNode::dumpTree(WriteBuffer & buffer, size_t indent) const
if (!column_transformers_list.getNodes().empty())
{
buffer << '\n';
column_transformers_list.dumpTree(buffer, indent + 2);
column_transformers_list.dumpTreeImpl(buffer, format_state, indent + 2);
}
}

View File

@ -141,15 +141,15 @@ public:
return QueryTreeNodeType::ASTERISK;
}
void dumpTree(WriteBuffer & buffer, size_t indent) const override;
String getName() const override;
protected:
void dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const override;
bool isEqualImpl(const IQueryTreeNode & rhs) const override;
void updateTreeHashImpl(HashState & hash_state) const override;
protected:
ASTPtr toASTImpl() const override;
QueryTreeNodePtr cloneImpl() const override;

View File

@ -15,7 +15,7 @@ public:
String getName() override { return "MultiIfToIf"; }
String getDescription() override { return "Optimize multiIf to if for single argument"; }
String getDescription() override { return "Optimize multiIf to if for single argument."; }
void run(QueryTreeNodePtr query_tree_node, ContextPtr context) override;

View File

@ -22,44 +22,45 @@ QueryNode::QueryNode()
children[projection_child_index] = std::make_shared<ListNode>();
}
void QueryNode::dumpTree(WriteBuffer & buffer, size_t indent) const
void QueryNode::dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const
{
buffer << std::string(indent, ' ') << "QUERY ";
writePointerHex(this, buffer);
buffer << std::string(indent, ' ') << "QUERY id: " << format_state.getNodeId(this);
if (hasAlias())
buffer << " alias : " << getAlias();
buffer << ", alias: " << getAlias();
buffer << " subquery : " << is_subquery;
buffer << " cte : " << is_cte;
buffer << " cte_name : " << cte_name;
buffer << ", is_subquery: " << is_subquery;
buffer << ", is_cte: " << is_cte;
if (!cte_name.empty())
buffer << ", cte_name: " << cte_name;
if (!getWith().getNodes().empty())
{
buffer << '\n' << std::string(indent + 2, ' ') << "WITH\n";
getWith().dumpTree(buffer, indent + 4);
getWith().dumpTreeImpl(buffer, format_state, indent + 4);
}
buffer << '\n';
buffer << std::string(indent + 2, ' ') << "PROJECTION\n";
getProjection().dumpTree(buffer, indent + 4);
getProjection().dumpTreeImpl(buffer, format_state, indent + 4);
if (getFrom())
{
buffer << '\n' << std::string(indent + 2, ' ') << "JOIN TREE\n";
getFrom()->dumpTree(buffer, indent + 4);
getFrom()->dumpTreeImpl(buffer, format_state, indent + 4);
}
if (getPrewhere())
{
buffer << '\n' << std::string(indent + 2, ' ') << "PREWHERE\n";
getPrewhere()->dumpTree(buffer, indent + 4);
getPrewhere()->dumpTreeImpl(buffer, format_state, indent + 4);
}
if (getWhere())
{
buffer << '\n' << std::string(indent + 2, ' ') << "WHERE\n";
getWhere()->dumpTree(buffer, indent + 4);
getWhere()->dumpTreeImpl(buffer, format_state, indent + 4);
}
}

View File

@ -122,13 +122,13 @@ public:
return QueryTreeNodeType::QUERY;
}
void dumpTree(WriteBuffer & buffer, size_t indent) const override;
void dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const override;
protected:
bool isEqualImpl(const IQueryTreeNode & rhs) const override;
void updateTreeHashImpl(HashState &) const override;
protected:
ASTPtr toASTImpl() const override;
QueryTreeNodePtr cloneImpl() const override;

View File

@ -21,11 +21,14 @@ TableNode::TableNode(StoragePtr storage_, ContextPtr context)
{
}
void TableNode::dumpTree(WriteBuffer & buffer, size_t indent) const
void TableNode::dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const
{
buffer << std::string(indent, ' ') << "TABLE ";
writePointerHex(this, buffer);
buffer << ' ' << storage_id.getFullNameNotQuoted();
buffer << std::string(indent, ' ') << "TABLE id: " << format_state.getNodeId(this);
if (hasAlias())
buffer << ", alias: " << getAlias();
buffer << ", table_name: " << storage_id.getFullNameNotQuoted();
}
bool TableNode::isEqualImpl(const IQueryTreeNode & rhs) const

View File

@ -66,15 +66,15 @@ public:
return QueryTreeNodeType::TABLE;
}
void dumpTree(WriteBuffer & buffer, size_t indent) const override;
String getName() const override;
protected:
void dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const override;
bool isEqualImpl(const IQueryTreeNode & rhs) const override;
void updateTreeHashImpl(HashState & state) const override;
protected:
ASTPtr toASTImpl() const override;
QueryTreeNodePtr cloneImpl() const override;

View File

@ -16,10 +16,8 @@ public:
return QueryTreeNodeType::TABLE;
}
void dumpTree(WriteBuffer & buffer, size_t indent) const override
void dumpTreeImpl(WriteBuffer &, FormatState &, size_t) const override
{
(void)(buffer);
(void)(indent);
}
bool isEqualImpl(const IQueryTreeNode &) const override
@ -27,9 +25,8 @@ public:
return true;
}
void updateTreeHashImpl(HashState & hash_state) const override
void updateTreeHashImpl(HashState &) const override
{
(void)(hash_state);
}
ASTPtr toASTImpl() const override

View File

@ -165,15 +165,17 @@ struct QueryASTSettings
struct QueryTreeSettings
{
bool run_passes = false;
bool dump_passes = false;
bool dump_ast = false;
Int64 passes = -1;
bool ast = false;
constexpr static char name[] = "QUERYTREE";
constexpr static char name[] = "QUERY TREE";
std::unordered_map<std::string, std::reference_wrapper<bool>> boolean_settings =
{
{"run_passes", run_passes},
{"ast", ast}
{"dump_passes", dump_passes},
{"dump_ast", dump_ast}
};
std::unordered_map<std::string, std::reference_wrapper<Int64>> integer_settings =
@ -381,30 +383,25 @@ QueryPipeline InterpreterExplainQuery::executeImpl()
auto query_tree_pass_manager = QueryTreePassManager(getContext());
addQueryTreePasses(query_tree_pass_manager);
if (settings.passes < 0)
size_t pass_index = settings.passes < 0 ? query_tree_pass_manager.getPasses().size() : static_cast<size_t>(settings.passes);
if (settings.dump_passes)
{
query_tree_pass_manager.dump(buf);
buf << '\n';
query_tree_pass_manager.run(query_tree);
}
else
{
size_t pass_index = static_cast<size_t>(settings.passes);
query_tree_pass_manager.dump(buf, pass_index);
if (pass_index > 0)
buf << '\n';
query_tree_pass_manager.run(query_tree, pass_index);
}
query_tree->dumpTree(buf, 0);
query_tree_pass_manager.run(query_tree, pass_index);
query_tree->dumpTree(buf);
}
else
{
query_tree->dumpTree(buf, 0);
query_tree->dumpTree(buf);
}
if (settings.ast)
if (settings.dump_ast)
{
buf << '\n';
query_tree->toAST()->format(IAST::FormatSettings(buf, false));

View File

@ -15,7 +15,7 @@ public:
{
ParsedAST, /// 'EXPLAIN AST SELECT ...'
AnalyzedSyntax, /// 'EXPLAIN SYNTAX SELECT ...'
QueryTree, /// 'EXPLAIN QUERYTREE SELECT ...'
QueryTree, /// 'EXPLAIN QUERY TREE SELECT ...'
QueryPlan, /// 'EXPLAIN SELECT ...'
QueryPipeline, /// 'EXPLAIN PIPELINE ...'
QueryEstimates, /// 'EXPLAIN ESTIMATE ...'
@ -110,7 +110,7 @@ private:
{
case ParsedAST: return "EXPLAIN AST";
case AnalyzedSyntax: return "EXPLAIN SYNTAX";
case QueryTree: return "EXPLAIN QUERYTREE";
case QueryTree: return "EXPLAIN QUERY TREE";
case QueryPlan: return "EXPLAIN";
case QueryPipeline: return "EXPLAIN PIPELINE";
case QueryEstimates: return "EXPLAIN ESTIMATE";

View File

@ -19,7 +19,7 @@ bool ParserExplainQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected
ParserKeyword s_ast("AST");
ParserKeyword s_explain("EXPLAIN");
ParserKeyword s_syntax("SYNTAX");
ParserKeyword s_query_tree("QUERYTREE");
ParserKeyword s_query_tree("QUERY TREE");
ParserKeyword s_pipeline("PIPELINE");
ParserKeyword s_plan("PLAN");
ParserKeyword s_estimates("ESTIMATE");