mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 08:40:50 +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 {};
|
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)
|
bool IdentifierSemantic::doesIdentifierBelongTo(const ASTIdentifier & identifier, const String & database, const String & table)
|
||||||
{
|
{
|
||||||
size_t num_components = identifier.name_parts.size();
|
size_t num_components = identifier.name_parts.size();
|
||||||
|
@ -44,6 +44,8 @@ struct IdentifierSemantic
|
|||||||
/// @returns name for 'not a column' identifiers
|
/// @returns name for 'not a column' identifiers
|
||||||
static std::optional<String> extractNestedName(const ASTIdentifier & identifier, const String & table_name);
|
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 DatabaseAndTableWithAlias & db_and_table);
|
||||||
static ColumnMatch canReferColumnToTable(const ASTIdentifier & identifier, const TableWithColumnNamesAndTypes & table_with_columns);
|
static ColumnMatch canReferColumnToTable(const ASTIdentifier & identifier, const TableWithColumnNamesAndTypes & table_with_columns);
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <cstring>
|
||||||
#include <Poco/String.h>
|
#include <Poco/String.h>
|
||||||
|
|
||||||
#include <Interpreters/TranslateQualifiedNamesVisitor.h>
|
#include <Interpreters/TranslateQualifiedNamesVisitor.h>
|
||||||
@ -6,6 +7,7 @@
|
|||||||
#include <Common/typeid_cast.h>
|
#include <Common/typeid_cast.h>
|
||||||
#include <Common/StringUtils/StringUtils.h>
|
#include <Common/StringUtils/StringUtils.h>
|
||||||
#include <Core/Names.h>
|
#include <Core/Names.h>
|
||||||
|
#include <DataTypes/DataTypeTuple.h>
|
||||||
|
|
||||||
#include <Parsers/ASTIdentifier.h>
|
#include <Parsers/ASTIdentifier.h>
|
||||||
#include <Parsers/ASTAsterisk.h>
|
#include <Parsers/ASTAsterisk.h>
|
||||||
@ -29,38 +31,56 @@ namespace ErrorCodes
|
|||||||
extern const int UNSUPPORTED_JOIN_KEYS;
|
extern const int UNSUPPORTED_JOIN_KEYS;
|
||||||
extern const int LOGICAL_ERROR;
|
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
|
bool TranslateQualifiedNamesMatcher::Data::unknownColumn(size_t table_pos, const ASTIdentifier & identifier) const
|
||||||
{
|
{
|
||||||
const auto & table = tables[table_pos].table;
|
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;
|
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)
|
for (const auto & column : columns)
|
||||||
{
|
{
|
||||||
const String & known_name = column.name;
|
if (matchColumnName(full_name, column.name, column.type))
|
||||||
if (short_name == known_name)
|
|
||||||
return false;
|
|
||||||
if (nested1 && *nested1 == known_name)
|
|
||||||
return false;
|
|
||||||
if (nested2 && *nested2 == known_name)
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto & hidden_columns = tables[table_pos].hidden_columns;
|
const auto & hidden_columns = tables[table_pos].hidden_columns;
|
||||||
for (const auto & column : hidden_columns)
|
for (const auto & column : hidden_columns)
|
||||||
{
|
{
|
||||||
const String & known_name = column.name;
|
if (matchColumnName(full_name, column.name, column.type))
|
||||||
if (short_name == known_name)
|
|
||||||
return false;
|
|
||||||
if (nested1 && *nested1 == known_name)
|
|
||||||
return false;
|
|
||||||
if (nested2 && *nested2 == known_name)
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !columns.empty();
|
return !columns.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ public:
|
|||||||
bool hasTable() const { return !tables.empty(); }
|
bool hasTable() const { return !tables.empty(); }
|
||||||
bool processAsterisks() const { return hasTable() && has_columns; }
|
bool processAsterisks() const { return hasTable() && has_columns; }
|
||||||
bool unknownColumn(size_t table_pos, const ASTIdentifier & identifier) const;
|
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);
|
static void visit(ASTPtr & ast, Data & data);
|
||||||
@ -53,6 +54,7 @@ private:
|
|||||||
static void visit(ASTFunction &, const ASTPtr &, Data &);
|
static void visit(ASTFunction &, const ASTPtr &, Data &);
|
||||||
|
|
||||||
static void extractJoinUsingColumns(ASTPtr ast, Data & data);
|
static void extractJoinUsingColumns(ASTPtr ast, Data & data);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Visits AST for names qualification.
|
/// 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