2018-12-26 14:43:25 +00:00
|
|
|
#include <Interpreters/RequiredSourceColumnsVisitor.h>
|
|
|
|
#include <Common/typeid_cast.h>
|
|
|
|
#include <Core/Names.h>
|
|
|
|
#include <Parsers/IAST.h>
|
|
|
|
#include <Parsers/ASTIdentifier.h>
|
|
|
|
#include <Parsers/ASTFunction.h>
|
|
|
|
#include <Parsers/ASTSelectQuery.h>
|
|
|
|
#include <Parsers/ASTSubquery.h>
|
|
|
|
#include <Parsers/ASTTablesInSelectQuery.h>
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int TYPE_MISMATCH;
|
|
|
|
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::vector<String> extractNamesFromLambda(const ASTFunction & node)
|
|
|
|
{
|
|
|
|
if (node.arguments->children.size() != 2)
|
|
|
|
throw Exception("lambda requires two arguments", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
|
|
|
|
2019-03-11 13:22:51 +00:00
|
|
|
const auto * lambda_args_tuple = node.arguments->children[0]->as<ASTFunction>();
|
2018-12-26 14:43:25 +00:00
|
|
|
|
|
|
|
if (!lambda_args_tuple || lambda_args_tuple->name != "tuple")
|
|
|
|
throw Exception("First argument of lambda must be a tuple", ErrorCodes::TYPE_MISMATCH);
|
|
|
|
|
|
|
|
std::vector<String> names;
|
|
|
|
for (auto & child : lambda_args_tuple->arguments->children)
|
|
|
|
{
|
2019-03-11 13:22:51 +00:00
|
|
|
const auto * identifier = child->as<ASTIdentifier>();
|
2018-12-26 14:43:25 +00:00
|
|
|
if (!identifier)
|
|
|
|
throw Exception("lambda argument declarations must be identifiers", ErrorCodes::TYPE_MISMATCH);
|
|
|
|
|
|
|
|
names.push_back(identifier->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
return names;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RequiredSourceColumnsMatcher::needChildVisit(ASTPtr & node, const ASTPtr & child)
|
|
|
|
{
|
2019-03-11 13:22:51 +00:00
|
|
|
if (child->as<ASTSelectQuery>())
|
2018-12-26 14:43:25 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
/// Processed. Do not need children.
|
2019-03-11 13:22:51 +00:00
|
|
|
if (node->as<ASTTableExpression>() || node->as<ASTArrayJoin>() || node->as<ASTSelectQuery>())
|
2018-12-26 14:43:25 +00:00
|
|
|
return false;
|
|
|
|
|
2019-03-11 13:22:51 +00:00
|
|
|
if (const auto * f = node->as<ASTFunction>())
|
2018-12-26 14:43:25 +00:00
|
|
|
{
|
|
|
|
/// "indexHint" is a special function for index analysis. Everything that is inside it is not calculated. @sa KeyCondition
|
|
|
|
/// "lambda" visit children itself.
|
|
|
|
if (f->name == "indexHint" || f->name == "lambda")
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-02-22 13:33:56 +00:00
|
|
|
void RequiredSourceColumnsMatcher::visit(ASTPtr & ast, Data & data)
|
2018-12-26 14:43:25 +00:00
|
|
|
{
|
|
|
|
/// results are columns
|
|
|
|
|
2019-03-11 13:22:51 +00:00
|
|
|
if (auto * t = ast->as<ASTIdentifier>())
|
2018-12-26 14:43:25 +00:00
|
|
|
{
|
|
|
|
visit(*t, ast, data);
|
2019-02-22 13:33:56 +00:00
|
|
|
return;
|
2018-12-26 14:43:25 +00:00
|
|
|
}
|
2019-03-11 13:22:51 +00:00
|
|
|
if (auto * t = ast->as<ASTFunction>())
|
2018-12-26 14:43:25 +00:00
|
|
|
{
|
|
|
|
data.addColumnAliasIfAny(*ast);
|
|
|
|
visit(*t, ast, data);
|
2019-02-22 13:33:56 +00:00
|
|
|
return;
|
2018-12-26 14:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// results are tables
|
|
|
|
|
2019-03-11 13:22:51 +00:00
|
|
|
if (auto * t = ast->as<ASTTablesInSelectQueryElement>())
|
2018-12-26 14:43:25 +00:00
|
|
|
{
|
|
|
|
visit(*t, ast, data);
|
2019-02-22 13:33:56 +00:00
|
|
|
return;
|
2018-12-26 14:43:25 +00:00
|
|
|
}
|
|
|
|
|
2019-03-11 13:22:51 +00:00
|
|
|
if (auto * t = ast->as<ASTTableExpression>())
|
2018-12-26 14:43:25 +00:00
|
|
|
{
|
|
|
|
visit(*t, ast, data);
|
2019-02-22 13:33:56 +00:00
|
|
|
return;
|
2018-12-26 14:43:25 +00:00
|
|
|
}
|
2019-03-11 13:22:51 +00:00
|
|
|
if (auto * t = ast->as<ASTSelectQuery>())
|
2018-12-26 14:43:25 +00:00
|
|
|
{
|
|
|
|
data.addTableAliasIfAny(*ast);
|
2019-02-22 13:33:56 +00:00
|
|
|
visit(*t, ast, data);
|
|
|
|
return;
|
2018-12-26 14:43:25 +00:00
|
|
|
}
|
2019-03-11 13:22:51 +00:00
|
|
|
if (ast->as<ASTSubquery>())
|
2018-12-26 14:43:25 +00:00
|
|
|
{
|
|
|
|
data.addTableAliasIfAny(*ast);
|
2019-02-22 13:33:56 +00:00
|
|
|
return;
|
2018-12-26 14:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// other
|
|
|
|
|
2019-03-11 13:22:51 +00:00
|
|
|
if (auto * t = ast->as<ASTArrayJoin>())
|
2018-12-26 14:43:25 +00:00
|
|
|
{
|
|
|
|
data.has_array_join = true;
|
2019-02-22 13:33:56 +00:00
|
|
|
visit(*t, ast, data);
|
|
|
|
return;
|
2018-12-26 14:43:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-22 13:33:56 +00:00
|
|
|
void RequiredSourceColumnsMatcher::visit(ASTSelectQuery & select, const ASTPtr &, Data & data)
|
2018-12-26 14:43:25 +00:00
|
|
|
{
|
|
|
|
/// special case for top-level SELECT items: they are publics
|
2019-04-09 14:22:35 +00:00
|
|
|
for (auto & node : select.select()->children)
|
2018-12-26 14:43:25 +00:00
|
|
|
{
|
2019-03-11 13:22:51 +00:00
|
|
|
if (const auto * identifier = node->as<ASTIdentifier>())
|
2019-02-15 15:34:30 +00:00
|
|
|
data.addColumnIdentifier(*identifier);
|
2018-12-26 14:43:25 +00:00
|
|
|
else
|
2019-02-15 15:34:30 +00:00
|
|
|
data.addColumnAliasIfAny(*node);
|
2018-12-26 14:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<ASTPtr *> out;
|
|
|
|
for (auto & node : select.children)
|
2019-04-09 14:22:35 +00:00
|
|
|
if (node != select.select())
|
|
|
|
Visitor(data).visit(node);
|
2018-12-26 14:43:25 +00:00
|
|
|
|
|
|
|
/// revisit select_expression_list (with children) when all the aliases are set
|
2019-04-09 14:22:35 +00:00
|
|
|
Visitor(data).visit(select.refSelect());
|
2018-12-26 14:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void RequiredSourceColumnsMatcher::visit(const ASTIdentifier & node, const ASTPtr &, Data & data)
|
|
|
|
{
|
|
|
|
if (node.name.empty())
|
|
|
|
throw Exception("Expected not empty name", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
|
|
|
|
|
|
|
if (!data.private_aliases.count(node.name))
|
|
|
|
data.addColumnIdentifier(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RequiredSourceColumnsMatcher::visit(const ASTFunction & node, const ASTPtr &, Data & data)
|
|
|
|
{
|
|
|
|
/// Do not add formal parameters of the lambda expression
|
|
|
|
if (node.name == "lambda")
|
|
|
|
{
|
|
|
|
Names local_aliases;
|
|
|
|
for (const auto & name : extractNamesFromLambda(node))
|
|
|
|
if (data.private_aliases.insert(name).second)
|
|
|
|
local_aliases.push_back(name);
|
|
|
|
|
|
|
|
/// visit child with masked local aliases
|
2019-01-21 19:56:11 +00:00
|
|
|
RequiredSourceColumnsVisitor(data).visit(node.arguments->children[1]);
|
2018-12-26 14:43:25 +00:00
|
|
|
|
|
|
|
for (const auto & name : local_aliases)
|
|
|
|
data.private_aliases.erase(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RequiredSourceColumnsMatcher::visit(ASTTablesInSelectQueryElement & node, const ASTPtr &, Data & data)
|
|
|
|
{
|
|
|
|
ASTTableExpression * expr = nullptr;
|
|
|
|
ASTTableJoin * join = nullptr;
|
|
|
|
|
|
|
|
for (auto & child : node.children)
|
|
|
|
{
|
2019-03-11 13:22:51 +00:00
|
|
|
if (auto * e = child->as<ASTTableExpression>())
|
2018-12-26 14:43:25 +00:00
|
|
|
expr = e;
|
2019-03-11 13:22:51 +00:00
|
|
|
if (auto * j = child->as<ASTTableJoin>())
|
2018-12-26 14:43:25 +00:00
|
|
|
join = j;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (join)
|
|
|
|
data.has_table_join = true;
|
|
|
|
data.tables.emplace_back(ColumnNamesContext::JoinedTable{expr, join});
|
|
|
|
}
|
|
|
|
|
2019-02-22 17:08:10 +00:00
|
|
|
/// ASTIdentifiers here are tables. Do not visit them as generic ones.
|
2019-02-22 13:33:56 +00:00
|
|
|
void RequiredSourceColumnsMatcher::visit(ASTTableExpression & node, const ASTPtr &, Data & data)
|
2018-12-26 14:43:25 +00:00
|
|
|
{
|
|
|
|
if (node.database_and_table_name)
|
|
|
|
data.addTableAliasIfAny(*node.database_and_table_name);
|
|
|
|
|
|
|
|
if (node.table_function)
|
|
|
|
data.addTableAliasIfAny(*node.table_function);
|
|
|
|
|
|
|
|
if (node.subquery)
|
|
|
|
data.addTableAliasIfAny(*node.subquery);
|
|
|
|
}
|
|
|
|
|
2019-02-22 13:33:56 +00:00
|
|
|
void RequiredSourceColumnsMatcher::visit(const ASTArrayJoin & node, const ASTPtr &, Data & data)
|
2018-12-26 14:43:25 +00:00
|
|
|
{
|
|
|
|
ASTPtr expression_list = node.expression_list;
|
|
|
|
if (!expression_list || expression_list->children.empty())
|
|
|
|
throw Exception("Expected not empty expression_list", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
|
|
|
|
|
|
|
std::vector<ASTPtr *> out;
|
|
|
|
|
|
|
|
/// Tech debt. Ignore ARRAY JOIN top-level identifiers and aliases. There's its own logic for them.
|
|
|
|
for (auto & expr : expression_list->children)
|
|
|
|
{
|
|
|
|
data.addArrayJoinAliasIfAny(*expr);
|
|
|
|
|
2019-03-11 13:22:51 +00:00
|
|
|
if (const auto * identifier = expr->as<ASTIdentifier>())
|
2018-12-26 14:43:25 +00:00
|
|
|
{
|
|
|
|
data.addArrayJoinIdentifier(*identifier);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
out.push_back(&expr);
|
|
|
|
}
|
|
|
|
|
2019-02-22 13:33:56 +00:00
|
|
|
for (ASTPtr * add_node : out)
|
|
|
|
Visitor(data).visit(*add_node);
|
2018-12-26 14:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|