mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-27 18:12:02 +00:00
Ban loop aliases in table definitions
This commit is contained in:
parent
fba2d66042
commit
5284f192ee
@ -80,6 +80,9 @@ void QueryNormalizer::visit(ASTIdentifier & node, ASTPtr & ast, Data & data)
|
||||
|
||||
/// If it is an alias, but not a parent alias (for constructs like "SELECT column + 1 AS column").
|
||||
auto it_alias = data.aliases.find(node.name());
|
||||
if (!data.allow_self_aliases && current_alias == node.name())
|
||||
throw Exception(ErrorCodes::CYCLIC_ALIASES, "Self referencing of {} to {}. Cyclic alias", backQuote(current_alias), backQuote(node.name()));
|
||||
|
||||
if (it_alias != data.aliases.end() && current_alias != node.name())
|
||||
{
|
||||
if (!IdentifierSemantic::canBeAlias(node))
|
||||
|
@ -48,18 +48,22 @@ public:
|
||||
MapOfASTs finished_asts; /// already processed vertices (and by what they replaced)
|
||||
SetOfASTs current_asts; /// vertices in the current call stack of this method
|
||||
std::string current_alias; /// the alias referencing to the ancestor of ast (the deepest ancestor with aliases)
|
||||
bool ignore_alias; /// normalize query without any aliases
|
||||
const bool ignore_alias; /// normalize query without any aliases
|
||||
|
||||
Data(const Aliases & aliases_, const NameSet & source_columns_set_, bool ignore_alias_, ExtractedSettings && settings_)
|
||||
/// It's Ok to have "c + 1 AS c" in queries, but not in table definition
|
||||
const bool allow_self_aliases; /// for constructs like "SELECT column + 1 AS column"
|
||||
|
||||
Data(const Aliases & aliases_, const NameSet & source_columns_set_, bool ignore_alias_, ExtractedSettings && settings_, bool allow_self_aliases_)
|
||||
: aliases(aliases_)
|
||||
, source_columns_set(source_columns_set_)
|
||||
, settings(settings_)
|
||||
, level(0)
|
||||
, ignore_alias(ignore_alias_)
|
||||
, allow_self_aliases(allow_self_aliases_)
|
||||
{}
|
||||
};
|
||||
|
||||
QueryNormalizer(Data & data)
|
||||
explicit QueryNormalizer(Data & data)
|
||||
: visitor_data(data)
|
||||
{}
|
||||
|
||||
|
@ -913,7 +913,7 @@ TreeRewriterResultPtr TreeRewriter::analyzeSelect(
|
||||
all_source_columns_set.insert(name);
|
||||
}
|
||||
|
||||
normalize(query, result.aliases, all_source_columns_set, select_options.ignore_alias, settings);
|
||||
normalize(query, result.aliases, all_source_columns_set, select_options.ignore_alias, settings, /* allow_self_aliases = */ true);
|
||||
|
||||
/// Remove unneeded columns according to 'required_result_columns'.
|
||||
/// Leave all selected columns in case of DISTINCT; columns that contain arrayJoin function inside.
|
||||
@ -968,7 +968,7 @@ TreeRewriterResultPtr TreeRewriter::analyze(
|
||||
|
||||
TreeRewriterResult result(source_columns, storage, metadata_snapshot, false);
|
||||
|
||||
normalize(query, result.aliases, result.source_columns_set, false, settings);
|
||||
normalize(query, result.aliases, result.source_columns_set, false, settings, /* allow_self_aliases = */ false);
|
||||
|
||||
/// Executing scalar subqueries. Column defaults could be a scalar subquery.
|
||||
executeScalarSubqueries(query, getContext(), 0, result.scalars, false);
|
||||
@ -994,7 +994,7 @@ TreeRewriterResultPtr TreeRewriter::analyze(
|
||||
}
|
||||
|
||||
void TreeRewriter::normalize(
|
||||
ASTPtr & query, Aliases & aliases, const NameSet & source_columns_set, bool ignore_alias, const Settings & settings)
|
||||
ASTPtr & query, Aliases & aliases, const NameSet & source_columns_set, bool ignore_alias, const Settings & settings, bool allow_self_aliases)
|
||||
{
|
||||
CustomizeCountDistinctVisitor::Data data_count_distinct{settings.count_distinct_implementation};
|
||||
CustomizeCountDistinctVisitor(data_count_distinct).visit(query);
|
||||
@ -1054,7 +1054,7 @@ void TreeRewriter::normalize(
|
||||
FunctionNameNormalizer().visit(query.get());
|
||||
|
||||
/// Common subexpression elimination. Rewrite rules.
|
||||
QueryNormalizer::Data normalizer_data(aliases, source_columns_set, ignore_alias, settings);
|
||||
QueryNormalizer::Data normalizer_data(aliases, source_columns_set, ignore_alias, settings, allow_self_aliases);
|
||||
QueryNormalizer(normalizer_data).visit(query);
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ public:
|
||||
std::shared_ptr<TableJoin> table_join = {}) const;
|
||||
|
||||
private:
|
||||
static void normalize(ASTPtr & query, Aliases & aliases, const NameSet & source_columns_set, bool ignore_alias, const Settings & settings);
|
||||
static void normalize(ASTPtr & query, Aliases & aliases, const NameSet & source_columns_set, bool ignore_alias, const Settings & settings, bool allow_self_aliases);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -9,6 +9,21 @@
|
||||
|
||||
using namespace DB;
|
||||
|
||||
|
||||
TEST(QueryNormalizer, SimpleLoopAlias)
|
||||
{
|
||||
String query = "a as a";
|
||||
ParserExpressionList parser(false);
|
||||
ASTPtr ast = parseQuery(parser, query, 0, 0);
|
||||
|
||||
Aliases aliases;
|
||||
aliases["a"] = parseQuery(parser, "a as a", 0, 0)->children[0];
|
||||
|
||||
Settings settings;
|
||||
QueryNormalizer::Data normalizer_data(aliases, {}, false, settings, false);
|
||||
EXPECT_THROW(QueryNormalizer(normalizer_data).visit(ast), Exception);
|
||||
}
|
||||
|
||||
TEST(QueryNormalizer, SimpleCycleAlias)
|
||||
{
|
||||
String query = "a as b, b as a";
|
||||
@ -20,6 +35,6 @@ TEST(QueryNormalizer, SimpleCycleAlias)
|
||||
aliases["b"] = parseQuery(parser, "a as b", 0, 0)->children[0];
|
||||
|
||||
Settings settings;
|
||||
QueryNormalizer::Data normalizer_data(aliases, {}, false, settings);
|
||||
QueryNormalizer::Data normalizer_data(aliases, {}, false, settings, true);
|
||||
EXPECT_THROW(QueryNormalizer(normalizer_data).visit(ast), Exception);
|
||||
}
|
||||
|
14
tests/queries/0_stateless/01902_self_aliases_in_columns.sql
Normal file
14
tests/queries/0_stateless/01902_self_aliases_in_columns.sql
Normal file
@ -0,0 +1,14 @@
|
||||
CREATE TABLE a
|
||||
(
|
||||
`number` UInt64,
|
||||
`x` MATERIALIZED x
|
||||
)
|
||||
ENGINE = MergeTree
|
||||
ORDER BY number; --{ serverError 174}
|
||||
|
||||
CREATE TABLE foo
|
||||
(
|
||||
i Int32,
|
||||
j ALIAS j + 1
|
||||
)
|
||||
ENGINE = MergeTree() ORDER BY i; --{ serverError 174}
|
Loading…
Reference in New Issue
Block a user