Skip to content

Commit 576ae9c

Browse files
authored
parser: fix parsing nested compound select with parens (#464)
we were handling ```sql SELECT ( (SELECT c FROM t) UNION SELECT c FROM u ) LIMIT 1; ``` but not ```sql SELECT ( (SELECT c FROM t) UNION (SELECT c FROM u) ) LIMIT 1; ``` related: #463
1 parent 167b8bd commit 576ae9c

File tree

3 files changed

+277
-1
lines changed

3 files changed

+277
-1
lines changed

crates/squawk_parser/src/grammar.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2332,7 +2332,15 @@ fn compound_select(p: &mut Parser<'_>, cm: CompletedMarker) -> CompletedMarker {
23322332
if !p.eat(ALL_KW) {
23332333
p.eat(DISTINCT_KW);
23342334
}
2335-
select_stmt(p, None);
2335+
if p.at(L_PAREN) {
2336+
tuple_expr(p);
2337+
} else {
2338+
if p.at_ts(SELECT_FIRST) {
2339+
select_stmt(p, None);
2340+
} else {
2341+
p.error("expected start of a select statement")
2342+
}
2343+
}
23362344
m.complete(p, COMPOUND_SELECT)
23372345
}
23382346

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
---
2+
source: crates/squawk_parser/src/test.rs
3+
input_file: crates/squawk_parser/test_data/ok/select_compound_union_select.sql
4+
---
5+
SOURCE_FILE
6+
SELECT
7+
SELECT_CLAUSE
8+
SELECT_KW "SELECT"
9+
WHITESPACE " "
10+
TARGET_LIST
11+
TARGET
12+
PAREN_EXPR
13+
L_PAREN "("
14+
WHITESPACE "\n "
15+
COMPOUND_SELECT
16+
PAREN_EXPR
17+
L_PAREN "("
18+
SELECT
19+
SELECT_CLAUSE
20+
SELECT_KW "SELECT"
21+
WHITESPACE " "
22+
TARGET_LIST
23+
TARGET
24+
NAME_REF
25+
IDENT "id"
26+
WHITESPACE " "
27+
FROM_CLAUSE
28+
FROM_KW "FROM"
29+
WHITESPACE " "
30+
NAME_REF
31+
IDENT "code_categories"
32+
WHITESPACE " "
33+
WHERE_CLAUSE
34+
WHERE_KW "WHERE"
35+
WHITESPACE " "
36+
BIN_EXPR
37+
NAME_REF
38+
IDENT "\"language\""
39+
WHITESPACE " "
40+
EQ "="
41+
WHITESPACE " "
42+
PREFIX_EXPR
43+
CUSTOM_OP
44+
AT "@"
45+
CAST_EXPR
46+
NAME_REF
47+
LANGUAGE_KW "language"
48+
COLON2 "::"
49+
CHAR_TYPE
50+
CHAR_KW "char"
51+
L_PAREN "("
52+
ARG_LIST
53+
ARG
54+
LITERAL
55+
INT_NUMBER "4"
56+
R_PAREN ")"
57+
WHITESPACE " "
58+
ORDER_BY_CLAUSE
59+
ORDER_KW "ORDER"
60+
WHITESPACE " "
61+
BY_KW "BY"
62+
WHITESPACE " "
63+
NAME_REF
64+
IDENT "\"id\""
65+
WHITESPACE " "
66+
ASC_KW "ASC"
67+
WHITESPACE " "
68+
LIMIT_CLAUSE
69+
LIMIT_KW "LIMIT"
70+
WHITESPACE " "
71+
LITERAL
72+
INT_NUMBER "1"
73+
R_PAREN ")"
74+
WHITESPACE "\n "
75+
UNION_KW "UNION"
76+
WHITESPACE "\n "
77+
PAREN_EXPR
78+
L_PAREN "("
79+
SELECT
80+
SELECT_CLAUSE
81+
SELECT_KW "SELECT"
82+
WHITESPACE " "
83+
TARGET_LIST
84+
TARGET
85+
NAME_REF
86+
IDENT "id"
87+
WHITESPACE " "
88+
FROM_CLAUSE
89+
FROM_KW "FROM"
90+
WHITESPACE " "
91+
NAME_REF
92+
IDENT "code_categories"
93+
WHITESPACE " "
94+
WHERE_CLAUSE
95+
WHERE_KW "WHERE"
96+
WHITESPACE " "
97+
BIN_EXPR
98+
NAME_REF
99+
IDENT "\"language\""
100+
WHITESPACE " "
101+
EQ "="
102+
WHITESPACE " "
103+
LITERAL
104+
STRING "'nl-NL'"
105+
WHITESPACE " "
106+
ORDER_BY_CLAUSE
107+
ORDER_KW "ORDER"
108+
WHITESPACE " "
109+
BY_KW "BY"
110+
WHITESPACE " "
111+
NAME_REF
112+
IDENT "\"id\""
113+
WHITESPACE " "
114+
ASC_KW "ASC"
115+
WHITESPACE " "
116+
LIMIT_CLAUSE
117+
LIMIT_KW "LIMIT"
118+
WHITESPACE " "
119+
LITERAL
120+
INT_NUMBER "1"
121+
R_PAREN ")"
122+
WHITESPACE "\n"
123+
R_PAREN ")"
124+
WHITESPACE " "
125+
LIMIT_CLAUSE
126+
LIMIT_KW "LIMIT"
127+
WHITESPACE " "
128+
LITERAL
129+
INT_NUMBER "1"
130+
SEMICOLON ";"
131+
WHITESPACE "\n\n"
132+
COMMENT "-- version without parentheses."
133+
WHITESPACE "\n"
134+
SELECT
135+
SELECT_CLAUSE
136+
SELECT_KW "SELECT"
137+
WHITESPACE " "
138+
TARGET_LIST
139+
TARGET
140+
PAREN_EXPR
141+
L_PAREN "("
142+
WHITESPACE "\n "
143+
COMPOUND_SELECT
144+
PAREN_EXPR
145+
L_PAREN "("
146+
SELECT
147+
SELECT_CLAUSE
148+
SELECT_KW "SELECT"
149+
WHITESPACE " "
150+
TARGET_LIST
151+
TARGET
152+
NAME_REF
153+
IDENT "id"
154+
WHITESPACE " "
155+
FROM_CLAUSE
156+
FROM_KW "FROM"
157+
WHITESPACE " "
158+
NAME_REF
159+
IDENT "code_categories"
160+
WHITESPACE " "
161+
WHERE_CLAUSE
162+
WHERE_KW "WHERE"
163+
WHITESPACE " "
164+
BIN_EXPR
165+
NAME_REF
166+
IDENT "\"language\""
167+
WHITESPACE " "
168+
EQ "="
169+
WHITESPACE " "
170+
PREFIX_EXPR
171+
CUSTOM_OP
172+
AT "@"
173+
CAST_EXPR
174+
NAME_REF
175+
LANGUAGE_KW "language"
176+
COLON2 "::"
177+
CHAR_TYPE
178+
CHAR_KW "char"
179+
L_PAREN "("
180+
ARG_LIST
181+
ARG
182+
LITERAL
183+
INT_NUMBER "4"
184+
R_PAREN ")"
185+
WHITESPACE " "
186+
ORDER_BY_CLAUSE
187+
ORDER_KW "ORDER"
188+
WHITESPACE " "
189+
BY_KW "BY"
190+
WHITESPACE " "
191+
NAME_REF
192+
IDENT "\"id\""
193+
WHITESPACE " "
194+
ASC_KW "ASC"
195+
WHITESPACE " "
196+
LIMIT_CLAUSE
197+
LIMIT_KW "LIMIT"
198+
WHITESPACE " "
199+
LITERAL
200+
INT_NUMBER "1"
201+
R_PAREN ")"
202+
WHITESPACE "\n "
203+
UNION_KW "UNION"
204+
WHITESPACE "\n "
205+
SELECT
206+
SELECT_CLAUSE
207+
SELECT_KW "SELECT"
208+
WHITESPACE " "
209+
TARGET_LIST
210+
TARGET
211+
NAME_REF
212+
IDENT "id"
213+
WHITESPACE " "
214+
FROM_CLAUSE
215+
FROM_KW "FROM"
216+
WHITESPACE " "
217+
NAME_REF
218+
IDENT "code_categories"
219+
WHITESPACE " "
220+
WHERE_CLAUSE
221+
WHERE_KW "WHERE"
222+
WHITESPACE " "
223+
BIN_EXPR
224+
NAME_REF
225+
IDENT "\"language\""
226+
WHITESPACE " "
227+
EQ "="
228+
WHITESPACE " "
229+
LITERAL
230+
STRING "'nl-NL'"
231+
WHITESPACE " "
232+
ORDER_BY_CLAUSE
233+
ORDER_KW "ORDER"
234+
WHITESPACE " "
235+
BY_KW "BY"
236+
WHITESPACE " "
237+
NAME_REF
238+
IDENT "\"id\""
239+
WHITESPACE " "
240+
ASC_KW "ASC"
241+
WHITESPACE " "
242+
LIMIT_CLAUSE
243+
LIMIT_KW "LIMIT"
244+
WHITESPACE " "
245+
LITERAL
246+
INT_NUMBER "1"
247+
WHITESPACE "\n"
248+
R_PAREN ")"
249+
WHITESPACE " "
250+
LIMIT_CLAUSE
251+
LIMIT_KW "LIMIT"
252+
WHITESPACE " "
253+
LITERAL
254+
INT_NUMBER "1"
255+
SEMICOLON ";"
256+
WHITESPACE "\n"
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
SELECT (
2+
(SELECT id FROM code_categories WHERE "language" = @language::char(4) ORDER BY "id" ASC LIMIT 1)
3+
UNION
4+
(SELECT id FROM code_categories WHERE "language" = 'nl-NL' ORDER BY "id" ASC LIMIT 1)
5+
) LIMIT 1;
6+
7+
-- version without parentheses.
8+
SELECT (
9+
(SELECT id FROM code_categories WHERE "language" = @language::char(4) ORDER BY "id" ASC LIMIT 1)
10+
UNION
11+
SELECT id FROM code_categories WHERE "language" = 'nl-NL' ORDER BY "id" ASC LIMIT 1
12+
) LIMIT 1;

0 commit comments

Comments
 (0)