From 8b35b27c32a19487e13aa7ee2eb1e1f3931d615f Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Wed, 4 Jun 2025 17:45:48 -0700 Subject: [PATCH] fixed arguments with casts --- .../jdbc/internal/ClickHouseLexer.g4 | 2 ++ .../jdbc/internal/ClickHouseParser.g4 | 1 + .../internal/ParsedPreparedStatement.java | 5 ++++ .../jdbc/PreparedStatementTest.java | 24 +++++++++++++++++++ .../jdbc/internal/SqlParserTest.java | 17 +++++++++++++ 5 files changed, 49 insertions(+) diff --git a/jdbc-v2/src/main/antlr4/com/clickhouse/jdbc/internal/ClickHouseLexer.g4 b/jdbc-v2/src/main/antlr4/com/clickhouse/jdbc/internal/ClickHouseLexer.g4 index ac3bbbea6..67ffdd846 100644 --- a/jdbc-v2/src/main/antlr4/com/clickhouse/jdbc/internal/ClickHouseLexer.g4 +++ b/jdbc-v2/src/main/antlr4/com/clickhouse/jdbc/internal/ClickHouseLexer.g4 @@ -223,6 +223,8 @@ OCTAL_LITERAL : '0' OCT_DIGIT+; DECIMAL_LITERAL : DEC_DIGIT+; HEXADECIMAL_LITERAL : '0' X HEX_DIGIT+; +CAST_OP : '::'; + // It's important that quote-symbol is a single character. STRING_LITERAL: QUOTE_SINGLE (~([\\']) | (BACKSLASH .) | (QUOTE_SINGLE QUOTE_SINGLE))* QUOTE_SINGLE 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 896ffb7bf..a589069dd 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 @@ -649,6 +649,7 @@ columnExpr | LBRACKET columnExprList? RBRACKET # ColumnExprArray | columnIdentifier # ColumnExprIdentifier | QUERY # ColumnExprParam + | QUERY CAST_OP identifier # ColumnExprParamWithCast ; columnArgList diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/ParsedPreparedStatement.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/ParsedPreparedStatement.java index 144b85426..f69e480d6 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/ParsedPreparedStatement.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/ParsedPreparedStatement.java @@ -167,6 +167,11 @@ public void enterColumnExprParam(ClickHouseParser.ColumnExprParamContext ctx) { appendParameter(ctx.start.getStartIndex()); } + @Override + public void enterColumnExprParamWithCast(ClickHouseParser.ColumnExprParamWithCastContext ctx) { + appendParameter(ctx.start.getStartIndex()); + } + @Override public void visitErrorNode(ErrorNode node) { setHasErrors(true); diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java index 002fb5fb4..565e6f8a0 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java @@ -3,6 +3,7 @@ import com.clickhouse.data.ClickHouseVersion; import com.clickhouse.jdbc.internal.DriverProperties; import org.apache.commons.lang3.RandomStringUtils; +import org.testcontainers.shaded.com.fasterxml.jackson.databind.deser.std.UUIDDeserializer; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Ignore; @@ -1051,4 +1052,27 @@ public void testNullValues() throws Exception { } } } + + @Test + public void testParamWithCast() throws Exception { + final String sql = " SELECT ?::integer, '?::integer', 123, ?:: UUID, ?"; + try (Connection conn = getJdbcConnection()) { + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, "1000"); + UUID uuid = UUID.randomUUID(); + stmt.setString(1, "1000"); + stmt.setString(2, uuid.toString()); + stmt.setInt(3, 3003001); + + try (ResultSet rs = stmt.executeQuery()) { + assertTrue(rs.next()); + Assert.assertEquals(rs.getInt(1), 1000); + Assert.assertEquals(rs.getString(2), "?::integer"); + Assert.assertEquals(rs.getInt(3), 123); + Assert.assertEquals(rs.getString(4), uuid.toString()); + Assert.assertEquals(rs.getInt(5), 3003001); + } + } + } + } } 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 59fa603dc..83adc500d 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 @@ -1,6 +1,7 @@ package com.clickhouse.jdbc.internal; +import org.testng.Assert; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; @@ -193,4 +194,20 @@ public void testEscapeQuotes() { assertEquals(SqlParser.escapeQuotes(inStr[i]), outStr[i]); } } + + @Test + public void testStmtWithCasts() { + String sql = "SELECT ?::integer, ?, '?::integer' FROM table WHERE v = ?::integer"; // CAST(?, INTEGER) + SqlParser parser = new SqlParser(); + ParsedPreparedStatement stmt = parser.parsePreparedStatement(sql); + Assert.assertEquals(stmt.getArgCount(), 3); + } + + @Test + public void testStmtWithFunction() { + String sql = "SELECT `parseDateTimeBestEffort`(?, ?) as dt FROM table WHERE v > `parseDateTimeBestEffort`(?, ?) "; + SqlParser parser = new SqlParser(); + ParsedPreparedStatement stmt = parser.parsePreparedStatement(sql); + Assert.assertEquals(stmt.getArgCount(), 4); + } } \ No newline at end of file