mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
Fix simpliest case of cyclic aliases in QueryNormalizer
This commit is contained in:
parent
1143c45c3f
commit
e63bb9a4a7
@ -91,14 +91,21 @@ void QueryNormalizer::visit(ASTIdentifier & node, ASTPtr & ast, Data & data)
|
||||
return;
|
||||
}
|
||||
|
||||
/// We are alias for other column (node.name), but we are alias by
|
||||
/// ourselves to some other column
|
||||
auto & alias_node = it_alias->second;
|
||||
|
||||
/// Let's replace it with the corresponding tree node.
|
||||
if (current_asts.count(alias_node.get()))
|
||||
String our_alias_or_name = alias_node->getAliasOrColumnName();
|
||||
std::optional<String> our_name = IdentifierSemantic::getColumnName(alias_node);
|
||||
|
||||
String node_alias = ast->tryGetAlias();
|
||||
|
||||
if (current_asts.count(alias_node.get()) /// We have loop of multiple aliases
|
||||
|| (node.name == our_alias_or_name && our_name && node_alias == *our_name)) /// Our alias points to node.name, direct loop
|
||||
throw Exception("Cyclic aliases", ErrorCodes::CYCLIC_ALIASES);
|
||||
|
||||
String my_alias = ast->tryGetAlias();
|
||||
if (!my_alias.empty() && my_alias != alias_node->getAliasOrColumnName())
|
||||
/// Let's replace it with the corresponding tree node.
|
||||
if (!node_alias.empty() && node_alias != our_alias_or_name)
|
||||
{
|
||||
/// Avoid infinite recursion here
|
||||
auto opt_name = IdentifierSemantic::getColumnName(alias_node);
|
||||
@ -108,7 +115,7 @@ void QueryNormalizer::visit(ASTIdentifier & node, ASTPtr & ast, Data & data)
|
||||
{
|
||||
/// 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 = alias_node->clone();
|
||||
ast->setAlias(my_alias);
|
||||
ast->setAlias(node_alias);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
24
dbms/src/Interpreters/tests/gtest_cycle_aliases.cpp
Normal file
24
dbms/src/Interpreters/tests/gtest_cycle_aliases.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <Interpreters/QueryNormalizer.h>
|
||||
#include <Parsers/IAST.h>
|
||||
#include <Parsers/queryToString.h>
|
||||
#include <Parsers/ExpressionListParsers.h>
|
||||
#include <Parsers/parseQuery.h>
|
||||
|
||||
using namespace DB;
|
||||
|
||||
TEST(QueryNormalizer, SimpleCycleAlias)
|
||||
{
|
||||
String query = "a as b, b as a";
|
||||
ParserExpressionList parser(false);
|
||||
ASTPtr ast = parseQuery(parser, query, 0);
|
||||
|
||||
Aliases aliases;
|
||||
aliases["a"] = parseQuery(parser, "b as a", 0)->children[0];
|
||||
aliases["b"] = parseQuery(parser, "a as b", 0)->children[0];
|
||||
|
||||
Settings settings;
|
||||
QueryNormalizer::Data normalizer_data(aliases, settings);
|
||||
EXPECT_THROW(QueryNormalizer(normalizer_data).visit(ast), Exception);
|
||||
}
|
@ -0,0 +1 @@
|
||||
1
|
15
dbms/tests/queries/0_stateless/01097_cyclic_defaults.sql
Normal file
15
dbms/tests/queries/0_stateless/01097_cyclic_defaults.sql
Normal file
@ -0,0 +1,15 @@
|
||||
DROP TABLE IF EXISTS table_with_cyclic_defaults;
|
||||
|
||||
CREATE TABLE table_with_cyclic_defaults (a DEFAULT b, b DEFAULT a) ENGINE = Memory; --{serverError 174}
|
||||
|
||||
CREATE TABLE table_with_cyclic_defaults (a DEFAULT b + 1, b DEFAULT a * a) ENGINE = Memory; --{serverError 174}
|
||||
|
||||
CREATE TABLE table_with_cyclic_defaults (a DEFAULT b, b DEFAULT toString(c), c DEFAULT concat(a, '1')) ENGINE = Memory; --{serverError 174}
|
||||
|
||||
CREATE TABLE table_with_cyclic_defaults (a DEFAULT b, b DEFAULT c, c DEFAULT a * b) ENGINE = Memory; --{serverError 174}
|
||||
|
||||
CREATE TABLE table_with_cyclic_defaults (a String DEFAULT b, b String DEFAULT a) ENGINE = Memory; --{serverError 174}
|
||||
|
||||
SELECT 1;
|
||||
|
||||
DROP TABLE IF EXISTS table_with_cyclic_defaults;
|
Loading…
Reference in New Issue
Block a user