support nested column names

This commit is contained in:
chertus 2019-11-13 19:49:29 +03:00
parent d70904d7ee
commit 31028b8f3b
4 changed files with 32 additions and 10 deletions

View File

@ -132,6 +132,15 @@ std::pair<String, String> IdentifierSemantic::extractDatabaseAndTable(const ASTI
return { "", identifier.name };
}
std::optional<String> IdentifierSemantic::extractNestedName(const ASTIdentifier & identifier, const String & table_name)
{
if (identifier.name_parts.size() == 3 && table_name == identifier.name_parts[0])
return identifier.name_parts[1] + '.' + identifier.name_parts[2];
else if (identifier.name_parts.size() == 2)
return identifier.name_parts[0] + '.' + identifier.name_parts[1];
return {};
}
bool IdentifierSemantic::doesIdentifierBelongTo(const ASTIdentifier & identifier, const String & database, const String & table)
{
size_t num_components = identifier.name_parts.size();

View File

@ -36,6 +36,7 @@ struct IdentifierSemantic
static std::optional<String> getTableName(const ASTIdentifier & node);
static std::optional<String> getTableName(const ASTPtr & ast);
static std::pair<String, String> extractDatabaseAndTable(const ASTIdentifier & identifier);
static std::optional<String> extractNestedName(const ASTIdentifier & identifier, const String & table_name);
static ColumnMatch canReferColumnToTable(const ASTIdentifier & identifier, const DatabaseAndTableWithAlias & db_and_table);
static void setColumnShortName(ASTIdentifier & identifier, const DatabaseAndTableWithAlias & db_and_table);

View File

@ -29,6 +29,26 @@ namespace ErrorCodes
extern const int LOGICAL_ERROR;
}
bool TranslateQualifiedNamesMatcher::Data::unknownColumn(size_t table_pos, const ASTIdentifier & identifier) const
{
const auto & table = tables[table_pos].first;
auto nested1 = IdentifierSemantic::extractNestedName(identifier, table.table);
auto nested2 = IdentifierSemantic::extractNestedName(identifier, table.alias);
String short_name = identifier.shortName();
const Names & column_names = tables[table_pos].second;
for (auto & known_name : column_names)
{
if (short_name == known_name)
return false;
if (nested1 && *nested1 == known_name)
return false;
if (nested2 && *nested2 == known_name)
return false;
}
return !column_names.empty();
}
bool TranslateQualifiedNamesMatcher::needChildVisit(ASTPtr & node, const ASTPtr & child)
{
/// Do not go to FROM, JOIN, subqueries.
@ -66,7 +86,7 @@ void TranslateQualifiedNamesMatcher::visit(ASTIdentifier & identifier, ASTPtr &,
bool allow_ambiguous = data.join_using_columns.count(short_name);
if (IdentifierSemantic::chooseTable(identifier, data.tables, table_pos, allow_ambiguous))
{
if (data.unknownColumn(table_pos, short_name))
if (data.unknownColumn(table_pos, identifier))
{
String table_name = data.tables[table_pos].first.getQualifiedNamePrefix(false);
throw Exception("There's no column '" + identifier.name + "' in table '" + table_name + "'",

View File

@ -38,15 +38,7 @@ public:
bool hasColumn(const String & name) const { return source_columns.count(name); }
bool hasTable() const { return !tables.empty(); }
bool processAsterisks() const { return hasTable() && has_columns; }
bool unknownColumn(size_t table_pos, const String & name) const
{
const Names & names = tables[table_pos].second;
for (auto & known_name : names)
if (name == known_name)
return false;
return !names.empty();
}
bool unknownColumn(size_t table_pos, const ASTIdentifier & node) const;
static std::vector<TableWithColumnNames> tablesOnly(const std::vector<DatabaseAndTableWithAlias> & tables)
{