simplify InDepthNodeVisitor

This commit is contained in:
chertus 2019-02-22 16:33:56 +03:00
parent 89f4cab025
commit 9e2aa47478
16 changed files with 100 additions and 123 deletions

View File

@ -28,6 +28,8 @@ namespace ErrorCodes
class ArrayJoinedColumnsMatcher
{
public:
using Visitor = InDepthNodeVisitor<ArrayJoinedColumnsMatcher, true>;
struct Data
{
const Aliases & aliases;
@ -36,8 +38,6 @@ public:
NameToNameMap & array_join_result_to_source;
};
static constexpr const char * label = "ArrayJoinedColumns";
static bool needChildVisit(ASTPtr & node, const ASTPtr & child)
{
if (typeid_cast<ASTTablesInSelectQuery *>(node.get()))
@ -50,17 +50,16 @@ public:
return true;
}
static std::vector<ASTPtr *> visit(ASTPtr & ast, Data & data)
static void visit(ASTPtr & ast, Data & data)
{
if (auto * t = typeid_cast<ASTIdentifier *>(ast.get()))
visit(*t, ast, data);
if (auto * t = typeid_cast<ASTSelectQuery *>(ast.get()))
return visit(*t, ast, data);
return {};
visit(*t, ast, data);
}
private:
static std::vector<ASTPtr *> visit(const ASTSelectQuery & node, ASTPtr &, Data & data)
static void visit(const ASTSelectQuery & node, ASTPtr &, Data & data)
{
ASTPtr array_join_expression_list = node.array_join_expression_list();
if (!array_join_expression_list)
@ -87,7 +86,8 @@ private:
out.emplace_back(&child2);
}
return out;
for (ASTPtr * add_node : out)
Visitor(data).visit(*add_node);
}
static void visit(const ASTIdentifier & node, ASTPtr &, Data & data)
@ -130,6 +130,6 @@ private:
}
};
using ArrayJoinedColumnsVisitor = InDepthNodeVisitor<ArrayJoinedColumnsMatcher, true>;
using ArrayJoinedColumnsVisitor = ArrayJoinedColumnsMatcher::Visitor;
}

View File

@ -181,11 +181,10 @@ static ASTPtr getCrossJoin(ASTSelectQuery & select, std::vector<DatabaseAndTable
}
std::vector<ASTPtr *> CrossToInnerJoinMatcher::visit(ASTPtr & ast, Data & data)
void CrossToInnerJoinMatcher::visit(ASTPtr & ast, Data & data)
{
if (auto * t = typeid_cast<ASTSelectQuery *>(ast.get()))
visit(*t, ast, data);
return {};
}
void CrossToInnerJoinMatcher::visit(ASTSelectQuery & select, ASTPtr & ast, Data & data)

View File

@ -16,10 +16,8 @@ public:
bool done = false;
};
static constexpr const char * label = "JoinToSubqueryTransform";
static bool needChildVisit(ASTPtr &, const ASTPtr &) { return true; }
static std::vector<ASTPtr *> visit(ASTPtr & ast, Data & data);
static void visit(ASTPtr & ast, Data & data);
private:
static void visit(ASTSelectQuery & select, ASTPtr & ast, Data & data);

View File

@ -60,13 +60,12 @@ bool ExecuteScalarSubqueriesMatcher::needChildVisit(ASTPtr & node, const ASTPtr
return true;
}
std::vector<ASTPtr *> ExecuteScalarSubqueriesMatcher::visit(ASTPtr & ast, Data & data)
void ExecuteScalarSubqueriesMatcher::visit(ASTPtr & ast, Data & data)
{
if (auto * t = typeid_cast<ASTSubquery *>(ast.get()))
visit(*t, ast, data);
if (auto * t = typeid_cast<ASTFunction *>(ast.get()))
return visit(*t, ast, data);
return {};
visit(*t, ast, data);
}
void ExecuteScalarSubqueriesMatcher::visit(const ASTSubquery & subquery, ASTPtr & ast, Data & data)
@ -134,7 +133,7 @@ void ExecuteScalarSubqueriesMatcher::visit(const ASTSubquery & subquery, ASTPtr
}
}
std::vector<ASTPtr *> ExecuteScalarSubqueriesMatcher::visit(const ASTFunction & func, ASTPtr & ast, Data &)
void ExecuteScalarSubqueriesMatcher::visit(const ASTFunction & func, ASTPtr & ast, Data & data)
{
/// Don't descend into subqueries in arguments of IN operator.
/// But if an argument is not subquery, than deeper may be scalar subqueries and we need to descend in them.
@ -156,7 +155,8 @@ std::vector<ASTPtr *> ExecuteScalarSubqueriesMatcher::visit(const ASTFunction &
for (auto & child : ast->children)
out.push_back(&child);
return out;
for (ASTPtr * add_node : out)
ExecuteScalarSubqueriesVisitor(data).visit(*add_node);
}
}

View File

@ -36,14 +36,12 @@ public:
size_t subquery_depth;
};
static constexpr const char * label = "ExecuteScalarSubqueries";
static bool needChildVisit(ASTPtr & node, const ASTPtr &);
static std::vector<ASTPtr *> visit(ASTPtr & ast, Data & data);
static void visit(ASTPtr & ast, Data & data);
private:
static void visit(const ASTSubquery & subquery, ASTPtr & ast, Data & data);
static std::vector<ASTPtr *> visit(const ASTFunction & func, ASTPtr & ast, Data & data);
static void visit(const ASTFunction & func, ASTPtr & ast, Data & data);
};
using ExecuteScalarSubqueriesVisitor = InDepthNodeVisitor<ExecuteScalarSubqueriesMatcher, true>;

View File

@ -20,24 +20,20 @@ public:
Tables & external_tables;
};
static constexpr const char * label = "ExternalTables";
static std::vector<ASTPtr *> visit(ASTPtr & ast, Data & data)
static void visit(ASTPtr & ast, Data & data)
{
if (auto * t = typeid_cast<ASTIdentifier *>(ast.get()))
return visit(*t, ast, data);
return {};
visit(*t, ast, data);
}
static bool needChildVisit(ASTPtr &, const ASTPtr &) { return true; }
private:
static std::vector<ASTPtr *> visit(const ASTIdentifier & node, ASTPtr &, Data & data)
static void visit(const ASTIdentifier & node, ASTPtr &, Data & data)
{
if (auto opt_name = IdentifierSemantic::getTableName(node))
if (StoragePtr external_storage = data.context.tryGetExternalTable(*opt_name))
data.external_tables[*opt_name] = external_storage;
return {};
}
};

View File

@ -138,15 +138,12 @@ public:
}
};
static constexpr const char * label = "GlobalSubqueries";
static std::vector<ASTPtr *> visit(ASTPtr & ast, Data & data)
static void visit(ASTPtr & ast, Data & data)
{
if (auto * t = typeid_cast<ASTFunction *>(ast.get()))
visit(*t, ast, data);
if (auto * t = typeid_cast<ASTTablesInSelectQueryElement *>(ast.get()))
visit(*t, ast, data);
return {};
}
static bool needChildVisit(ASTPtr &, const ASTPtr & child)

View File

@ -1,5 +1,6 @@
#pragma once
#include <typeinfo>
#include <vector>
#include <Common/typeid_cast.h>
#include <Parsers/DumpASTNode.h>
@ -8,7 +9,7 @@ namespace DB
{
/// Visits AST tree in depth, call functions for nodes according to Matcher type data.
/// You need to define Data, label, visit() and needChildVisit() in Matcher class.
/// You need to define Data, visit() and needChildVisit() in Matcher class.
template <typename Matcher, bool _top_to_bottom>
class InDepthNodeVisitor
{
@ -23,17 +24,12 @@ public:
void visit(ASTPtr & ast)
{
DumpASTNode dump(*ast, ostr, visit_depth, Matcher::label);
DumpASTNode dump(*ast, ostr, visit_depth, typeid(Matcher).name());
if constexpr (!_top_to_bottom)
visitChildren(ast);
/// It operates with ASTPtr * cause we may want to rewrite ASTPtr in visit().
std::vector<ASTPtr *> additional_nodes = Matcher::visit(ast, data);
/// visit additional nodes (ex. only part of children)
for (ASTPtr * node : additional_nodes)
visit(*node);
Matcher::visit(ast, data);
if constexpr (_top_to_bottom)
visitChildren(ast);
@ -60,15 +56,12 @@ public:
using Data = _Data;
using TypeToVisit = typename Data::TypeToVisit;
static constexpr const char * label = "";
static bool needChildVisit(ASTPtr &, const ASTPtr &) { return _visit_children; }
static std::vector<ASTPtr *> visit(ASTPtr & ast, Data & data)
static void visit(ASTPtr & ast, Data & data)
{
if (auto * t = typeid_cast<TypeToVisit *>(ast.get()))
data.visit(*t, ast);
return {};
}
};
@ -79,15 +72,12 @@ class LinkedMatcher
public:
using Data = std::pair<typename First::Data, typename Second::Data>;
static constexpr const char * label = "";
static bool needChildVisit(ASTPtr &, const ASTPtr &) { return true; }
static std::vector<ASTPtr *> visit(ASTPtr & ast, Data & data)
static void visit(ASTPtr & ast, Data & data)
{
First::visit(ast, data.first);
Second::visit(ast, data.second);
return {};
}
};

View File

@ -79,8 +79,6 @@ struct ColumnAliasesMatcher
}
};
static constexpr const char * label = "ColumnAliases";
static bool needChildVisit(ASTPtr & node, const ASTPtr &)
{
if (typeid_cast<const ASTQualifiedAsterisk *>(node.get()))
@ -88,7 +86,7 @@ struct ColumnAliasesMatcher
return true;
}
static std::vector<ASTPtr *> visit(ASTPtr & ast, Data & data)
static void visit(ASTPtr & ast, Data & data)
{
if (auto * t = typeid_cast<ASTIdentifier *>(ast.get()))
visit(*t, ast, data);
@ -96,7 +94,6 @@ struct ColumnAliasesMatcher
if (typeid_cast<ASTAsterisk *>(ast.get()) ||
typeid_cast<ASTQualifiedAsterisk *>(ast.get()))
throw Exception("Multiple JOIN do not support asterisks yet", ErrorCodes::NOT_IMPLEMENTED);
return {};
}
static void visit(ASTIdentifier & node, ASTPtr &, Data & data)
@ -225,11 +222,10 @@ using AppendSemanticVisitor = InDepthNodeVisitor<AppendSemanticMatcher, true>;
} /// namelesspace
std::vector<ASTPtr *> JoinToSubqueryTransformMatcher::visit(ASTPtr & ast, Data & data)
void JoinToSubqueryTransformMatcher::visit(ASTPtr & ast, Data & data)
{
if (auto * t = typeid_cast<ASTSelectQuery *>(ast.get()))
visit(*t, ast, data);
return {};
}
void JoinToSubqueryTransformMatcher::visit(ASTSelectQuery & select, ASTPtr &, Data & data)

View File

@ -18,10 +18,8 @@ public:
bool done = false;
};
static constexpr const char * label = "JoinToSubqueryTransform";
static bool needChildVisit(ASTPtr &, const ASTPtr &) { return true; }
static std::vector<ASTPtr *> visit(ASTPtr & ast, Data & data);
static void visit(ASTPtr & ast, Data & data);
private:
/// - combines two source TablesInSelectQueryElement into resulting one (Subquery)

View File

@ -33,26 +33,25 @@ bool QueryAliasesMatcher::needChildVisit(ASTPtr & node, const ASTPtr &)
{
/// Don't descent into table functions and subqueries and special case for ArrayJoin.
if (typeid_cast<ASTTableExpression *>(node.get()) ||
typeid_cast<ASTSelectWithUnionQuery *>(node.get()) ||
typeid_cast<ASTSubquery *>(node.get()) ||
typeid_cast<ASTArrayJoin *>(node.get()))
return false;
return true;
}
std::vector<ASTPtr *> QueryAliasesMatcher::visit(ASTPtr & ast, Data & data)
void QueryAliasesMatcher::visit(ASTPtr & ast, Data & data)
{
if (auto * t = typeid_cast<ASTSubquery *>(ast.get()))
return visit(*t, ast, data);
if (auto * t = typeid_cast<ASTArrayJoin *>(ast.get()))
return visit(*t, ast, data);
visitOther(ast, data);
return {};
if (auto * s = typeid_cast<ASTSubquery *>(ast.get()))
visit(*s, ast, data);
else if (auto * aj = typeid_cast<ASTArrayJoin *>(ast.get()))
visit(*aj, ast, data);
else
visitOther(ast, data);
}
/// The top-level aliases in the ARRAY JOIN section have a special meaning, we will not add them
/// (skip the expression list itself and its children).
std::vector<ASTPtr *> QueryAliasesMatcher::visit(const ASTArrayJoin &, const ASTPtr & ast, Data & data)
void QueryAliasesMatcher::visit(const ASTArrayJoin &, const ASTPtr & ast, Data & data)
{
visitOther(ast, data);
@ -64,15 +63,17 @@ std::vector<ASTPtr *> QueryAliasesMatcher::visit(const ASTArrayJoin &, const AST
/// create own visitor to run bottom to top
for (auto & child : grand_children)
QueryAliasesVisitor(data).visit(child);
return {};
Visitor(data).visit(child);
}
/// set unique aliases for all subqueries. this is needed, because:
/// 1) content of subqueries could change after recursive analysis, and auto-generated column names could become incorrect
/// 2) result of different scalar subqueries can be cached inside expressions compilation cache and must have different names
std::vector<ASTPtr *> QueryAliasesMatcher::visit(ASTSubquery & subquery, const ASTPtr & ast, Data & data)
void QueryAliasesMatcher::visit(ASTSubquery & subquery, const ASTPtr & ast, Data & data)
{
if (!data.subqueries)
return;
Aliases & aliases = data.aliases;
static std::atomic_uint64_t subquery_index = 0;
@ -92,7 +93,6 @@ std::vector<ASTPtr *> QueryAliasesMatcher::visit(ASTSubquery & subquery, const A
}
else
visitOther(ast, data);
return {};
}
void QueryAliasesMatcher::visitOther(const ASTPtr & ast, Data & data)

View File

@ -15,23 +15,24 @@ struct ASTArrayJoin;
class QueryAliasesMatcher
{
public:
using Visitor = InDepthNodeVisitor<QueryAliasesMatcher, false>;
struct Data
{
Aliases & aliases;
bool subqueries = true;
};
static constexpr const char * label = "QueryAliases";
static std::vector<ASTPtr *> visit(ASTPtr & ast, Data & data);
static void visit(ASTPtr & ast, Data & data);
static bool needChildVisit(ASTPtr & node, const ASTPtr & child);
private:
static std::vector<ASTPtr *> visit(ASTSubquery & subquery, const ASTPtr & ast, Data & data);
static std::vector<ASTPtr *> visit(const ASTArrayJoin &, const ASTPtr & ast, Data & data);
static void visit(ASTSubquery & subquery, const ASTPtr & ast, Data & data);
static void visit(const ASTArrayJoin &, const ASTPtr & ast, Data & data);
static void visitOther(const ASTPtr & ast, Data & data);
};
/// Visits AST nodes and collect their aliases in one map (with links to source nodes).
using QueryAliasesVisitor = InDepthNodeVisitor<QueryAliasesMatcher, false>;
using QueryAliasesVisitor = QueryAliasesMatcher::Visitor;
}

View File

@ -62,20 +62,20 @@ bool RequiredSourceColumnsMatcher::needChildVisit(ASTPtr & node, const ASTPtr &
return true;
}
std::vector<ASTPtr *> RequiredSourceColumnsMatcher::visit(ASTPtr & ast, Data & data)
void RequiredSourceColumnsMatcher::visit(ASTPtr & ast, Data & data)
{
/// results are columns
if (auto * t = typeid_cast<ASTIdentifier *>(ast.get()))
{
visit(*t, ast, data);
return {};
return;
}
if (auto * t = typeid_cast<ASTFunction *>(ast.get()))
{
data.addColumnAliasIfAny(*ast);
visit(*t, ast, data);
return {};
return;
}
/// results are tables
@ -83,24 +83,25 @@ std::vector<ASTPtr *> RequiredSourceColumnsMatcher::visit(ASTPtr & ast, Data & d
if (auto * t = typeid_cast<ASTTablesInSelectQueryElement *>(ast.get()))
{
visit(*t, ast, data);
return {};
return;
}
if (auto * t = typeid_cast<ASTTableExpression *>(ast.get()))
{
//data.addTableAliasIfAny(*ast); alias is attached to child
visit(*t, ast, data);
return {};
return;
}
if (auto * t = typeid_cast<ASTSelectQuery *>(ast.get()))
{
data.addTableAliasIfAny(*ast);
return visit(*t, ast, data);
visit(*t, ast, data);
return;
}
if (typeid_cast<ASTSubquery *>(ast.get()))
{
data.addTableAliasIfAny(*ast);
return {};
return;
}
/// other
@ -108,13 +109,12 @@ std::vector<ASTPtr *> RequiredSourceColumnsMatcher::visit(ASTPtr & ast, Data & d
if (auto * t = typeid_cast<ASTArrayJoin *>(ast.get()))
{
data.has_array_join = true;
return visit(*t, ast, data);
visit(*t, ast, data);
return;
}
return {};
}
std::vector<ASTPtr *> RequiredSourceColumnsMatcher::visit(ASTSelectQuery & select, const ASTPtr &, Data & data)
void RequiredSourceColumnsMatcher::visit(ASTSelectQuery & select, const ASTPtr &, Data & data)
{
/// special case for top-level SELECT items: they are publics
for (auto & node : select.select_expression_list->children)
@ -132,7 +132,9 @@ std::vector<ASTPtr *> RequiredSourceColumnsMatcher::visit(ASTSelectQuery & selec
/// revisit select_expression_list (with children) when all the aliases are set
out.push_back(&select.select_expression_list);
return out;
for (ASTPtr * add_node : out)
Visitor(data).visit(*add_node);
}
void RequiredSourceColumnsMatcher::visit(const ASTIdentifier & node, const ASTPtr &, Data & data)
@ -180,7 +182,7 @@ void RequiredSourceColumnsMatcher::visit(ASTTablesInSelectQueryElement & node, c
data.tables.emplace_back(ColumnNamesContext::JoinedTable{expr, join});
}
std::vector<ASTPtr *> RequiredSourceColumnsMatcher::visit(ASTTableExpression & node, const ASTPtr &, Data & data)
void RequiredSourceColumnsMatcher::visit(ASTTableExpression & node, const ASTPtr &, Data & data)
{
/// ASTIdentifiers here are tables. Do not visit them as generic ones.
if (node.database_and_table_name)
@ -199,10 +201,11 @@ std::vector<ASTPtr *> RequiredSourceColumnsMatcher::visit(ASTTableExpression & n
out.push_back(&node.subquery);
}
return out;
for (ASTPtr * add_node : out)
Visitor(data).visit(*add_node);
}
std::vector<ASTPtr *> RequiredSourceColumnsMatcher::visit(const ASTArrayJoin & node, const ASTPtr &, Data & data)
void RequiredSourceColumnsMatcher::visit(const ASTArrayJoin & node, const ASTPtr &, Data & data)
{
ASTPtr expression_list = node.expression_list;
if (!expression_list || expression_list->children.empty())
@ -224,7 +227,8 @@ std::vector<ASTPtr *> RequiredSourceColumnsMatcher::visit(const ASTArrayJoin & n
out.push_back(&expr);
}
return out;
for (ASTPtr * add_node : out)
Visitor(data).visit(*add_node);
}
}

View File

@ -21,25 +21,24 @@ struct ASTTableExpression;
class RequiredSourceColumnsMatcher
{
public:
using Visitor = InDepthNodeVisitor<RequiredSourceColumnsMatcher, false>;
using Data = ColumnNamesContext;
static constexpr const char * label = "RequiredSourceColumns";
static bool needChildVisit(ASTPtr & node, const ASTPtr & child);
static std::vector<ASTPtr *> visit(ASTPtr & ast, Data & data);
static void visit(ASTPtr & ast, Data & data);
private:
static void visit(const ASTIdentifier & node, const ASTPtr &, Data & data);
static void visit(const ASTFunction & node, const ASTPtr &, Data & data);
static void visit(ASTTablesInSelectQueryElement & node, const ASTPtr &, Data & data);
static std::vector<ASTPtr *> visit(ASTTableExpression & node, const ASTPtr &, Data & data);
static std::vector<ASTPtr *> visit(const ASTArrayJoin & node, const ASTPtr &, Data & data);
static std::vector<ASTPtr *> visit(ASTSelectQuery & select, const ASTPtr &, Data & data);
static void visit(ASTTableExpression & node, const ASTPtr &, Data & data);
static void visit(const ASTArrayJoin & node, const ASTPtr &, Data & data);
static void visit(ASTSelectQuery & select, const ASTPtr &, Data & data);
};
/// Extracts all the information about columns and tables from ASTSelectQuery block into ColumnNamesContext object.
/// It doesn't use anything but AST. It visits nodes from bottom to top except ASTFunction content to get aliases in right manner.
/// @note There's some ambiguousness with nested columns names that can't be solved without schema.
using RequiredSourceColumnsVisitor = InDepthNodeVisitor<RequiredSourceColumnsMatcher, false>;
using RequiredSourceColumnsVisitor = RequiredSourceColumnsMatcher::Visitor;
}

View File

@ -44,22 +44,21 @@ bool TranslateQualifiedNamesMatcher::needChildVisit(ASTPtr & node, const ASTPtr
return true;
}
std::vector<ASTPtr *> TranslateQualifiedNamesMatcher::visit(ASTPtr & ast, Data & data)
void TranslateQualifiedNamesMatcher::visit(ASTPtr & ast, Data & data)
{
if (auto * t = typeid_cast<ASTIdentifier *>(ast.get()))
return visit(*t, ast, data);
visit(*t, ast, data);
if (auto * t = typeid_cast<ASTTableJoin *>(ast.get()))
return visit(*t, ast, data);
visit(*t, ast, data);
if (auto * t = typeid_cast<ASTSelectQuery *>(ast.get()))
return visit(*t, ast, data);
visit(*t, ast, data);
if (auto * node = typeid_cast<ASTExpressionList *>(ast.get()))
visit(*node, ast, data);
if (auto * node = typeid_cast<ASTFunction *>(ast.get()))
visit(*node, ast, data);
return {};
}
std::vector<ASTPtr *> TranslateQualifiedNamesMatcher::visit(ASTIdentifier & identifier, ASTPtr &, Data & data)
void TranslateQualifiedNamesMatcher::visit(ASTIdentifier & identifier, ASTPtr &, Data & data)
{
if (IdentifierSemantic::getColumnName(identifier))
{
@ -82,8 +81,6 @@ std::vector<ASTPtr *> TranslateQualifiedNamesMatcher::visit(ASTIdentifier & iden
if (!data.tables.empty())
IdentifierSemantic::setColumnNormalName(identifier, data.tables[best_table_pos].first);
}
return {};
}
/// As special case, treat count(*) as count(), not as count(list of all columns).
@ -98,7 +95,7 @@ void TranslateQualifiedNamesMatcher::visit(ASTFunction & node, const ASTPtr &, D
func_arguments->children.clear();
}
std::vector<ASTPtr *> TranslateQualifiedNamesMatcher::visit(const ASTQualifiedAsterisk & , const ASTPtr & ast, Data & data)
void TranslateQualifiedNamesMatcher::visit(const ASTQualifiedAsterisk & , const ASTPtr & ast, Data & data)
{
if (ast->children.size() != 1)
throw Exception("Logical error: qualified asterisk must have exactly one child", ErrorCodes::LOGICAL_ERROR);
@ -110,22 +107,24 @@ std::vector<ASTPtr *> TranslateQualifiedNamesMatcher::visit(const ASTQualifiedAs
for (const auto & known_table : data.tables)
if (db_and_table.satisfies(known_table.first, true))
return {};
return;
throw Exception("Unknown qualified identifier: " + ident->getAliasOrColumnName(), ErrorCodes::UNKNOWN_IDENTIFIER);
}
std::vector<ASTPtr *> TranslateQualifiedNamesMatcher::visit(ASTTableJoin & join, const ASTPtr & , Data &)
void TranslateQualifiedNamesMatcher::visit(ASTTableJoin & join, const ASTPtr & , Data & data)
{
std::vector<ASTPtr *> out;
if (join.using_expression_list)
out.push_back(&join.using_expression_list);
else if (join.on_expression)
out.push_back(&join.on_expression);
return out;
for (ASTPtr * add_node : out)
Visitor(data).visit(*add_node);
}
std::vector<ASTPtr *> TranslateQualifiedNamesMatcher::visit(ASTSelectQuery & select, const ASTPtr & , Data & data)
void TranslateQualifiedNamesMatcher::visit(ASTSelectQuery & select, const ASTPtr & , Data & data)
{
if (auto join = select.join())
extractJoinUsingColumns(join->table_join, data);
@ -139,7 +138,9 @@ std::vector<ASTPtr *> TranslateQualifiedNamesMatcher::visit(ASTSelectQuery & sel
out.push_back(&select.where_expression);
if (select.having_expression)
out.push_back(&select.having_expression);
return out;
for (ASTPtr * add_node : out)
Visitor(data).visit(*add_node);
}
/// qualifed names for duplicates

View File

@ -20,6 +20,8 @@ class ASTFunction;
class TranslateQualifiedNamesMatcher
{
public:
using Visitor = InDepthNodeVisitor<TranslateQualifiedNamesMatcher, true>;
struct Data
{
const NameSet & source_columns;
@ -46,16 +48,14 @@ public:
bool processAsterisks() const { return !tables.empty() && has_columns; }
};
static constexpr const char * label = "TranslateQualifiedNames";
static std::vector<ASTPtr *> visit(ASTPtr & ast, Data & data);
static void visit(ASTPtr & ast, Data & data);
static bool needChildVisit(ASTPtr & node, const ASTPtr & child);
private:
static std::vector<ASTPtr *> visit(ASTIdentifier & node, ASTPtr & ast, Data &);
static std::vector<ASTPtr *> visit(const ASTQualifiedAsterisk & node, const ASTPtr & ast, Data &);
static std::vector<ASTPtr *> visit(ASTTableJoin & node, const ASTPtr & ast, Data &);
static std::vector<ASTPtr *> visit(ASTSelectQuery & node, const ASTPtr & ast, Data &);
static void visit(ASTIdentifier & node, ASTPtr & ast, Data &);
static void visit(const ASTQualifiedAsterisk & node, const ASTPtr & ast, Data &);
static void visit(ASTTableJoin & node, const ASTPtr & ast, Data &);
static void visit(ASTSelectQuery & node, const ASTPtr & ast, Data &);
static void visit(ASTExpressionList &, const ASTPtr &, Data &);
static void visit(ASTFunction &, const ASTPtr &, Data &);
@ -64,6 +64,6 @@ private:
/// Visits AST for names qualification.
/// It finds columns and translate their names to the normal form. Expand asterisks and qualified asterisks with column names.
using TranslateQualifiedNamesVisitor = InDepthNodeVisitor<TranslateQualifiedNamesMatcher, true>;
using TranslateQualifiedNamesVisitor = TranslateQualifiedNamesMatcher::Visitor;
}