diff --git a/src/Analyzer/ColumnNode.cpp b/src/Analyzer/ColumnNode.cpp index 86b9f940e44..15a59770423 100644 --- a/src/Analyzer/ColumnNode.cpp +++ b/src/Analyzer/ColumnNode.cpp @@ -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 diff --git a/src/Analyzer/ColumnNode.h b/src/Analyzer/ColumnNode.h index 8300b2485bb..2b182da2ae3 100644 --- a/src/Analyzer/ColumnNode.h +++ b/src/Analyzer/ColumnNode.h @@ -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; diff --git a/src/Analyzer/ColumnTransformers.cpp b/src/Analyzer/ColumnTransformers.cpp index c6a3945950b..9bcc1bb2d02 100644 --- a/src/Analyzer/ColumnTransformers.cpp +++ b/src/Analyzer/ColumnTransformers.cpp @@ -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'; diff --git a/src/Analyzer/ColumnTransformers.h b/src/Analyzer/ColumnTransformers.h index e5e82033ec8..5956824ebd7 100644 --- a/src/Analyzer/ColumnTransformers.h +++ b/src/Analyzer/ColumnTransformers.h @@ -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; diff --git a/src/Analyzer/ConstantNode.cpp b/src/Analyzer/ConstantNode.cpp index a6c6189d03a..92d9b56d5cf 100644 --- a/src/Analyzer/ConstantNode.cpp +++ b/src/Analyzer/ConstantNode.cpp @@ -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 diff --git a/src/Analyzer/ConstantNode.h b/src/Analyzer/ConstantNode.h index ed605f03256..02fd6a2c65f 100644 --- a/src/Analyzer/ConstantNode.h +++ b/src/Analyzer/ConstantNode.h @@ -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; diff --git a/src/Analyzer/FunctionNode.cpp b/src/Analyzer/FunctionNode.cpp index 30e2a5a8dd0..195e9306cdb 100644 --- a/src/Analyzer/FunctionNode.cpp +++ b/src/Analyzer/FunctionNode.cpp @@ -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); } } diff --git a/src/Analyzer/FunctionNode.h b/src/Analyzer/FunctionNode.h index 657b81811df..2020afe89df 100644 --- a/src/Analyzer/FunctionNode.h +++ b/src/Analyzer/FunctionNode.h @@ -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; diff --git a/src/Analyzer/IQueryTreeNode.cpp b/src/Analyzer/IQueryTreeNode.cpp index 710ebb01561..01977651180 100644 --- a/src/Analyzer/IQueryTreeNode.cpp +++ b/src/Analyzer/IQueryTreeNode.cpp @@ -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()) diff --git a/src/Analyzer/IQueryTreeNode.h b/src/Analyzer/IQueryTreeNode.h index 1df296ab3de..17a7a481789 100644 --- a/src/Analyzer/IQueryTreeNode.h +++ b/src/Analyzer/IQueryTreeNode.h @@ -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 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. */ diff --git a/src/Analyzer/IdentifierNode.cpp b/src/Analyzer/IdentifierNode.cpp index 510a9cec93c..5275ec8c586 100644 --- a/src/Analyzer/IdentifierNode.cpp +++ b/src/Analyzer/IdentifierNode.cpp @@ -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 diff --git a/src/Analyzer/IdentifierNode.h b/src/Analyzer/IdentifierNode.h index 38f909173f4..06bde3d4e0a 100644 --- a/src/Analyzer/IdentifierNode.h +++ b/src/Analyzer/IdentifierNode.h @@ -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; diff --git a/src/Analyzer/LambdaNode.cpp b/src/Analyzer/LambdaNode.cpp index bd0d9f117dc..52778b30c5d 100644 --- a/src/Analyzer/LambdaNode.cpp +++ b/src/Analyzer/LambdaNode.cpp @@ -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 diff --git a/src/Analyzer/LambdaNode.h b/src/Analyzer/LambdaNode.h index a49bf780e12..dc005f2b120 100644 --- a/src/Analyzer/LambdaNode.h +++ b/src/Analyzer/LambdaNode.h @@ -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; diff --git a/src/Analyzer/ListNode.cpp b/src/Analyzer/ListNode.cpp index e7f14c62ac2..ffd72a3990e 100644 --- a/src/Analyzer/ListNode.cpp +++ b/src/Analyzer/ListNode.cpp @@ -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'; diff --git a/src/Analyzer/ListNode.h b/src/Analyzer/ListNode.h index 029023b9d8a..413dc964612 100644 --- a/src/Analyzer/ListNode.h +++ b/src/Analyzer/ListNode.h @@ -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; diff --git a/src/Analyzer/MatcherNode.cpp b/src/Analyzer/MatcherNode.cpp index af5b0de4990..3aa70557987 100644 --- a/src/Analyzer/MatcherNode.cpp +++ b/src/Analyzer/MatcherNode.cpp @@ -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); } } diff --git a/src/Analyzer/MatcherNode.h b/src/Analyzer/MatcherNode.h index 1d9d77d9b36..00024801091 100644 --- a/src/Analyzer/MatcherNode.h +++ b/src/Analyzer/MatcherNode.h @@ -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; diff --git a/src/Analyzer/MultiIfToIfPass.h b/src/Analyzer/MultiIfToIfPass.h index fc4859d1769..619a4b965c7 100644 --- a/src/Analyzer/MultiIfToIfPass.h +++ b/src/Analyzer/MultiIfToIfPass.h @@ -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; diff --git a/src/Analyzer/QueryNode.cpp b/src/Analyzer/QueryNode.cpp index 67a66644eb4..a9584752e6d 100644 --- a/src/Analyzer/QueryNode.cpp +++ b/src/Analyzer/QueryNode.cpp @@ -22,44 +22,45 @@ QueryNode::QueryNode() children[projection_child_index] = std::make_shared(); } -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); } } diff --git a/src/Analyzer/QueryNode.h b/src/Analyzer/QueryNode.h index b8d0d6a0d88..6d08bf0642f 100644 --- a/src/Analyzer/QueryNode.h +++ b/src/Analyzer/QueryNode.h @@ -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; diff --git a/src/Analyzer/TableNode.cpp b/src/Analyzer/TableNode.cpp index 647ef9eaf2e..65dbccfd27a 100644 --- a/src/Analyzer/TableNode.cpp +++ b/src/Analyzer/TableNode.cpp @@ -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 diff --git a/src/Analyzer/TableNode.h b/src/Analyzer/TableNode.h index a195d5c2df4..25f6529d489 100644 --- a/src/Analyzer/TableNode.h +++ b/src/Analyzer/TableNode.h @@ -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; diff --git a/src/Analyzer/tests/gtest_query_tree_node.cpp b/src/Analyzer/tests/gtest_query_tree_node.cpp index 56483614bcd..0940aa5861d 100644 --- a/src/Analyzer/tests/gtest_query_tree_node.cpp +++ b/src/Analyzer/tests/gtest_query_tree_node.cpp @@ -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 diff --git a/src/Interpreters/InterpreterExplainQuery.cpp b/src/Interpreters/InterpreterExplainQuery.cpp index dbc742c9cb3..baba2214333 100644 --- a/src/Interpreters/InterpreterExplainQuery.cpp +++ b/src/Interpreters/InterpreterExplainQuery.cpp @@ -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> boolean_settings = { {"run_passes", run_passes}, - {"ast", ast} + {"dump_passes", dump_passes}, + {"dump_ast", dump_ast} }; std::unordered_map> 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(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(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)); diff --git a/src/Parsers/ASTExplainQuery.h b/src/Parsers/ASTExplainQuery.h index f802751b0ec..156ffdeacb9 100644 --- a/src/Parsers/ASTExplainQuery.h +++ b/src/Parsers/ASTExplainQuery.h @@ -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"; diff --git a/src/Parsers/ParserExplainQuery.cpp b/src/Parsers/ParserExplainQuery.cpp index 52d82a29118..62e23202031 100644 --- a/src/Parsers/ParserExplainQuery.cpp +++ b/src/Parsers/ParserExplainQuery.cpp @@ -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");