diff --git a/jdbc-v2/src/main/antlr4/com/clickhouse/jdbc/internal/ClickHouseParser.g4 b/jdbc-v2/src/main/antlr4/com/clickhouse/jdbc/internal/ClickHouseParser.g4 index d6b06a28f..510bd0b04 100644 --- a/jdbc-v2/src/main/antlr4/com/clickhouse/jdbc/internal/ClickHouseParser.g4 +++ b/jdbc-v2/src/main/antlr4/com/clickhouse/jdbc/internal/ClickHouseParser.g4 @@ -41,7 +41,12 @@ query // CTE statement ctes - : LPAREN? WITH cteUnboundCol? (COMMA cteUnboundCol)* COMMA? namedQuery (COMMA namedQuery)* RPAREN? + : LPAREN? WITH cte (COMMA cte)* RPAREN? + ; + +cte + : namedQuery + | cteUnboundCol ; namedQuery diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/SqlParserTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/SqlParserTest.java index 61e84df1b..ee5e12e8a 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/SqlParserTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/SqlParserTest.java @@ -252,6 +252,26 @@ public static Object[][] testCTEStmtsDP() { }; } + @Test(dataProvider = "testMixedCTEStmtsDP") + public void testMixedCTEStatements(String sql, int args) { + SqlParser parser = new SqlParser(); + ParsedPreparedStatement stmt = parser.parsePreparedStatement(sql); + Assert.assertFalse(stmt.isHasErrors()); + Assert.assertEquals(stmt.getArgCount(), args); + } + + @DataProvider + public static Object[][] testMixedCTEStmtsDP() { + return new Object[][] { + { "with a as (select ?), (select 2) as b select * from a, b;", 1 }, + { "with (select 2) as b, a as (select ?) select * from a, b;", 1 }, + { "with a as (select ?), (select 2) as b, c as (select ?) select * from a, b, c;", 2 }, + { "with (select 2) as b, a as (select ?), (select 3) as c select * from a, b, c;", 1 }, + { "with (select ?) as a select * from a", 1 }, + { MULTI_PARAMS, 8 }, + }; + } + @Test(dataProvider = "testMiscStmtDp") public void testMiscStatements(String sql, int args) { SqlParser parser = new SqlParser(); @@ -329,6 +349,25 @@ public Object[][] testMiscStmtDp() { }; } + + private static final String MULTI_PARAMS = "with brands as (" + + " select" + + " report_date," + + " language_code" + + " from brands" + + " where domain = ?" + + " and domain_hash = xxHash64(?)" + + " and location_id = ?" + + " and language_code = ?" + + " ), (select max(report_date) as max_report_date from brands) as max_date " + + "select name " + + "from brands " + + "where domain = ?" + + " and domain_hash = xxHash64(?)" + + " and location_id = ?" + + " and language_code = ?" + + " and report_date = max_date"; + private static final String INSERT_INLINE_DATA = "INSERT INTO `interval_15_XUTLZWBLKMNZZPRZSKRF`.`checkins` (`timestamp`, `id`) " + "VALUES ((`now64`(9) + INTERVAL -225 second), 1)"; @@ -412,4 +451,4 @@ public Object[][] testMiscStmtDp() { "WHERE\n" + " EventDate = toDate(?) AND\n" + " EventTime <= ts_upper_bound;"; -} \ No newline at end of file +}