From 1ad4b6ed606b657b5570b26b712992952f4e6d66 Mon Sep 17 00:00:00 2001 From: kssenii Date: Mon, 16 Aug 2021 23:34:39 +0300 Subject: [PATCH] Fix --- src/Interpreters/InterpreterSelectQuery.cpp | 27 +++++++++++++++++-- ...02004_intersect_except_operators.reference | 7 +++++ .../02004_intersect_except_operators.sql | 5 ++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Interpreters/InterpreterSelectQuery.cpp b/src/Interpreters/InterpreterSelectQuery.cpp index edcef191e73..9f4d573735e 100644 --- a/src/Interpreters/InterpreterSelectQuery.cpp +++ b/src/Interpreters/InterpreterSelectQuery.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -878,16 +879,38 @@ static bool hasWithTotalsInAnySubqueryInFromClause(const ASTSelectQuery & query) { if (const auto * ast_union = query_table->as()) { - /// NOTE: Child of subquery can be ASTSelectWithUnionQuery or ASTSelectQuery, - /// and after normalization, the height of the AST tree is at most 2 for (const auto & elem : ast_union->list_of_selects->children) { + /// After normalization, the height of the AST tree is at most 2. if (const auto * child_union = elem->as()) { for (const auto & child_elem : child_union->list_of_selects->children) if (hasWithTotalsInAnySubqueryInFromClause(child_elem->as())) return true; } + /// After normalization, the height of the AST tree can have any depth, + /// but the number of children at each level is always 2. + else if (const auto * child_intersect_except = elem->as()) + { + std::function traverse_recursively = [&](ASTPtr child_ast) -> bool + { + if (const auto * child = child_ast->as ()) + return hasWithTotalsInAnySubqueryInFromClause(child->as()); + + if (const auto * child = child_ast->as()) + for (const auto & subchild : child->list_of_selects->children) + if (traverse_recursively(subchild)) + return true; + + if (const auto * child = child_ast->as()) + for (const auto & subchild : child->children) + if (traverse_recursively(subchild)) + return true; + return false; + }; + if (traverse_recursively(elem)) + return true; + } else { if (hasWithTotalsInAnySubqueryInFromClause(elem->as())) diff --git a/tests/queries/0_stateless/02004_intersect_except_operators.reference b/tests/queries/0_stateless/02004_intersect_except_operators.reference index 03b881f690b..85559496f2f 100644 --- a/tests/queries/0_stateless/02004_intersect_except_operators.reference +++ b/tests/queries/0_stateless/02004_intersect_except_operators.reference @@ -84,6 +84,13 @@ select count() from (select number from numbers(100) intersect select number fro 30 select count() from (select number from numbers(1000000) intersect select number from numbers(200000, 600000) except select number from numbers(300000, 200000) except select number from numbers(600000, 200000)); 200000 +select count() from (select 1 intersect select 1) limit 100; +1 +select count() from (select 1 except select 2) limit 100; +1 +with (select count() from (select 1 union distinct select 2 except select 1)) as max +select count() from (select 1 union all select max) limit 100; +2 select 1 union all select 1 intersect select 1; 1 1 diff --git a/tests/queries/0_stateless/02004_intersect_except_operators.sql b/tests/queries/0_stateless/02004_intersect_except_operators.sql index 7f08cc0adf2..b95051cba65 100644 --- a/tests/queries/0_stateless/02004_intersect_except_operators.sql +++ b/tests/queries/0_stateless/02004_intersect_except_operators.sql @@ -30,6 +30,11 @@ select count() from (select number from numbers(100) intersect select number fro select count() from (select number from numbers(100) intersect select number from numbers(20, 60) except select number from numbers(30, 20) except select number from numbers(60, 20) union all select number from numbers(100, 10)); select count() from (select number from numbers(1000000) intersect select number from numbers(200000, 600000) except select number from numbers(300000, 200000) except select number from numbers(600000, 200000)); +select count() from (select 1 intersect select 1) limit 100; +select count() from (select 1 except select 2) limit 100; +with (select count() from (select 1 union distinct select 2 except select 1)) as max +select count() from (select 1 union all select max) limit 100; + select 1 union all select 1 intersect select 1; select 1 union all select 1 intersect select 2; select * from (select 1 union all select 2 union all select 3 union all select 4 except select 3 union all select 5) order by 1;