column to table matching refactoring

This commit is contained in:
chertus 2019-10-16 20:33:53 +03:00
parent e6e88241fc
commit 483108f46f
6 changed files with 70 additions and 70 deletions

View File

@ -90,9 +90,12 @@ public:
using TypeToVisit = const ASTFunction;
CheckExpressionVisitorData(const std::vector<JoinedTable> & tables_)
: tables(tables_)
: joined_tables(tables_)
, ands_only(true)
{}
{
for (auto & joined : joined_tables)
tables.push_back(joined.table);
}
void visit(const ASTFunction & node, ASTPtr & ast)
{
@ -156,7 +159,8 @@ public:
}
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;
bool ands_only;
@ -180,31 +184,16 @@ private:
/// @return table position to attach expression to or 0.
size_t checkIdentifiers(const ASTIdentifier & left, const ASTIdentifier & right)
{
/// {best_match, best_table_pos}
std::pair<size_t, size_t> left_best{0, 0};
std::pair<size_t, size_t> right_best{0, 0};
size_t left_table_pos = 0;
bool left_match = IdentifierSemantic::chooseTable(left, tables, left_table_pos);
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);
if (match > left_best.first)
{
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())
size_t table_pos = std::max(left_table_pos, right_table_pos);
if (joined_tables[table_pos].canAttachOnExpression())
return table_pos;
}
return 0;
@ -212,20 +201,10 @@ private:
size_t checkIdentifier(const ASTIdentifier & identifier)
{
size_t best_match = 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)
{
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())
if (match && joined_tables[best_table_pos].canAttachOnExpression())
return best_table_pos;
return 0;
}

View File

@ -28,17 +28,9 @@ void FindIdentifierBestTableData::visit(ASTIdentifier & identifier, ASTPtr &)
}
else
{
// FIXME: make a better matcher using `names`?
size_t best_match = 0;
for (const auto & table_names : tables)
{
if (size_t match = IdentifierSemantic::canReferColumnToTable(identifier, table_names.first))
if (match > best_match)
{
best_match = match;
best_table = &table_names.first;
}
}
size_t best_table_pos = 0;
if (IdentifierSemantic::chooseTable(identifier, tables, best_table_pos))
best_table = &tables[best_table_pos].first;
}
identifier_table.emplace_back(&identifier, best_table);

View File

@ -5,6 +5,37 @@
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)
{
if (!node.semantic->special)
@ -57,26 +88,16 @@ size_t IdentifierSemantic::getMembership(const ASTIdentifier & identifier)
return identifier.semantic->membership;
}
bool IdentifierSemantic::trySetMembership(ASTIdentifier & identifier, const std::vector<TableWithColumnNames> & tables,
size_t & best_table_pos)
bool IdentifierSemantic::chooseTable(const ASTIdentifier & identifier, const std::vector<DatabaseAndTableWithAlias> & 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 = canReferColumnToTable(identifier, tables[i].first))
if (match > best_match)
{
best_match = match;
best_table_pos = i;
}
return tryChooseTable<DatabaseAndTableWithAlias>(identifier, tables, best_table_pos);
}
if (best_match)
{
setMembership(identifier, best_table_pos + 1);
return true;
}
return false;
bool IdentifierSemantic::chooseTable(const ASTIdentifier & identifier, const std::vector<TableWithColumnNames> & tables,
size_t & best_table_pos)
{
return tryChooseTable<TableWithColumnNames>(identifier, tables, best_table_pos);
}
std::pair<String, String> IdentifierSemantic::extractDatabaseAndTable(const ASTIdentifier & identifier)

View File

@ -35,7 +35,8 @@ struct IdentifierSemantic
static bool canBeAlias(const ASTIdentifier & identifier);
static void setMembership(ASTIdentifier & identifier, size_t table_no);
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:
static bool doesIdentifierBelongTo(const ASTIdentifier & identifier, const String & database, const String & table);

View File

@ -163,7 +163,13 @@ struct ColumnAliasesMatcher
auto it = rev_aliases.find(long_name);
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)
{
String alias = hide_prefix + long_name;

View File

@ -62,7 +62,8 @@ void TranslateQualifiedNamesMatcher::visit(ASTIdentifier & identifier, ASTPtr &,
if (IdentifierSemantic::getColumnName(identifier))
{
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.
if (best_table_pos && data.hasColumn(identifier.shortName()))