Skip to content

Commit 4f45dc8

Browse files
committed
Added a few SQL tests fro Statement/PreparedStatement. Addded more tests for parsers
1 parent cf863d4 commit 4f45dc8

File tree

8 files changed

+259
-10
lines changed

8 files changed

+259
-10
lines changed

jdbc-v2/src/main/java/com/clickhouse/jdbc/DriverProperties.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public enum DriverProperties {
6666
* <li>JAVACC - parser extracts required information but PreparedStatement parameters parsed separately.</li>
6767
* </ul>
6868
*/
69-
SQL_PARSER("jdbc_sql_parser", "ANTLR4", List.of("ANTLR4", "ANTLR4_PARAMS_PARSER", "JAVACC")),
69+
SQL_PARSER("jdbc_sql_parser", "JAVACC", List.of("ANTLR4", "ANTLR4_PARAMS_PARSER", "JAVACC")),
7070
;
7171

7272

jdbc-v2/src/test/java/com/clickhouse/jdbc/SQLTests.java renamed to jdbc-v2/src/test/java/com/clickhouse/jdbc/BaseSQLTests.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@
2929
import static org.testng.Assert.fail;
3030

3131
@Test(groups = {"integration"})
32-
public class SQLTests extends JdbcIntegrationTest {
32+
public class BaseSQLTests extends JdbcIntegrationTest {
3333

3434
private static final ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory())
3535
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
3636

37-
@Test(groups = {"integration"}, dataProvider = "testSQLQueryWithResultSetDP")
37+
@Test(groups = {"integration"}, dataProvider = "testSQLQueryWithResultSetDP", enabled = false)
3838
public void testSQLQueryWithResultSet(Map<String, TestDataset> tables, SQLTestCase testCase) throws Exception {
3939

4040
try (Connection connection = getJdbcConnection()) {
@@ -61,9 +61,13 @@ public void testSQLQueryWithResultSet(Map<String, TestDataset> tables, SQLTestCa
6161

6262
@DataProvider(name = "testSQLQueryWithResultSetDP")
6363
public static Object[][] testSQLQueryWithResultSetDP() throws Exception {
64-
ClassLoader classLoader = SQLTests.class.getClassLoader();
65-
try (InputStream datasetsInput = classLoader.getResourceAsStream("datasets.yaml");
66-
InputStream tests = classLoader.getResourceAsStream("SQLTests.yaml")) {
64+
return loadTestData("datasets.yaml", "SQLTests.yaml");
65+
}
66+
67+
protected static Object[][] loadTestData(String datasetsSource, String sqlTestsSource) throws Exception {
68+
ClassLoader classLoader = BaseSQLTests.class.getClassLoader();
69+
try (InputStream datasetsInput = classLoader.getResourceAsStream(datasetsSource);
70+
InputStream tests = classLoader.getResourceAsStream(sqlTestsSource)) {
6771

6872
// Parse resource files
6973
TestDataset[] datasets = yamlMapper.readValue(datasetsInput, TestDataset[].class);
@@ -91,12 +95,11 @@ public static Object[][] testSQLQueryWithResultSetDP() throws Exception {
9195

9296
return testData;
9397
} catch (Exception e) {
94-
e.printStackTrace();
9598
throw new RuntimeException(e);
9699
}
97100
}
98101

99-
private void setupTables(Map<String, TestDataset> tables, Connection connection) throws Exception {
102+
protected void setupTables(Map<String, TestDataset> tables, Connection connection) throws Exception {
100103
for (Map.Entry<String, TestDataset> entry : tables.entrySet()) {
101104
String tableName = entry.getKey();
102105
TestDataset dataset = entry.getValue();
@@ -155,7 +158,7 @@ public int rsMetadataChecks(ResultSet rs, SQLTestCase testCase, Map<String, Test
155158
return checkCount;
156159
}
157160

158-
private int dataCheck(ResultSet rs, SQLTestCase testCase, Map<String, TestDataset> tables) throws Exception {
161+
protected int dataCheck(ResultSet rs, SQLTestCase testCase, Map<String, TestDataset> tables) throws Exception {
159162

160163
List<Pair<TestResultCheckModel, DataCheck>> checks = testCase.getChecks().stream().filter(cm -> DATA_CHECKS.containsKey(cm.getName()))
161164
.map(cm -> Pair.of(cm, DATA_CHECKS.get(cm.getName()))).collect(Collectors.toList());
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.clickhouse.jdbc;
2+
3+
4+
import org.testng.Assert;
5+
import org.testng.annotations.DataProvider;
6+
import org.testng.annotations.Test;
7+
8+
import java.sql.Connection;
9+
import java.sql.PreparedStatement;
10+
import java.sql.ResultSet;
11+
import java.util.Map;
12+
13+
/**
14+
* Integration test for prepared statement. Testing SQL with prepared statement is main focus of this test.
15+
* Any tests that relate to schema, data type, tricky SQL comes here.
16+
*
17+
*/
18+
@Test(groups = {"integration"}, enabled = false)
19+
public class PreparedStatementSQLTest extends BaseSQLTests {
20+
21+
@Test(groups = {"integration"}, dataProvider = "testSQLStatements")
22+
public void testQuery(Map<String, TestDataset> tables, SQLTestCase testCase) throws Exception {
23+
24+
try (Connection connection = getJdbcConnection()) {
25+
setupTables(tables, connection);
26+
27+
try (PreparedStatement stmt = connection.prepareStatement(testCase.getQuery());
28+
ResultSet rs = stmt.executeQuery()) {
29+
30+
int checkCount = 0;
31+
checkCount += rsMetadataChecks(rs, testCase, tables);
32+
checkCount += dataCheck(rs, testCase, tables);
33+
Assert.assertEquals(checkCount, testCase.getChecks().size(), "Check count does not match");
34+
Assert.assertTrue(checkCount > 0, "Test without checks");
35+
}
36+
}
37+
}
38+
39+
40+
@DataProvider(name = "testSQLStatements")
41+
public static Object[][] testSQLStatementsDP() throws Exception {
42+
return loadTestData("datasets.yaml", "PreparedStatementSQLTests.yaml");
43+
}
44+
45+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.clickhouse.jdbc;
2+
3+
4+
import org.testng.Assert;
5+
import org.testng.annotations.DataProvider;
6+
import org.testng.annotations.Test;
7+
8+
import java.sql.Connection;
9+
import java.sql.PreparedStatement;
10+
import java.sql.ResultSet;
11+
import java.sql.Statement;
12+
import java.util.Map;
13+
import java.util.concurrent.atomic.AtomicBoolean;
14+
15+
/**
16+
* Integration test for prepared statement. Testing SQL with prepared statement is main focus of this test.
17+
* Any tests that relate to schema, data type, tricky SQL comes here.
18+
*
19+
*/
20+
@Test(groups = {"integration"})
21+
public class StatementSQLTest extends BaseSQLTests {
22+
23+
private AtomicBoolean isTablesSetup = new AtomicBoolean(false);
24+
25+
26+
@Test(groups = {"integration"}, dataProvider = "testSQLStatements")
27+
public void testQuery(Map<String, TestDataset> tables, SQLTestCase testCase) throws Exception {
28+
29+
try (Connection connection = getJdbcConnection()) {
30+
setupTables(tables, connection);
31+
32+
try (Statement stmt = connection.createStatement();
33+
ResultSet rs = stmt.executeQuery(testCase.getQuery())) {
34+
35+
int checkCount = 0;
36+
checkCount += rsMetadataChecks(rs, testCase, tables);
37+
checkCount += dataCheck(rs, testCase, tables);
38+
Assert.assertEquals(checkCount, testCase.getChecks().size(), "Check count does not match");
39+
Assert.assertTrue(checkCount > 0, "Test without checks");
40+
}
41+
}
42+
}
43+
44+
45+
@DataProvider(name = "testSQLStatements")
46+
public static Object[][] testSQLStatementsDP() throws Exception {
47+
return loadTestData("datasets.yaml", "StatementSQLTests.yaml");
48+
}
49+
50+
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,9 +344,16 @@ public Object[][] testMiscStmtDp() {
344344
{" \n INSERT INTO TESTING \n SELECT ? AS num", 1},
345345
{" SELECT '##?0.1' as f, ? as a\n #this is debug \n FROM table", 1},
346346
{"WITH '#!?0.1' as f, ? as a\n #this is debug \n SELECT * FROM a", 1},
347+
{SELECT_WITH_WHERE_CLAUSE_FUNC_WITH_PARAMS, 2}
347348
};
348349
}
349350

351+
private static final String SELECT_WITH_WHERE_CLAUSE_FUNC_WITH_PARAMS = "SELECT `source`.`id` AS `id`,\n" +
352+
" `source`.`val` AS `val` FROM\n" +
353+
" (with base as (\\n select 1 id, 'abc' val\\n)\\nselect * from base)\n" +
354+
" AS `source`\n" +
355+
" WHERE `positionCaseInsensitiveUTF8`(`source`.`val`, ?) > ? LIMIT 2000";
356+
350357
private static final String INSERT_WITH_COMMENTS = "-- line comment1 ?\n"
351358
+ "# line comment2 ?\n"
352359
+ "#! line comment3 ?\n"
@@ -459,6 +466,7 @@ public static Object[][] testStatementWithoutResultSetDP() {
459466
return new Object[][]{
460467
/* has result set */
461468
{"SELECT * FROM test_table", 0, true},
469+
{"SELECT 1 table WHERE 1 = ?", 1, true},
462470
{"SHOW CREATE TABLE `db`.`test_table`", 0, true},
463471
{"SHOW CREATE TEMPORARY TABLE `db1`.`tmp_table`", 0, true},
464472
{"SHOW CREATE DICTIONARY dict1", 0, true},
@@ -559,6 +567,7 @@ public static Object[][] testStatementWithoutResultSetDP() {
559567
{"CREATE SETTINGS PROFILE max_memory_usage_profile SETTINGS max_memory_usage = 100000001 MIN 90000000 MAX 110000000 TO robin", 0, false},
560568
{"CREATE NAMED COLLECTION foobar AS a = '1', b = '2' OVERRIDABLE", 0, false},
561569
{"alter table t2 alter column v type Int32", 0, false},
570+
{"alter table t alter column j default 1", 0, false},
562571
{"ALTER TABLE t MODIFY COLUMN j default 1", 0, false},
563572
{"ALTER TABLE t MODIFY COMMENT 'comment'", 0, false},
564573
{"ALTER TABLE t ADD COLUMN id Int32 AFTER v", 0, false},
@@ -567,6 +576,7 @@ public static Object[][] testStatementWithoutResultSetDP() {
567576
{"DELETE FROM table WHERE a = ?", 1, false},
568577
{"DELETE FROM table WHERE a = ? AND b = ?", 2, false},
569578
{"DELETE FROM hits WHERE Title LIKE '%hello%';", 0, false},
579+
{"DELETE FROM t WHERE true", 0, false},
570580
{"SYSTEM START FETCHES", 0, false},
571581
{"SYSTEM RELOAD DICTIONARIES", 0, false},
572582
{"SYSTEM RELOAD DICTIONARIES ON CLUSTER `default`", 0, false},
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
- name: select_all_events
3+
query: SELECT * FROM events
4+
tables:
5+
events: datasets/events
6+
# checks:
7+
# - name: row_count
8+
# expected: ${events.rowCount}
9+
# - name: column_count
10+
# expected: ${events.columnsCount}
11+
# - name: column_names
12+
# expected: ${events.columnNames}
13+
# - name: column_types
14+
# expected: ${events.columnTypes}
15+
- name: cte_select_with_params_01
16+
query: |
17+
WITH
18+
toDate('2025-08-20') as DATE_END
19+
,events AS (
20+
SELECT 1
21+
)
22+
SELECT *
23+
FROM events
24+
tables:
25+
events: datasets/events
26+
checks:
27+
- name: row_count
28+
expected: 1
29+
- name: column_count
30+
expected: 1
31+
- name: column_names
32+
expected: ["1"]
33+
- name: column_types
34+
expected: ["UInt8"]
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
---
2+
- name: select_all_events
3+
query: SELECT * FROM events
4+
tables:
5+
events: datasets/events
6+
# checks:
7+
# - name: row_count
8+
# expected: ${events.rowCount}
9+
# - name: column_count
10+
# expected: ${events.columnsCount}
11+
# - name: column_names
12+
# expected: ${events.columnNames}
13+
# - name: column_types
14+
# expected: ${events.columnTypes}
15+
- name: select_with_01
16+
query: |
17+
WITH
18+
toDate('2025-08-20') as DATE_END,
19+
cte_events AS (
20+
SELECT 1, DATE_END
21+
)
22+
SELECT *, DATE_END
23+
FROM cte_events
24+
tables:
25+
events: datasets/events
26+
checks:
27+
- name: column_count
28+
expected: 3
29+
- name: column_names
30+
expected: ["1", "cte_events.DATE_END", "DATE_END"]
31+
- name: column_types
32+
expected: ["UInt8", "Date", "Date"]
33+
- name: select_with_02
34+
query: |
35+
WITH
36+
toDate('2025-08-20') as DATE_END,
37+
cte_events AS (
38+
SELECT 1
39+
)
40+
SELECT *
41+
FROM cte_events
42+
tables:
43+
events: datasets/events
44+
checks:
45+
- name: row_count
46+
expected: 1
47+
- name: column_count
48+
expected: 1
49+
- name: column_names
50+
expected: ["1"]
51+
- name: column_types
52+
expected: ["UInt8"]
53+
- name: select_with_fill_03
54+
query: |
55+
SELECT
56+
value,
57+
toUnixTimestamp(ts1) * 1000 AS timestamp
58+
FROM
59+
(
60+
SELECT
61+
count() AS value,
62+
toStartOfInterval(ts, toIntervalDay(1)) AS ts1
63+
FROM events
64+
WHERE (ts >= toDateTime(1736035200)) AND (ts <= toDateTime(1751587199))
65+
GROUP BY ts1
66+
ORDER BY ts1 ASC WITH FILL FROM toDateTime(1736035200) TO toDateTime(1751587199) STEP toIntervalDay(1)
67+
)
68+
tables:
69+
events: datasets/events
70+
checks:
71+
- name: row_count
72+
expected: 180
73+
- name: column_count
74+
expected: 2
75+
- name: column_names
76+
expected: ["value", "timestamp"]
77+
- name: column_types
78+
expected: ["UInt64", "UInt64"]
79+
- name: explain_stmt_01
80+
query: EXPLAIN SELECT 1
81+
tables:
82+
events: datasets/empty_table
83+
checks:
84+
- name: row_count
85+
expected: 2
86+
- name: column_count
87+
expected: 1
88+
- name: column_names
89+
expected: ["explain"]
90+
- name: column_types
91+
expected: ["String"]

jdbc-v2/src/test/resources/datasets.yaml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,20 @@
1212
- ["4", "event2", "2025-01-02 00:02:00.004000000", "30.2"]
1313
- ["5", "event1", "2025-01-05 00:01:10.002000000", "12.8"]
1414
- ["6", "event3", "2025-01-02 00:01:20.003000000", "45.9"]
15-
- ["7", "event4", "2025-01-02 00:01:30.004000000", "22.1"]
15+
- ["7", "event4", "2025-01-02 00:01:30.004000000", "22.1"]
16+
- name: empty_table
17+
columns:
18+
- "Int8 Int8"
19+
- "Int16 Int16"
20+
- "Int32 Int32"
21+
- "Int64 Int64"
22+
- "UInt8 UInt8"
23+
- "UInt16 UInt16"
24+
- "UInt32 UInt32"
25+
- "UInt64 UInt64"
26+
- "Float32 Float32"
27+
- "Float64 Float64"
28+
- "String String"
29+
- "DateTime DateTime"
30+
- "DateTime64 DateTime64"
31+
data: []

0 commit comments

Comments
 (0)