Skip to content

Commit c9635f9

Browse files
Merge pull request ClickHouse#79952 from ClickHouse/fix-inconsistent-formatting-except
Fix inconsistent formatting with EXCEPT
2 parents 1c5a1bf + 3e5edb4 commit c9635f9

File tree

5 files changed

+67
-15
lines changed

5 files changed

+67
-15
lines changed

src/Parsers/ASTSelectWithUnionQuery.cpp

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ void ASTSelectWithUnionQuery::formatQueryImpl(WriteBuffer & ostr, const FormatSe
3030
{
3131
std::string indent_str = settings.one_line ? "" : std::string(4 * frame.indent, ' ');
3232

33-
auto mode_to_str = [&](auto mode)
33+
auto mode_to_str = [&](SelectUnionMode mode)
3434
{
3535
if (mode == SelectUnionMode::UNION_DEFAULT)
3636
return "UNION";
@@ -53,26 +53,55 @@ void ASTSelectWithUnionQuery::formatQueryImpl(WriteBuffer & ostr, const FormatSe
5353
return "";
5454
};
5555

56+
auto is_except = [](SelectUnionMode mode)
57+
{
58+
return mode == SelectUnionMode::EXCEPT_DEFAULT
59+
|| mode == SelectUnionMode::EXCEPT_ALL
60+
|| mode == SelectUnionMode::EXCEPT_DISTINCT;
61+
};
62+
63+
auto get_mode = [&](ASTs::const_iterator it)
64+
{
65+
return is_normalized
66+
? union_mode
67+
: list_of_modes[it - list_of_selects->children.begin() - 1];
68+
};
69+
5670
for (ASTs::const_iterator it = list_of_selects->children.begin(); it != list_of_selects->children.end(); ++it)
5771
{
5872
if (it != list_of_selects->children.begin())
73+
{
5974
ostr << settings.nl_or_ws << indent_str << (settings.hilite ? hilite_keyword : "")
60-
<< mode_to_str((is_normalized) ? union_mode : list_of_modes[it - list_of_selects->children.begin() - 1])
61-
<< (settings.hilite ? hilite_none : "");
75+
<< mode_to_str(get_mode(it))
76+
<< (settings.hilite ? hilite_none : "")
77+
<< settings.nl_or_ws;
78+
}
6279

63-
if (auto * /*node*/ _ = (*it)->as<ASTSelectWithUnionQuery>())
64-
{
65-
if (it != list_of_selects->children.begin())
66-
ostr << settings.nl_or_ws;
80+
bool need_parens = false;
6781

82+
/// EXCEPT can be confused with the asterisk modifier:
83+
/// SELECT * EXCEPT SELECT 1 -- two queries
84+
/// SELECT * EXCEPT col -- a modifier for asterisk
85+
/// For this reason, add parentheses when formatting any side of EXCEPT.
86+
ASTs::const_iterator next = it;
87+
++next;
88+
if ((it != list_of_selects->children.begin() && is_except(get_mode(it)))
89+
|| (next != list_of_selects->children.end() && is_except(get_mode(next))))
90+
need_parens = true;
91+
92+
/// If this is a subtree with another chain of selects, we also need parens.
93+
auto * union_node = (*it)->as<ASTSelectWithUnionQuery>();
94+
if (union_node)
95+
need_parens = true;
96+
97+
if (need_parens)
98+
{
6899
ostr << indent_str;
69-
auto sub_query = std::make_shared<ASTSubquery>(*it);
70-
sub_query->format(ostr, settings, state, frame);
100+
auto subquery = std::make_shared<ASTSubquery>(*it);
101+
subquery->format(ostr, settings, state, frame);
71102
}
72103
else
73104
{
74-
if (it != list_of_selects->children.begin())
75-
ostr << settings.nl_or_ws;
76105
(*it)->format(ostr, settings, state, frame);
77106
}
78107
}

src/Parsers/ASTSelectWithUnionQuery.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ class ASTSelectWithUnionQuery : public ASTQueryWithOutput
2020
QueryKind getQueryKind() const override { return QueryKind::Select; }
2121

2222
SelectUnionMode union_mode;
23-
2423
SelectUnionModes list_of_modes;
25-
2624
bool is_normalized = false;
2725

2826
ASTPtr list_of_selects;
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
SELECT 1
22
UNION
33
SELECT 1
4-
SELECT 2
4+
(
5+
SELECT 2
6+
)
57
EXCEPT
6-
SELECT 2
8+
(
9+
SELECT 2
10+
)
711
SELECT 3
812
INTERSECT
913
SELECT 3
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-- { echo }
2+
3+
SELECT (*) EXCEPT SELECT 1;
4+
0
5+
(SELECT *) EXCEPT SELECT 1;
6+
0
7+
SELECT * + 1 EXCEPT SELECT 1;
8+
(SELECT * EXCEPT a) EXCEPT SELECT 1;
9+
0
10+
SELECT * FROM (SELECT 1 UNION ALL SELECT 2 EXCEPT SELECT 3 UNION ALL SELECT (*) EXCEPT SELECT 4) ORDER BY *;
11+
0
12+
1
13+
2
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
SET enable_analyzer = 1;
2+
-- { echo }
3+
4+
SELECT (*) EXCEPT SELECT 1;
5+
(SELECT *) EXCEPT SELECT 1;
6+
SELECT * + 1 EXCEPT SELECT 1;
7+
(SELECT * EXCEPT a) EXCEPT SELECT 1;
8+
SELECT * FROM (SELECT 1 UNION ALL SELECT 2 EXCEPT SELECT 3 UNION ALL SELECT (*) EXCEPT SELECT 4) ORDER BY *;

0 commit comments

Comments
 (0)