diff --git a/src/Interpreters/ActionsVisitor.cpp b/src/Interpreters/ActionsVisitor.cpp index f756a138a28..13c48e9dcca 100644 --- a/src/Interpreters/ActionsVisitor.cpp +++ b/src/Interpreters/ActionsVisitor.cpp @@ -526,6 +526,7 @@ bool ActionsMatcher::needChildVisit(const ASTPtr & node, const ASTPtr & child) { /// Visit children themself if (node->as() || + node->as() || node->as() || node->as() || node->as()) @@ -543,6 +544,8 @@ void ActionsMatcher::visit(const ASTPtr & ast, Data & data) { if (const auto * identifier = ast->as()) visit(*identifier, ast, data); + else if (const auto * table = ast->as()) + visit(*table, ast, data); else if (const auto * node = ast->as()) visit(*node, ast, data); else if (const auto * literal = ast->as()) @@ -659,9 +662,9 @@ void ActionsMatcher::visit(ASTExpressionList & expression_list, const ASTPtr &, } } -void ActionsMatcher::visit(const ASTIdentifier & identifier, const ASTPtr & ast, Data & data) +void ActionsMatcher::visit(const ASTIdentifier & identifier, const ASTPtr &, Data & data) { - auto column_name = ast->getColumnName(); + auto column_name = identifier.getColumnName(); if (data.hasColumn(column_name)) return; @@ -1004,7 +1007,7 @@ SetPtr ActionsMatcher::makeSet(const ASTFunction & node, Data & data, bool no_su const ASTPtr & right_in_operand = args.children.at(1); /// If the subquery or table name for SELECT. - const auto * identifier = right_in_operand->as(); + const auto * identifier = right_in_operand->as(); if (right_in_operand->as() || identifier) { if (no_subqueries) diff --git a/src/Interpreters/GlobalSubqueriesVisitor.h b/src/Interpreters/GlobalSubqueriesVisitor.h index 3c765a0e3a6..4df9da14651 100644 --- a/src/Interpreters/GlobalSubqueriesVisitor.h +++ b/src/Interpreters/GlobalSubqueriesVisitor.h @@ -158,9 +158,7 @@ public: static bool needChildVisit(ASTPtr &, const ASTPtr & child) { /// We do not go into subqueries. - if (child->as()) - return false; - return true; + return !child->as(); } private: diff --git a/src/Interpreters/MarkTableIdentifiersVisitor.cpp b/src/Interpreters/MarkTableIdentifiersVisitor.cpp index 554fa7dacaa..d77941e476d 100644 --- a/src/Interpreters/MarkTableIdentifiersVisitor.cpp +++ b/src/Interpreters/MarkTableIdentifiersVisitor.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -24,29 +25,35 @@ void MarkTableIdentifiersMatcher::visit(ASTPtr & ast, Data & data) visit(*node_func, ast, data); } -void MarkTableIdentifiersMatcher::visit(const ASTFunction & func, ASTPtr &, Data & data) +void MarkTableIdentifiersMatcher::visit(const ASTFunction & func, ASTPtr & ptr, Data & data) { /// `IN t` can be specified, where t is a table, which is equivalent to `IN (SELECT * FROM t)`. if (checkFunctionIsInOrGlobalInOperator(func)) { - auto & ast = func.arguments->children.at(1); + auto ast = func.arguments->children.at(1); auto opt_name = tryGetIdentifierName(ast); if (opt_name && !data.aliases.count(*opt_name)) - setIdentifierSpecial(ast); + { + ptr = func.clone(); + ptr->as()->arguments->children[1] = ast->as()->createTable(); + assert(ptr->as()->arguments->children[1]); + } } // First argument of joinGet can be a table name, perhaps with a database. // First argument of dictGet can be a dictionary name, perhaps with a database. - if (functionIsJoinGet(func.name) || functionIsDictGet(func.name)) + else if (functionIsJoinGet(func.name) || functionIsDictGet(func.name)) { if (func.arguments->children.empty()) - { return; - } auto & ast = func.arguments->children.at(0); auto opt_name = tryGetIdentifierName(ast); if (opt_name && !data.aliases.count(*opt_name)) - setIdentifierSpecial(ast); + { + ptr = func.clone(); + ptr->as()->arguments->children[0] = ast->as()->createTable(); + assert(ptr->as()->arguments->children[0]); + } } } diff --git a/src/Parsers/ASTIdentifier.cpp b/src/Parsers/ASTIdentifier.cpp index 3f9fd36f348..7b4270f875d 100644 --- a/src/Parsers/ASTIdentifier.cpp +++ b/src/Parsers/ASTIdentifier.cpp @@ -142,6 +142,13 @@ void ASTIdentifier::restoreTable() } } +std::shared_ptr ASTIdentifier::createTable() const +{ + if (name_parts.size() == 1) return std::make_shared(name_parts[0]); + if (name_parts.size() == 2) return std::make_shared(name_parts[0], name_parts[1]); + return nullptr; +} + void ASTIdentifier::resetFullName() { full_name = name_parts[0]; diff --git a/src/Parsers/ASTIdentifier.h b/src/Parsers/ASTIdentifier.h index 7a6ce5e3589..223fe689b80 100644 --- a/src/Parsers/ASTIdentifier.h +++ b/src/Parsers/ASTIdentifier.h @@ -14,10 +14,11 @@ struct IdentifierSemantic; struct IdentifierSemanticImpl; struct StorageID; +class ASTTableIdentifier; + /// Generic identifier. ASTTableIdentifier - for table identifier. class ASTIdentifier : public ASTWithAlias { - friend class ReplaceQueryParameterVisitor; public: explicit ASTIdentifier(const String & short_name, ASTPtr && name_param = {}); explicit ASTIdentifier(std::vector && name_parts, bool special = false, std::vector && name_params = {}); @@ -44,6 +45,7 @@ public: const String & name() const; void restoreTable(); // TODO(ilezhankin): get rid of this + std::shared_ptr createTable() const; // return |nullptr| if identifier is not table. protected: String full_name; @@ -56,10 +58,9 @@ protected: private: using ASTWithAlias::children; /// ASTIdentifier is child free + friend class ReplaceQueryParameterVisitor; friend struct IdentifierSemantic; - friend ASTPtr createTableIdentifier(const StorageID & table_id); friend void setIdentifierSpecial(ASTPtr & ast); - friend StorageID getTableIdentifier(const ASTPtr & ast); void resetFullName(); }; diff --git a/utils/simple-backport/format-changelog.py b/utils/simple-backport/format-changelog.py index 9fa42246e12..91547befed4 100755 --- a/utils/simple-backport/format-changelog.py +++ b/utils/simple-backport/format-changelog.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3.8 +#!/usr/bin/python3 import argparse import collections