Fixed error with duplicate columns in subqueries [#METR-22381].

This commit is contained in:
Alexey Milovidov 2016-08-20 20:10:00 +03:00
parent 2c16a4ad2a
commit 902c70bfa9
4 changed files with 51 additions and 15 deletions

View File

@ -160,10 +160,24 @@ FunctionPtr getFunctionFromFactory(const String & name, const ASTFunction::Genus
return function;
}
void removeDuplicateColumns(NamesAndTypesList & columns)
{
std::set<String> names;
for (auto it = columns.begin(); it != columns.end();)
{
if (names.emplace(it->name).second)
++it;
else
columns.erase(it++);
}
}
}
void ExpressionAnalyzer::init()
{
removeDuplicateColumns(columns);
select_query = typeid_cast<ASTSelectQuery *>(ast.get());
/// В зависимости от профиля пользователя проверить наличие прав на выполнение

View File

@ -66,7 +66,7 @@ void ASTSelectQuery::renameColumns(const ASTSelectQuery & source)
}
}
void ASTSelectQuery::rewriteSelectExpressionList(const Names & column_names)
void ASTSelectQuery::rewriteSelectExpressionList(const Names & required_column_names)
{
ASTPtr result = std::make_shared<ASTExpressionList>();
ASTs asts = select_expression_list->children;
@ -91,7 +91,7 @@ void ASTSelectQuery::rewriteSelectExpressionList(const Names & column_names)
Mapping mapping(asts.size());
/// На какой позиции в SELECT-выражении находится соответствующий столбец из column_names.
std::vector<size_t> from(column_names.size());
std::vector<size_t> positions_of_required_columns(required_column_names.size());
/// Не будем выбрасывать выражения, содержащие функцию arrayJoin.
for (size_t i = 0; i < asts.size(); ++i)
@ -100,31 +100,29 @@ void ASTSelectQuery::rewriteSelectExpressionList(const Names & column_names)
mapping[i] = Arrow(i);
}
for (size_t i = 0; i < column_names.size(); ++i)
for (size_t i = 0; i < required_column_names.size(); ++i)
{
bool done = false;
for (size_t j = 0; j < asts.size(); ++j)
size_t j = 0;
for (; j < asts.size(); ++j)
{
if (asts[j]->getAliasOrColumnName() == column_names[i])
if (asts[j]->getAliasOrColumnName() == required_column_names[i])
{
from[i] = j;
done = true;
positions_of_required_columns[i] = j;
break;
}
}
if (!done)
if (j == asts.size())
throw Exception("Error while rewriting expression list for select query."
" Could not find alias: " + column_names[i],
" Could not find alias: " + required_column_names[i],
DB::ErrorCodes::UNKNOWN_IDENTIFIER);
}
auto to = from;
std::vector<size_t> positions_of_required_columns_in_subquery_order = positions_of_required_columns;
std::sort(positions_of_required_columns_in_subquery_order.begin(), positions_of_required_columns_in_subquery_order.end());
/// Теперь from - список позиций column_names по возрастанию.
std::sort(from.begin(), from.end());
for (size_t i = 0; i < required_column_names.size(); ++i)
mapping[positions_of_required_columns_in_subquery_order[i]] = Arrow(positions_of_required_columns[i]);
for (size_t i = 0; i < column_names.size(); ++i)
mapping[from[i]] = Arrow(to[i]);
/// Составить новое выражение.
for (const auto & arrow : mapping)

View File

@ -0,0 +1,12 @@
1 2
1 1
1
1 2
1 1 1
1 1
1 1
1 1
42 1 2
42 1 2
0 hello world
1 hello world

View File

@ -0,0 +1,12 @@
select x, y from (select 1 as x, 2 as y, x, y);
select x, y from (select 1 as x, 1 as y, x, y);
select x from (select 1 as x, 1 as y, x, y);
select * from (select 1 as x, 2 as y, x, y);
select * from (select 1 as a, 1 as b, 1 as c, b, c);
select b, c from (select 1 as a, 1 as b, 1 as c, b, c);
select b, c from (select 1 as a, 1 as b, 1 as c, b, c) any left join (select 1 as a) using a;
select b, c from (select 1 as a, 1 as b, 1 as c, 1 as b, 1 as c) any left join (select 1 as a) using a;
select a, b, c from (select 42 as a, 1 as b, 2 as c, 1 as b, 2 as c) any left join (select 42 as a, 3 as d) using a;
select a, b, c from (select 42 as a, 1 as b, 2 as c, 1 as b, 2 as c) any left join (select 42 as a, 3 as d) using a order by d;
SELECT k, a1, b1, a2, b2 FROM (SELECT 0 AS k, 'hello' AS a1, 'world' AS b1, a1) ANY FULL OUTER JOIN (SELECT 1 AS k, 'hello' AS a2, 'world' AS b2, a2) USING (k) ORDER BY k;