This commit is contained in:
kssenii 2021-08-16 23:34:39 +03:00
parent 7ee2dc04a1
commit 1ad4b6ed60
3 changed files with 37 additions and 2 deletions

View File

@ -8,6 +8,7 @@
#include <Parsers/ASTLiteral.h> #include <Parsers/ASTLiteral.h>
#include <Parsers/ASTOrderByElement.h> #include <Parsers/ASTOrderByElement.h>
#include <Parsers/ASTSelectWithUnionQuery.h> #include <Parsers/ASTSelectWithUnionQuery.h>
#include <Parsers/ASTSelectIntersectExceptQuery.h>
#include <Parsers/ASTTablesInSelectQuery.h> #include <Parsers/ASTTablesInSelectQuery.h>
#include <Parsers/ExpressionListParsers.h> #include <Parsers/ExpressionListParsers.h>
#include <Parsers/parseQuery.h> #include <Parsers/parseQuery.h>
@ -878,16 +879,38 @@ static bool hasWithTotalsInAnySubqueryInFromClause(const ASTSelectQuery & query)
{ {
if (const auto * ast_union = query_table->as<ASTSelectWithUnionQuery>()) if (const auto * ast_union = query_table->as<ASTSelectWithUnionQuery>())
{ {
/// 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) 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<ASTSelectWithUnionQuery>()) if (const auto * child_union = elem->as<ASTSelectWithUnionQuery>())
{ {
for (const auto & child_elem : child_union->list_of_selects->children) for (const auto & child_elem : child_union->list_of_selects->children)
if (hasWithTotalsInAnySubqueryInFromClause(child_elem->as<ASTSelectQuery &>())) if (hasWithTotalsInAnySubqueryInFromClause(child_elem->as<ASTSelectQuery &>()))
return true; 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<ASTSelectIntersectExceptQuery>())
{
std::function<bool(ASTPtr)> traverse_recursively = [&](ASTPtr child_ast) -> bool
{
if (const auto * child = child_ast->as <ASTSelectQuery>())
return hasWithTotalsInAnySubqueryInFromClause(child->as<ASTSelectQuery &>());
if (const auto * child = child_ast->as<ASTSelectWithUnionQuery>())
for (const auto & subchild : child->list_of_selects->children)
if (traverse_recursively(subchild))
return true;
if (const auto * child = child_ast->as<ASTSelectIntersectExceptQuery>())
for (const auto & subchild : child->children)
if (traverse_recursively(subchild))
return true;
return false;
};
if (traverse_recursively(elem))
return true;
}
else else
{ {
if (hasWithTotalsInAnySubqueryInFromClause(elem->as<ASTSelectQuery &>())) if (hasWithTotalsInAnySubqueryInFromClause(elem->as<ASTSelectQuery &>()))

View File

@ -84,6 +84,13 @@ select count() from (select number from numbers(100) intersect select number fro
30 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)); 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 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; select 1 union all select 1 intersect select 1;
1 1
1 1

View File

@ -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(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 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 1;
select 1 union all select 1 intersect select 2; 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; 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;