mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 07:01:59 +00:00
Fixed infinite recursion in expression analyzer. [#CLICKHOUSE-3125]
This commit is contained in:
parent
942a4df2bd
commit
7bc58340b0
@ -1014,7 +1014,7 @@ void ExpressionAnalyzer::normalizeTreeImpl(
|
|||||||
* For example, in the table there is a column "domain(URL)", and we requested domain(URL).
|
* For example, in the table there is a column "domain(URL)", and we requested domain(URL).
|
||||||
*/
|
*/
|
||||||
String function_string = func_node->getColumnName();
|
String function_string = func_node->getColumnName();
|
||||||
NamesAndTypesList::const_iterator it = findColumn(function_string);
|
auto it = findColumn(function_string);
|
||||||
if (columns.end() != it)
|
if (columns.end() != it)
|
||||||
{
|
{
|
||||||
ast = std::make_shared<ASTIdentifier>(func_node->range, function_string);
|
ast = std::make_shared<ASTIdentifier>(func_node->range, function_string);
|
||||||
@ -1051,24 +1051,34 @@ void ExpressionAnalyzer::normalizeTreeImpl(
|
|||||||
if (identifier_node->kind == ASTIdentifier::Column)
|
if (identifier_node->kind == ASTIdentifier::Column)
|
||||||
{
|
{
|
||||||
/// If it is an alias, but not a parent alias (for constructs like "SELECT column + 1 AS column").
|
/// If it is an alias, but not a parent alias (for constructs like "SELECT column + 1 AS column").
|
||||||
Aliases::const_iterator jt = aliases.find(identifier_node->name);
|
auto it_alias = aliases.find(identifier_node->name);
|
||||||
if (jt != aliases.end() && current_alias != identifier_node->name)
|
if (it_alias != aliases.end() && current_alias != identifier_node->name)
|
||||||
{
|
{
|
||||||
/// Let's replace it with the corresponding tree node.
|
/// Let's replace it with the corresponding tree node.
|
||||||
if (current_asts.count(jt->second.get()))
|
if (current_asts.count(it_alias->second.get()))
|
||||||
throw Exception("Cyclic aliases", ErrorCodes::CYCLIC_ALIASES);
|
throw Exception("Cyclic aliases", ErrorCodes::CYCLIC_ALIASES);
|
||||||
if (!my_alias.empty() && my_alias != jt->second->getAliasOrColumnName())
|
|
||||||
|
if (!my_alias.empty() && my_alias != it_alias->second->getAliasOrColumnName())
|
||||||
{
|
{
|
||||||
/// In a construct like "a AS b", where a is an alias, you must set alias b to the result of substituting alias a.
|
/// Avoid infinite recursion here
|
||||||
ast = jt->second->clone();
|
auto replace_to_identifier = typeid_cast<ASTIdentifier *>(it_alias->second.get());
|
||||||
ast->setAlias(my_alias);
|
bool is_cycle = replace_to_identifier &&
|
||||||
|
replace_to_identifier->kind == ASTIdentifier::Column &&
|
||||||
|
replace_to_identifier->name == identifier_node->name;
|
||||||
|
|
||||||
|
if (!is_cycle)
|
||||||
|
{
|
||||||
|
/// In a construct like "a AS b", where a is an alias, you must set alias b to the result of substituting alias a.
|
||||||
|
ast = it_alias->second->clone();
|
||||||
|
ast->setAlias(my_alias);
|
||||||
|
replaced = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ast = jt->second;
|
ast = it_alias->second;
|
||||||
|
replaced = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
replaced = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,2 +1,5 @@
|
|||||||
1
|
1
|
||||||
1
|
1
|
||||||
|
0 0
|
||||||
|
0 0 0
|
||||||
|
0 0 0
|
||||||
|
@ -3,3 +3,7 @@ CREATE TABLE test.nested (n Nested(x UInt8)) ENGINE = Memory;
|
|||||||
INSERT INTO test.nested VALUES ([1, 2]);
|
INSERT INTO test.nested VALUES ([1, 2]);
|
||||||
SELECT 1 AS x FROM remote('127.0.0.1', test.nested) ARRAY JOIN n.x;
|
SELECT 1 AS x FROM remote('127.0.0.1', test.nested) ARRAY JOIN n.x;
|
||||||
DROP TABLE test.nested;
|
DROP TABLE test.nested;
|
||||||
|
|
||||||
|
SELECT dummy AS dummy, dummy AS b FROM system.one;
|
||||||
|
SELECT dummy AS dummy, dummy AS b, b AS c FROM system.one;
|
||||||
|
SELECT b AS c, dummy AS b, dummy AS dummy FROM system.one;
|
||||||
|
Loading…
Reference in New Issue
Block a user