Skip to content

Commit accec17

Browse files
committed
fix(jdbc-v2): Correctly parse mixed-order CTEs in SqlParser
The grammar for CTEs was too restrictive. It required a specific order for different CTE syntax styles. The grammar expected all CTEs to be defined before all CSEs (Common Scalar Expression). This commit refactors the `ctes` grammar rule to be more flexible. It introduces a new, more generic `cte` rule that can represent either CTE style. The main `ctes` rule is now defined as a list of these generic `cte` elements, allowing them to appear in any order.
1 parent 1e525e7 commit accec17

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

jdbc-v2/src/main/antlr4/com/clickhouse/jdbc/internal/ClickHouseParser.g4

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,12 @@ query
4141

4242
// CTE statement
4343
ctes
44-
: LPAREN? WITH cteUnboundCol? (COMMA cteUnboundCol)* COMMA? namedQuery (COMMA namedQuery)* RPAREN?
44+
: LPAREN? WITH cte (COMMA cte)* RPAREN?
45+
;
46+
47+
cte
48+
: namedQuery
49+
| cteUnboundCol
4550
;
4651

4752
namedQuery

jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/SqlParserTest.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,26 @@ public static Object[][] testCTEStmtsDP() {
252252
};
253253
}
254254

255+
@Test(dataProvider = "testMixedCTEStmtsDP")
256+
public void testMixedCTEStatements(String sql, int args) {
257+
SqlParser parser = new SqlParser();
258+
ParsedPreparedStatement stmt = parser.parsePreparedStatement(sql);
259+
Assert.assertFalse(stmt.isHasErrors());
260+
Assert.assertEquals(stmt.getArgCount(), args);
261+
}
262+
263+
@DataProvider
264+
public static Object[][] testMixedCTEStmtsDP() {
265+
return new Object[][] {
266+
{ "with a as (select ?), (select 2) as b select * from a, b;", 1 },
267+
{ "with (select 2) as b, a as (select ?) select * from a, b;", 1 },
268+
{ "with a as (select ?), (select 2) as b, c as (select ?) select * from a, b, c;", 2 },
269+
{ "with (select 2) as b, a as (select ?), (select 3) as c select * from a, b, c;", 1 },
270+
{ "with (select ?) as a select * from a", 1 },
271+
{ MULTI_PARAMS, 8 },
272+
};
273+
}
274+
255275
@Test(dataProvider = "testMiscStmtDp")
256276
public void testMiscStatements(String sql, int args) {
257277
SqlParser parser = new SqlParser();
@@ -329,6 +349,25 @@ public Object[][] testMiscStmtDp() {
329349
};
330350
}
331351

352+
353+
private static final String MULTI_PARAMS = "with brands as (" +
354+
" select" +
355+
" report_date," +
356+
" language_code" +
357+
" from brands" +
358+
" where domain = ?" +
359+
" and domain_hash = xxHash64(?)" +
360+
" and location_id = ?" +
361+
" and language_code = ?" +
362+
" ), (select max(report_date) as max_report_date from brands) as max_date " +
363+
"select name " +
364+
"from brands " +
365+
"where domain = ?" +
366+
" and domain_hash = xxHash64(?)" +
367+
" and location_id = ?" +
368+
" and language_code = ?" +
369+
" and report_date = max_date";
370+
332371
private static final String INSERT_INLINE_DATA =
333372
"INSERT INTO `interval_15_XUTLZWBLKMNZZPRZSKRF`.`checkins` (`timestamp`, `id`) " +
334373
"VALUES ((`now64`(9) + INTERVAL -225 second), 1)";
@@ -412,4 +451,4 @@ public Object[][] testMiscStmtDp() {
412451
"WHERE\n" +
413452
" EventDate = toDate(?) AND\n" +
414453
" EventTime <= ts_upper_bound;";
415-
}
454+
}

0 commit comments

Comments
 (0)