mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 16:42:05 +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;
|
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;
|
auto & alias_node = it_alias->second;
|
||||||
|
|
||||||
/// Let's replace it with the corresponding tree node.
|
String our_alias_or_name = alias_node->getAliasOrColumnName();
|
||||||
if (current_asts.count(alias_node.get()))
|
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);
|
throw Exception("Cyclic aliases", ErrorCodes::CYCLIC_ALIASES);
|
||||||
|
|
||||||
String my_alias = ast->tryGetAlias();
|
/// Let's replace it with the corresponding tree node.
|
||||||
if (!my_alias.empty() && my_alias != alias_node->getAliasOrColumnName())
|
if (!node_alias.empty() && node_alias != our_alias_or_name)
|
||||||
{
|
{
|
||||||
/// Avoid infinite recursion here
|
/// Avoid infinite recursion here
|
||||||
auto opt_name = IdentifierSemantic::getColumnName(alias_node);
|
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.
|
/// 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 = alias_node->clone();
|
||||||
ast->setAlias(my_alias);
|
ast->setAlias(node_alias);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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