mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 09:02:00 +00:00
column to table matching refactoring
This commit is contained in:
parent
e6e88241fc
commit
483108f46f
@ -90,9 +90,12 @@ public:
|
|||||||
using TypeToVisit = const ASTFunction;
|
using TypeToVisit = const ASTFunction;
|
||||||
|
|
||||||
CheckExpressionVisitorData(const std::vector<JoinedTable> & tables_)
|
CheckExpressionVisitorData(const std::vector<JoinedTable> & tables_)
|
||||||
: tables(tables_)
|
: joined_tables(tables_)
|
||||||
, ands_only(true)
|
, ands_only(true)
|
||||||
{}
|
{
|
||||||
|
for (auto & joined : joined_tables)
|
||||||
|
tables.push_back(joined.table);
|
||||||
|
}
|
||||||
|
|
||||||
void visit(const ASTFunction & node, ASTPtr & ast)
|
void visit(const ASTFunction & node, ASTPtr & ast)
|
||||||
{
|
{
|
||||||
@ -156,7 +159,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::vector<JoinedTable> & tables;
|
const std::vector<JoinedTable> & joined_tables;
|
||||||
|
std::vector<DatabaseAndTableWithAlias> tables;
|
||||||
std::map<size_t, std::vector<ASTPtr>> asts_to_join_on;
|
std::map<size_t, std::vector<ASTPtr>> asts_to_join_on;
|
||||||
bool ands_only;
|
bool ands_only;
|
||||||
|
|
||||||
@ -180,31 +184,16 @@ private:
|
|||||||
/// @return table position to attach expression to or 0.
|
/// @return table position to attach expression to or 0.
|
||||||
size_t checkIdentifiers(const ASTIdentifier & left, const ASTIdentifier & right)
|
size_t checkIdentifiers(const ASTIdentifier & left, const ASTIdentifier & right)
|
||||||
{
|
{
|
||||||
/// {best_match, best_table_pos}
|
size_t left_table_pos = 0;
|
||||||
std::pair<size_t, size_t> left_best{0, 0};
|
bool left_match = IdentifierSemantic::chooseTable(left, tables, left_table_pos);
|
||||||
std::pair<size_t, size_t> right_best{0, 0};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < tables.size(); ++i)
|
size_t right_table_pos = 0;
|
||||||
|
bool right_match = IdentifierSemantic::chooseTable(right, tables, right_table_pos);
|
||||||
|
|
||||||
|
if (left_match && right_match && (left_table_pos != right_table_pos))
|
||||||
{
|
{
|
||||||
size_t match = IdentifierSemantic::canReferColumnToTable(left, tables[i].table);
|
size_t table_pos = std::max(left_table_pos, right_table_pos);
|
||||||
if (match > left_best.first)
|
if (joined_tables[table_pos].canAttachOnExpression())
|
||||||
{
|
|
||||||
left_best.first = match;
|
|
||||||
left_best.second = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
match = IdentifierSemantic::canReferColumnToTable(right, tables[i].table);
|
|
||||||
if (match > right_best.first)
|
|
||||||
{
|
|
||||||
right_best.first = match;
|
|
||||||
right_best.second = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (left_best.first && right_best.first && (left_best.second != right_best.second))
|
|
||||||
{
|
|
||||||
size_t table_pos = std::max(left_best.second, right_best.second);
|
|
||||||
if (tables[table_pos].canAttachOnExpression())
|
|
||||||
return table_pos;
|
return table_pos;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -212,20 +201,10 @@ private:
|
|||||||
|
|
||||||
size_t checkIdentifier(const ASTIdentifier & identifier)
|
size_t checkIdentifier(const ASTIdentifier & identifier)
|
||||||
{
|
{
|
||||||
size_t best_match = 0;
|
|
||||||
size_t best_table_pos = 0;
|
size_t best_table_pos = 0;
|
||||||
|
bool match = IdentifierSemantic::chooseTable(identifier, tables, best_table_pos);
|
||||||
|
|
||||||
for (size_t i = 0; i < tables.size(); ++i)
|
if (match && joined_tables[best_table_pos].canAttachOnExpression())
|
||||||
{
|
|
||||||
size_t match = IdentifierSemantic::canReferColumnToTable(identifier, tables[i].table);
|
|
||||||
if (match > best_match)
|
|
||||||
{
|
|
||||||
best_match = match;
|
|
||||||
best_table_pos = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (best_match && tables[best_table_pos].canAttachOnExpression())
|
|
||||||
return best_table_pos;
|
return best_table_pos;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -28,17 +28,9 @@ void FindIdentifierBestTableData::visit(ASTIdentifier & identifier, ASTPtr &)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// FIXME: make a better matcher using `names`?
|
size_t best_table_pos = 0;
|
||||||
size_t best_match = 0;
|
if (IdentifierSemantic::chooseTable(identifier, tables, best_table_pos))
|
||||||
for (const auto & table_names : tables)
|
best_table = &tables[best_table_pos].first;
|
||||||
{
|
|
||||||
if (size_t match = IdentifierSemantic::canReferColumnToTable(identifier, table_names.first))
|
|
||||||
if (match > best_match)
|
|
||||||
{
|
|
||||||
best_match = match;
|
|
||||||
best_table = &table_names.first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
identifier_table.emplace_back(&identifier, best_table);
|
identifier_table.emplace_back(&identifier, best_table);
|
||||||
|
@ -5,6 +5,37 @@
|
|||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
const DatabaseAndTableWithAlias & extractTable(const DatabaseAndTableWithAlias & table)
|
||||||
|
{
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DatabaseAndTableWithAlias & extractTable(const TableWithColumnNames & table)
|
||||||
|
{
|
||||||
|
return table.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool tryChooseTable(const ASTIdentifier & identifier, const std::vector<T> & tables, size_t & best_table_pos)
|
||||||
|
{
|
||||||
|
best_table_pos = 0;
|
||||||
|
size_t best_match = 0;
|
||||||
|
for (size_t i = 0; i < tables.size(); ++i)
|
||||||
|
if (size_t match = IdentifierSemantic::canReferColumnToTable(identifier, extractTable(tables[i])))
|
||||||
|
if (match > best_match)
|
||||||
|
{
|
||||||
|
best_match = match;
|
||||||
|
best_table_pos = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return best_match;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<String> IdentifierSemantic::getColumnName(const ASTIdentifier & node)
|
std::optional<String> IdentifierSemantic::getColumnName(const ASTIdentifier & node)
|
||||||
{
|
{
|
||||||
if (!node.semantic->special)
|
if (!node.semantic->special)
|
||||||
@ -57,26 +88,16 @@ size_t IdentifierSemantic::getMembership(const ASTIdentifier & identifier)
|
|||||||
return identifier.semantic->membership;
|
return identifier.semantic->membership;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IdentifierSemantic::trySetMembership(ASTIdentifier & identifier, const std::vector<TableWithColumnNames> & tables,
|
bool IdentifierSemantic::chooseTable(const ASTIdentifier & identifier, const std::vector<DatabaseAndTableWithAlias> & tables,
|
||||||
size_t & best_table_pos)
|
size_t & best_table_pos)
|
||||||
{
|
{
|
||||||
best_table_pos = 0;
|
return tryChooseTable<DatabaseAndTableWithAlias>(identifier, tables, best_table_pos);
|
||||||
size_t best_match = 0;
|
}
|
||||||
for (size_t i = 0; i < tables.size(); ++i)
|
|
||||||
if (size_t match = canReferColumnToTable(identifier, tables[i].first))
|
|
||||||
if (match > best_match)
|
|
||||||
{
|
|
||||||
best_match = match;
|
|
||||||
best_table_pos = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (best_match)
|
bool IdentifierSemantic::chooseTable(const ASTIdentifier & identifier, const std::vector<TableWithColumnNames> & tables,
|
||||||
{
|
size_t & best_table_pos)
|
||||||
setMembership(identifier, best_table_pos + 1);
|
{
|
||||||
return true;
|
return tryChooseTable<TableWithColumnNames>(identifier, tables, best_table_pos);
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<String, String> IdentifierSemantic::extractDatabaseAndTable(const ASTIdentifier & identifier)
|
std::pair<String, String> IdentifierSemantic::extractDatabaseAndTable(const ASTIdentifier & identifier)
|
||||||
|
@ -35,7 +35,8 @@ struct IdentifierSemantic
|
|||||||
static bool canBeAlias(const ASTIdentifier & identifier);
|
static bool canBeAlias(const ASTIdentifier & identifier);
|
||||||
static void setMembership(ASTIdentifier & identifier, size_t table_no);
|
static void setMembership(ASTIdentifier & identifier, size_t table_no);
|
||||||
static size_t getMembership(const ASTIdentifier & identifier);
|
static size_t getMembership(const ASTIdentifier & identifier);
|
||||||
static bool trySetMembership(ASTIdentifier & identifier, const std::vector<TableWithColumnNames> & tables, size_t & best_table_pos);
|
static bool chooseTable(const ASTIdentifier &, const std::vector<DatabaseAndTableWithAlias> & tables, size_t & best_table_pos);
|
||||||
|
static bool chooseTable(const ASTIdentifier &, const std::vector<TableWithColumnNames> & tables, size_t & best_table_pos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool doesIdentifierBelongTo(const ASTIdentifier & identifier, const String & database, const String & table);
|
static bool doesIdentifierBelongTo(const ASTIdentifier & identifier, const String & database, const String & table);
|
||||||
|
@ -163,7 +163,13 @@ struct ColumnAliasesMatcher
|
|||||||
auto it = rev_aliases.find(long_name);
|
auto it = rev_aliases.find(long_name);
|
||||||
if (it == rev_aliases.end())
|
if (it == rev_aliases.end())
|
||||||
{
|
{
|
||||||
bool last_table = IdentifierSemantic::canReferColumnToTable(*identifier, tables.back());
|
bool last_table = false;
|
||||||
|
{
|
||||||
|
size_t best_table_pos = 0;
|
||||||
|
if (IdentifierSemantic::chooseTable(*identifier, tables, best_table_pos))
|
||||||
|
last_table = (best_table_pos + 1 == tables.size());
|
||||||
|
}
|
||||||
|
|
||||||
if (!last_table)
|
if (!last_table)
|
||||||
{
|
{
|
||||||
String alias = hide_prefix + long_name;
|
String alias = hide_prefix + long_name;
|
||||||
|
@ -62,7 +62,8 @@ void TranslateQualifiedNamesMatcher::visit(ASTIdentifier & identifier, ASTPtr &,
|
|||||||
if (IdentifierSemantic::getColumnName(identifier))
|
if (IdentifierSemantic::getColumnName(identifier))
|
||||||
{
|
{
|
||||||
size_t best_table_pos = 0;
|
size_t best_table_pos = 0;
|
||||||
IdentifierSemantic::trySetMembership(identifier, data.tables, best_table_pos);
|
if (IdentifierSemantic::chooseTable(identifier, data.tables, best_table_pos))
|
||||||
|
IdentifierSemantic::setMembership(identifier, best_table_pos + 1);
|
||||||
|
|
||||||
/// In case if column from the joined table are in source columns, change it's name to qualified.
|
/// In case if column from the joined table are in source columns, change it's name to qualified.
|
||||||
if (best_table_pos && data.hasColumn(identifier.shortName()))
|
if (best_table_pos && data.hasColumn(identifier.shortName()))
|
||||||
|
Loading…
Reference in New Issue
Block a user