2018-09-27 19:25:18 +00:00
|
|
|
#include <Interpreters/TranslateQualifiedNamesVisitor.h>
|
|
|
|
|
2018-12-06 15:29:55 +00:00
|
|
|
#include <Common/typeid_cast.h>
|
2018-11-02 18:53:23 +00:00
|
|
|
#include <Core/Names.h>
|
2018-09-28 15:01:13 +00:00
|
|
|
|
2018-09-27 19:25:18 +00:00
|
|
|
#include <Parsers/ASTIdentifier.h>
|
|
|
|
#include <Parsers/ASTQualifiedAsterisk.h>
|
|
|
|
#include <Parsers/ASTSelectQuery.h>
|
|
|
|
#include <Parsers/ASTSelectWithUnionQuery.h>
|
|
|
|
#include <Parsers/ASTTablesInSelectQuery.h>
|
|
|
|
|
2018-11-02 18:53:23 +00:00
|
|
|
|
2018-09-27 19:25:18 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int UNKNOWN_IDENTIFIER;
|
2018-12-06 15:29:55 +00:00
|
|
|
extern const int UNKNOWN_ELEMENT_IN_AST;
|
|
|
|
extern const int LOGICAL_ERROR;
|
2018-09-27 19:25:18 +00:00
|
|
|
}
|
|
|
|
|
2018-12-06 15:29:55 +00:00
|
|
|
bool TranslateQualifiedNamesMatcher::needChildVisit(ASTPtr & node, const ASTPtr & child)
|
2018-09-27 19:25:18 +00:00
|
|
|
{
|
2018-12-06 15:29:55 +00:00
|
|
|
/// Do not go to FROM, JOIN, subqueries.
|
|
|
|
if (typeid_cast<ASTTableExpression *>(child.get()) ||
|
|
|
|
typeid_cast<ASTSelectWithUnionQuery *>(child.get()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/// Processed nodes. Do not go into children.
|
|
|
|
if (typeid_cast<ASTIdentifier *>(node.get()) ||
|
|
|
|
typeid_cast<ASTQualifiedAsterisk *>(node.get()) ||
|
|
|
|
typeid_cast<ASTTableJoin *>(node.get()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/// ASTSelectQuery + others
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-12-07 14:24:47 +00:00
|
|
|
std::vector<ASTPtr *> TranslateQualifiedNamesMatcher::visit(ASTPtr & ast, Data & data)
|
2018-12-06 15:29:55 +00:00
|
|
|
{
|
|
|
|
if (auto * t = typeid_cast<ASTIdentifier *>(ast.get()))
|
|
|
|
return visit(*t, ast, data);
|
|
|
|
if (auto * t = typeid_cast<ASTQualifiedAsterisk *>(ast.get()))
|
|
|
|
return visit(*t, ast, data);
|
|
|
|
if (auto * t = typeid_cast<ASTTableJoin *>(ast.get()))
|
|
|
|
return visit(*t, ast, data);
|
|
|
|
if (auto * t = typeid_cast<ASTSelectQuery *>(ast.get()))
|
|
|
|
return visit(*t, ast, data);
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2018-12-07 14:24:47 +00:00
|
|
|
std::vector<ASTPtr *> TranslateQualifiedNamesMatcher::visit(const ASTIdentifier & identifier, ASTPtr & ast, Data & data)
|
2018-12-06 15:29:55 +00:00
|
|
|
{
|
|
|
|
const NameSet & source_columns = data.source_columns;
|
|
|
|
const std::vector<DatabaseAndTableWithAlias> & tables = data.tables;
|
|
|
|
|
2019-01-14 18:15:04 +00:00
|
|
|
if (getColumnIdentifierName(identifier))
|
2018-09-27 19:25:18 +00:00
|
|
|
{
|
|
|
|
/// Select first table name with max number of qualifiers which can be stripped.
|
|
|
|
size_t max_num_qualifiers_to_strip = 0;
|
|
|
|
size_t best_table_pos = 0;
|
|
|
|
|
|
|
|
for (size_t table_pos = 0; table_pos < tables.size(); ++table_pos)
|
|
|
|
{
|
|
|
|
const auto & table = tables[table_pos];
|
2018-11-01 17:07:20 +00:00
|
|
|
auto num_qualifiers_to_strip = getNumComponentsToStripInOrderToTranslateQualifiedName(identifier, table);
|
2018-09-27 19:25:18 +00:00
|
|
|
|
|
|
|
if (num_qualifiers_to_strip > max_num_qualifiers_to_strip)
|
|
|
|
{
|
|
|
|
max_num_qualifiers_to_strip = num_qualifiers_to_strip;
|
|
|
|
best_table_pos = table_pos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-28 12:13:01 +00:00
|
|
|
if (max_num_qualifiers_to_strip)
|
|
|
|
stripIdentifier(ast, max_num_qualifiers_to_strip);
|
2018-09-27 19:25:18 +00:00
|
|
|
|
|
|
|
/// In case if column from the joined table are in source columns, change it's name to qualified.
|
2018-11-02 18:53:23 +00:00
|
|
|
if (best_table_pos && source_columns.count(ast->getColumnName()))
|
2018-09-27 19:25:18 +00:00
|
|
|
{
|
|
|
|
const DatabaseAndTableWithAlias & table = tables[best_table_pos];
|
|
|
|
table.makeQualifiedName(ast);
|
|
|
|
}
|
|
|
|
}
|
2018-12-06 15:29:55 +00:00
|
|
|
|
|
|
|
return {};
|
2018-09-27 19:25:18 +00:00
|
|
|
}
|
|
|
|
|
2018-12-07 14:24:47 +00:00
|
|
|
std::vector<ASTPtr *> TranslateQualifiedNamesMatcher::visit(const ASTQualifiedAsterisk & , const ASTPtr & ast, Data & data)
|
2018-09-27 19:25:18 +00:00
|
|
|
{
|
|
|
|
if (ast->children.size() != 1)
|
|
|
|
throw Exception("Logical error: qualified asterisk must have exactly one child", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
2019-01-16 12:08:43 +00:00
|
|
|
auto & ident = ast->children[0];
|
2018-09-27 19:25:18 +00:00
|
|
|
|
2019-01-16 12:08:43 +00:00
|
|
|
/// @note it could contain table alias as table name.
|
|
|
|
DatabaseAndTableWithAlias db_and_table(ident);
|
2018-10-29 19:04:28 +00:00
|
|
|
|
2019-01-16 12:08:43 +00:00
|
|
|
for (const auto & known_table : data.tables)
|
|
|
|
if (db_and_table.satisfies(known_table, true))
|
|
|
|
return {};
|
2018-09-27 19:25:18 +00:00
|
|
|
|
|
|
|
throw Exception("Unknown qualified identifier: " + ident->getAliasOrColumnName(), ErrorCodes::UNKNOWN_IDENTIFIER);
|
|
|
|
}
|
|
|
|
|
2018-12-07 14:24:47 +00:00
|
|
|
std::vector<ASTPtr *> TranslateQualifiedNamesMatcher::visit(ASTTableJoin & join, const ASTPtr & , Data &)
|
2018-09-27 19:25:18 +00:00
|
|
|
{
|
|
|
|
/// Don't translate on_expression here in order to resolve equation parts later.
|
2018-12-07 14:24:47 +00:00
|
|
|
std::vector<ASTPtr *> out;
|
2018-11-01 17:07:20 +00:00
|
|
|
if (join.using_expression_list)
|
2018-12-07 14:24:47 +00:00
|
|
|
out.push_back(&join.using_expression_list);
|
2018-12-06 15:29:55 +00:00
|
|
|
return out;
|
2018-09-27 19:25:18 +00:00
|
|
|
}
|
|
|
|
|
2018-12-07 14:24:47 +00:00
|
|
|
std::vector<ASTPtr *> TranslateQualifiedNamesMatcher::visit(ASTSelectQuery & select, const ASTPtr & , Data &)
|
2018-09-27 19:25:18 +00:00
|
|
|
{
|
2019-01-22 19:56:53 +00:00
|
|
|
/// If the WHERE clause or HAVING consists of a single qualified column, the reference must be translated not only in children,
|
2018-09-27 19:25:18 +00:00
|
|
|
/// but also in where_expression and having_expression.
|
2018-12-07 14:24:47 +00:00
|
|
|
std::vector<ASTPtr *> out;
|
2018-11-01 17:07:20 +00:00
|
|
|
if (select.prewhere_expression)
|
2018-12-07 14:24:47 +00:00
|
|
|
out.push_back(&select.prewhere_expression);
|
2018-11-01 17:07:20 +00:00
|
|
|
if (select.where_expression)
|
2018-12-07 14:24:47 +00:00
|
|
|
out.push_back(&select.where_expression);
|
2018-11-01 17:07:20 +00:00
|
|
|
if (select.having_expression)
|
2018-12-07 14:24:47 +00:00
|
|
|
out.push_back(&select.having_expression);
|
2018-12-06 15:29:55 +00:00
|
|
|
return out;
|
2018-09-27 19:25:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|