mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 00:30:49 +00:00
Merge pull request #38136 from bigo-sg/translate_qualified_bug
Bug fixed in TranslateQualifiedNamesMatcher
This commit is contained in:
commit
776a80bff8
@ -142,6 +142,33 @@ std::optional<String> IdentifierSemantic::extractNestedName(const ASTIdentifier
|
||||
return {};
|
||||
}
|
||||
|
||||
String IdentifierSemantic::extractNestedName(const ASTIdentifier & identifier, const DatabaseAndTableWithAlias & table)
|
||||
{
|
||||
auto match = IdentifierSemantic::canReferColumnToTable(identifier, table);
|
||||
size_t to_strip = 0;
|
||||
switch (match)
|
||||
{
|
||||
case IdentifierSemantic::ColumnMatch::TableName:
|
||||
case IdentifierSemantic::ColumnMatch::AliasedTableName:
|
||||
case IdentifierSemantic::ColumnMatch::TableAlias:
|
||||
to_strip = 1;
|
||||
break;
|
||||
case IdentifierSemantic::ColumnMatch::DBAndTable:
|
||||
to_strip = 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
String res;
|
||||
for (size_t i = to_strip, sz = identifier.name_parts.size(); i < sz; ++i)
|
||||
{
|
||||
if (!res.empty())
|
||||
res += ".";
|
||||
res += identifier.name_parts[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool IdentifierSemantic::doesIdentifierBelongTo(const ASTIdentifier & identifier, const String & database, const String & table)
|
||||
{
|
||||
size_t num_components = identifier.name_parts.size();
|
||||
|
@ -44,6 +44,8 @@ struct IdentifierSemantic
|
||||
/// @returns name for 'not a column' identifiers
|
||||
static std::optional<String> extractNestedName(const ASTIdentifier & identifier, const String & table_name);
|
||||
|
||||
static String extractNestedName(const ASTIdentifier & identifier, const DatabaseAndTableWithAlias & table);
|
||||
|
||||
static ColumnMatch canReferColumnToTable(const ASTIdentifier & identifier, const DatabaseAndTableWithAlias & db_and_table);
|
||||
static ColumnMatch canReferColumnToTable(const ASTIdentifier & identifier, const TableWithColumnNamesAndTypes & table_with_columns);
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <cstring>
|
||||
#include <Poco/String.h>
|
||||
|
||||
#include <Interpreters/TranslateQualifiedNamesVisitor.h>
|
||||
@ -6,6 +7,7 @@
|
||||
#include <Common/typeid_cast.h>
|
||||
#include <Common/StringUtils/StringUtils.h>
|
||||
#include <Core/Names.h>
|
||||
#include <DataTypes/DataTypeTuple.h>
|
||||
|
||||
#include <Parsers/ASTIdentifier.h>
|
||||
#include <Parsers/ASTAsterisk.h>
|
||||
@ -29,38 +31,56 @@ namespace ErrorCodes
|
||||
extern const int UNSUPPORTED_JOIN_KEYS;
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
bool TranslateQualifiedNamesMatcher::Data::matchColumnName(const std::string_view & name, const String & column_name, DataTypePtr column_type)
|
||||
{
|
||||
if (name.size() < column_name.size())
|
||||
return false;
|
||||
|
||||
if (!name.starts_with(column_name))
|
||||
return false;
|
||||
|
||||
if (name.size() == column_name.size())
|
||||
return true;
|
||||
|
||||
/// In case the type is named tuple, check the name recursively.
|
||||
if (const DataTypeTuple * type_tuple = typeid_cast<const DataTypeTuple *>(column_type.get()))
|
||||
{
|
||||
if (type_tuple->haveExplicitNames() && name.at(column_name.size()) == '.')
|
||||
{
|
||||
const Strings & names = type_tuple->getElementNames();
|
||||
const DataTypes & element_types = type_tuple->getElements();
|
||||
std::string_view sub_name = name.substr(column_name.size() + 1);
|
||||
for (size_t i = 0; i < names.size(); ++i)
|
||||
{
|
||||
if (matchColumnName(sub_name, names[i], element_types[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool TranslateQualifiedNamesMatcher::Data::unknownColumn(size_t table_pos, const ASTIdentifier & identifier) const
|
||||
{
|
||||
const auto & table = tables[table_pos].table;
|
||||
auto nested1 = IdentifierSemantic::extractNestedName(identifier, table.table);
|
||||
auto nested2 = IdentifierSemantic::extractNestedName(identifier, table.alias);
|
||||
|
||||
const String & short_name = identifier.shortName();
|
||||
const auto & columns = tables[table_pos].columns;
|
||||
|
||||
// Remove database and table name from the identifier'name
|
||||
auto full_name = IdentifierSemantic::extractNestedName(identifier, table);
|
||||
|
||||
for (const auto & column : columns)
|
||||
{
|
||||
const String & known_name = column.name;
|
||||
if (short_name == known_name)
|
||||
return false;
|
||||
if (nested1 && *nested1 == known_name)
|
||||
return false;
|
||||
if (nested2 && *nested2 == known_name)
|
||||
if (matchColumnName(full_name, column.name, column.type))
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto & hidden_columns = tables[table_pos].hidden_columns;
|
||||
for (const auto & column : hidden_columns)
|
||||
{
|
||||
const String & known_name = column.name;
|
||||
if (short_name == known_name)
|
||||
return false;
|
||||
if (nested1 && *nested1 == known_name)
|
||||
return false;
|
||||
if (nested2 && *nested2 == known_name)
|
||||
if (matchColumnName(full_name, column.name, column.type))
|
||||
return false;
|
||||
}
|
||||
|
||||
return !columns.empty();
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ public:
|
||||
bool hasTable() const { return !tables.empty(); }
|
||||
bool processAsterisks() const { return hasTable() && has_columns; }
|
||||
bool unknownColumn(size_t table_pos, const ASTIdentifier & identifier) const;
|
||||
static bool matchColumnName(const std::string_view & name, const String & column_name, DataTypePtr column_type);
|
||||
};
|
||||
|
||||
static void visit(ASTPtr & ast, Data & data);
|
||||
@ -53,6 +54,7 @@ private:
|
||||
static void visit(ASTFunction &, const ASTPtr &, Data &);
|
||||
|
||||
static void extractJoinUsingColumns(ASTPtr ast, Data & data);
|
||||
|
||||
};
|
||||
|
||||
/// Visits AST for names qualification.
|
||||
|
@ -0,0 +1,2 @@
|
||||
12
|
||||
12
|
@ -0,0 +1,10 @@
|
||||
CREATE TABLE nested_name_tuples
|
||||
(
|
||||
`a` Tuple(x String, y Tuple(i Int32, j String))
|
||||
)
|
||||
ENGINE = Memory;
|
||||
|
||||
INSERT INTO nested_name_tuples VALUES(('asd', (12, 'ddd')));
|
||||
|
||||
SELECT t.a.y.i FROM nested_name_tuples as t;
|
||||
SELECT nested_name_tuples.a.y.i FROM nested_name_tuples as t;
|
Loading…
Reference in New Issue
Block a user