Merge pull request #38136 from bigo-sg/translate_qualified_bug

Bug fixed in TranslateQualifiedNamesMatcher
This commit is contained in:
Yakov Olkhovskiy 2022-07-01 14:07:00 -04:00 committed by GitHub
commit 776a80bff8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 81 additions and 18 deletions

View File

@ -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();

View File

@ -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);

View File

@ -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();
}

View File

@ -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.

View File

@ -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;