From 827e7c189b08c881762807bc597c4a8a7e166d74 Mon Sep 17 00:00:00 2001 From: Zhichun Wu Date: Thu, 6 May 2021 10:05:08 +0800 Subject: [PATCH 1/9] Ignore database only for DDL containing DATABASE keyword, and allow to change current database of a statement --- .../clickhouse/ClickHouseStatementImpl.java | 13 +++-- .../ClickHouseConnectionImplTest.java | 50 ++++++++++++++++++- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseStatementImpl.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseStatementImpl.java index 7699f5833..47d25c406 100644 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseStatementImpl.java +++ b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseStatementImpl.java @@ -43,6 +43,7 @@ import ru.yandex.clickhouse.except.ClickHouseExceptionSpecifier; import ru.yandex.clickhouse.jdbc.parser.ClickHouseSqlParser; import ru.yandex.clickhouse.jdbc.parser.ClickHouseSqlStatement; +import ru.yandex.clickhouse.jdbc.parser.StatementType; import ru.yandex.clickhouse.response.ClickHouseLZ4Stream; import ru.yandex.clickhouse.response.ClickHouseResponse; import ru.yandex.clickhouse.response.ClickHouseResponseSummary; @@ -141,7 +142,7 @@ public boolean isStreaming() { * between creation of this object and query execution, but javadoc does not allow * {@code setCatalog} influence on already created statements. */ - private final String initialDatabase; + protected String currentDatabase; protected ClickHouseSqlStatement getLastStatement() { ClickHouseSqlStatement stmt = null; @@ -303,7 +304,7 @@ public ClickHouseStatementImpl(CloseableHttpClient client, ClickHouseConnection this.httpContext = ClickHouseHttpClientBuilder.createClientContext(properties); this.connection = connection; this.properties = properties == null ? new ClickHouseProperties() : properties; - this.initialDatabase = this.properties.getDatabase(); + this.currentDatabase = this.properties.getDatabase(); this.isResultSetScrollable = (resultSetType != ResultSet.TYPE_FORWARD_ONLY); this.batchStmts = new ArrayList<>(); @@ -709,7 +710,11 @@ private InputStream getInputStream( Map additionalRequestParams ) throws ClickHouseException { String sql = parsedStmt.getSQL(); - boolean ignoreDatabase = parsedStmt.isRecognized() && !parsedStmt.isDML(); + boolean ignoreDatabase = parsedStmt.isRecognized() && !parsedStmt.isDML() + && parsedStmt.containsKeyword("DATABASE"); + if (parsedStmt.getStatementType() == StatementType.USE) { + currentDatabase = parsedStmt.getDatabaseOrDefault(currentDatabase); + } log.debug("Executing SQL: {}", sql); @@ -866,7 +871,7 @@ private List getUrlQueryParams( Map params = properties.buildQueryParams(true); if (!ignoreDatabase) { - params.put(ClickHouseQueryParam.DATABASE, initialDatabase); + params.put(ClickHouseQueryParam.DATABASE, currentDatabase); } params.putAll(getAdditionalDBParams()); diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseConnectionImplTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseConnectionImplTest.java index 99a7340c8..94c360d4f 100644 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseConnectionImplTest.java +++ b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseConnectionImplTest.java @@ -13,8 +13,8 @@ import ru.yandex.clickhouse.except.ClickHouseException; import ru.yandex.clickhouse.settings.ClickHouseProperties; +import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; @@ -75,6 +75,54 @@ public void testOofWrongPassword() throws Exception { assertFailure(createDataSource("oof", "baz")); } + @Test + public void testDefaultDatabase() throws Exception { + ClickHouseDataSource ds = ClickHouseContainerForTest.newDataSource(); + String currentDbQuery = "select currentDatabase()"; + try (Connection conn = ds.getConnection(); Statement s = conn.createStatement()) { + try (ResultSet rs = s.executeQuery(currentDbQuery)) { + assertTrue(rs.next()); + assertEquals(rs.getString(1), "default"); + assertFalse(rs.next()); + } + s.execute("create database if not exists tdb1; create database if not exists tdb2"); + } + + ds = ClickHouseContainerForTest.newDataSource("tdb2"); + try (Connection conn = ds.getConnection(); Statement s = conn.createStatement()) { + try (ResultSet rs = s.executeQuery("select currentDatabase()")) { + assertTrue(rs.next()); + assertEquals(rs.getString(1), "tdb2"); + assertFalse(rs.next()); + } + + s.execute("create table tdb2_aaa(a String) engine=Memory; insert into tdb2_aaa values('3')"); + + try (ResultSet rs = s.executeQuery("select currentDatabase(), a from tdb2_aaa")) { + assertTrue(rs.next()); + assertEquals(rs.getString(1), "tdb2"); + assertEquals(rs.getString(2), "3"); + assertFalse(rs.next()); + } + + s.execute("use tdb1; create table tdb1_aaa(a String) engine=Memory; insert into tdb1_aaa values('1')"); + + try (ResultSet rs = s.executeQuery("select currentDatabase(), a from tdb1_aaa")) { + assertTrue(rs.next()); + assertEquals(rs.getString(1), "tdb1"); + assertEquals(rs.getString(2), "1"); + assertFalse(rs.next()); + } + + try (ResultSet rs = s.executeQuery("use `tdb2`; select currentDatabase(), a from tdb2_aaa")) { + assertTrue(rs.next()); + assertEquals(rs.getString(1), "tdb2"); + assertEquals(rs.getString(2), "3"); + assertFalse(rs.next()); + } + } + } + private static void assertSuccess(DataSource dataSource) throws Exception { Connection connection = dataSource.getConnection(); assertTrue(connection.createStatement().execute("SELECT 1")); From 8d0653426ba8fa999eb4a3b0fb586dab53a1e214 Mon Sep 17 00:00:00 2001 From: Zhichun Wu Date: Thu, 6 May 2021 10:12:39 +0800 Subject: [PATCH 2/9] Enhance unit test to cover prepared statement as well --- .../ClickHouseConnectionImplTest.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseConnectionImplTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseConnectionImplTest.java index 94c360d4f..d1aa4e3a7 100644 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseConnectionImplTest.java +++ b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseConnectionImplTest.java @@ -1,6 +1,7 @@ package ru.yandex.clickhouse.integration; import java.sql.Connection; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; @@ -85,12 +86,19 @@ public void testDefaultDatabase() throws Exception { assertEquals(rs.getString(1), "default"); assertFalse(rs.next()); } + + PreparedStatement p = conn.prepareStatement(currentDbQuery); + try (ResultSet rs = p.executeQuery()) { + assertTrue(rs.next()); + assertEquals(rs.getString(1), "default"); + assertFalse(rs.next()); + } s.execute("create database if not exists tdb1; create database if not exists tdb2"); } ds = ClickHouseContainerForTest.newDataSource("tdb2"); try (Connection conn = ds.getConnection(); Statement s = conn.createStatement()) { - try (ResultSet rs = s.executeQuery("select currentDatabase()")) { + try (ResultSet rs = s.executeQuery(currentDbQuery)) { assertTrue(rs.next()); assertEquals(rs.getString(1), "tdb2"); assertFalse(rs.next()); @@ -120,6 +128,14 @@ public void testDefaultDatabase() throws Exception { assertEquals(rs.getString(2), "3"); assertFalse(rs.next()); } + + String sql = "select currentDatabase(), a from tdb2_aaa"; + try (PreparedStatement p = conn.prepareStatement(sql); ResultSet rs = p.executeQuery()) { + assertTrue(rs.next()); + assertEquals(rs.getString(1), "tdb2"); + assertEquals(rs.getString(2), "3"); + assertFalse(rs.next()); + } } } From 298c2abdf0cf4d1fe7aee8bb56d3adedb91956be Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 10 May 2021 16:13:16 +0800 Subject: [PATCH 3/9] In the addBatch method, add parsedStmt.hasValues() check to ensure that the query of the form 'INSERT INTO ... SELECT' will be executed --- .../ru/yandex/clickhouse/ClickHousePreparedStatementImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHousePreparedStatementImpl.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHousePreparedStatementImpl.java index 4abb48f95..66b243740 100644 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHousePreparedStatementImpl.java +++ b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHousePreparedStatementImpl.java @@ -327,7 +327,7 @@ public void addBatch(String sql) throws SQLException { @Override public void addBatch() throws SQLException { - if (parsedStmt.getStatementType() == StatementType.INSERT) { + if (parsedStmt.getStatementType() == StatementType.INSERT && parsedStmt.hasValues()) { batchRows.addAll(buildBatch()); } else { batchStmts.add(buildSql()); From 5ca9485fe76bce8e5e8cb4effcaa74b4ffc5a089 Mon Sep 17 00:00:00 2001 From: Piotr Findeisen Date: Mon, 10 May 2021 16:26:42 +0200 Subject: [PATCH 4/9] Return correct value from getAutoCommit --- .../java/ru/yandex/clickhouse/ClickHouseConnectionImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnectionImpl.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnectionImpl.java index 6ec960ca4..0b498c6ac 100644 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnectionImpl.java +++ b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnectionImpl.java @@ -214,7 +214,7 @@ public void setAutoCommit(boolean autoCommit) throws SQLException { @Override public boolean getAutoCommit() throws SQLException { - return false; + return true; } @Override From 259682eaa8d5af741e4df57ca745f21ae3ae574c Mon Sep 17 00:00:00 2001 From: Piotr Findeisen Date: Mon, 10 May 2021 16:32:10 +0200 Subject: [PATCH 5/9] Return proper error when user tries to enable transactions Transactions are not supported, so `setAutoCommit(false)` should fail, as it does not provide the isolation or rollback-ability requested by the caller. `commit()` and `rollback()` should fail in auto-commit mode (this is what PostgreSQL JDBC driver does). --- .../ru/yandex/clickhouse/ClickHouseConnectionImpl.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnectionImpl.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnectionImpl.java index 0b498c6ac..87ec88fa7 100644 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnectionImpl.java +++ b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnectionImpl.java @@ -209,7 +209,10 @@ public String nativeSQL(String sql) throws SQLException { @Override public void setAutoCommit(boolean autoCommit) throws SQLException { - + if (autoCommit) { + return; + } + throw new SQLFeatureNotSupportedException("Transactions are not supported"); } @Override @@ -219,12 +222,12 @@ public boolean getAutoCommit() throws SQLException { @Override public void commit() throws SQLException { - + throw new SQLException("Cannot commit when auto-commit is enabled"); } @Override public void rollback() throws SQLException { - + throw new SQLException("Cannot commit when auto-commit is enabled"); } @Override From d8139941e458ff4de8fcf3509b1b07e8795bac6f Mon Sep 17 00:00:00 2001 From: Piotr Findeisen Date: Tue, 11 May 2021 09:20:00 +0200 Subject: [PATCH 6/9] fixup! Return proper error when user tries to enable transactions --- .../java/ru/yandex/clickhouse/ClickHouseConnectionImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnectionImpl.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnectionImpl.java index 87ec88fa7..1ba8d191e 100644 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnectionImpl.java +++ b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/ClickHouseConnectionImpl.java @@ -227,7 +227,7 @@ public void commit() throws SQLException { @Override public void rollback() throws SQLException { - throw new SQLException("Cannot commit when auto-commit is enabled"); + throw new SQLException("Cannot rollback when auto-commit is enabled"); } @Override From d0af95bda3b3323dee73b0ee42f4b93328ff2d66 Mon Sep 17 00:00:00 2001 From: Zhichun Wu Date: Mon, 7 Jun 2021 08:01:41 +0800 Subject: [PATCH 7/9] Fix table format issue --- clickhouse-jdbc/docs/datetime.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clickhouse-jdbc/docs/datetime.md b/clickhouse-jdbc/docs/datetime.md index cbb058c4e..7c99b2099 100644 --- a/clickhouse-jdbc/docs/datetime.md +++ b/clickhouse-jdbc/docs/datetime.md @@ -51,7 +51,7 @@ The methods which take a [Calendar]((https://docs.oracle.com/javase/8/docs/api/j For Date and DateTime fields, the JDBC driver has enough time zone related information available, so these methods would only be relevant for String or other typed fields. There might be valid use cases, but for now we think that adding such an option would make things even more complicated. Requested Type | Number | Date | DateTime | Other ----------------| ---------------------------------- +---------------| -------|------|----------|-------- [Date](https://docs.oracle.com/javase/8/docs/api/java/sql/Date.html) | Seconds or milliseconds past epoch truncated to day in relevant time zone | Date in relevant time zone, midnight | Date time in relevant time zone, rewind to midnight | Try number, date time (with or without offset) truncated to day, date [Time](https://docs.oracle.com/javase/8/docs/api/java/sql/Time.html) | Local time at 1970-01-01 (e.g. “1337” is “13:37:00” at TZ) | Midnight on 1970-01-01 in relevant time zone | Local time in relevant time zone | Local time in relevant time zone via ISO format or via number, at 1970-01-01 [Timestamp](https://docs.oracle.com/javase/8/docs/api/java/sql/Timestamp.html) | Seconds or milliseconds past epoch | Local date at midnight in relevant time zone | Local date and time in relevant time zone | Number, date time with or without offset From 4e67c9c62460adf88b1d4a2c98d2a7a0a6cbf861 Mon Sep 17 00:00:00 2001 From: Zhichun Wu Date: Mon, 7 Jun 2021 08:02:57 +0800 Subject: [PATCH 8/9] Fix the issue of handling negative big decimals --- .../util/ClickHouseRowBinaryStream.java | 26 ++++++------ .../integration/RowBinaryStreamTest.java | 42 ++++++++++++++++++- .../util/ClickHouseRowBinaryStreamTest.java | 25 ++++++++++- 3 files changed, 79 insertions(+), 14 deletions(-) diff --git a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryStream.java b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryStream.java index 3c0887533..626d84900 100644 --- a/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryStream.java +++ b/clickhouse-jdbc/src/main/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryStream.java @@ -188,22 +188,24 @@ public void writeFloat64(double value) throws IOException { Utils.writeLong(out, Double.doubleToLongBits(value)); } - public void writeDecimal128(BigDecimal num, int scale) throws IOException { - BigInteger bi = Utils.toBigInteger(num, scale); - byte[] r = bi.toByteArray(); - for (int i = r.length; i > 0; i--) { - out.write(r[i - 1]); + public void writeBigInteger(BigInteger value, int byteLength) throws IOException { + byte empty = value.signum() == -1 ? (byte) 0xFF : 0x00; + byte[] bytes = value.toByteArray(); + for (int i = bytes.length - 1; i >= 0; i--) { + out.write(bytes[i]); + } + + for (int i = byteLength - bytes.length; i > 0; i--) { + out.write(empty); } - out.write(new byte[16 - r.length]); + } + + public void writeDecimal128(BigDecimal num, int scale) throws IOException { + writeBigInteger(Utils.toBigInteger(num, scale), 16); } public void writeDecimal256(BigDecimal num, int scale) throws IOException { - BigInteger bi = Utils.toBigInteger(num, scale); - byte[] r = bi.toByteArray(); - for (int i = r.length; i > 0; i--) { - out.write(r[i - 1]); - } - out.write(new byte[32 - r.length]); + writeBigInteger(Utils.toBigInteger(num, scale), 32); } public void writeDecimal64(BigDecimal num, int scale) throws IOException { diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/RowBinaryStreamTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/RowBinaryStreamTest.java index 443a456e5..b6a672f89 100644 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/RowBinaryStreamTest.java +++ b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/RowBinaryStreamTest.java @@ -2,11 +2,11 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertThrows; import static org.testng.Assert.assertTrue; import java.io.EOFException; import java.io.IOException; +import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Date; import java.sql.ResultSet; @@ -276,6 +276,46 @@ public void testBitmap() throws Exception { } } + @Test + public void testBigDecimals() throws Exception { + try (ClickHouseStatement statement = connection.createStatement()) { + statement.execute("set allow_experimental_bigint_types=1;" + + "create table if not exists test.test_big_decimals(d128 Decimal128(6), d256 Decimal256(12)) engine=Memory"); + } catch (SQLException e) { + return; + } + + try (ClickHouseStatement statement = connection.createStatement()) { + BigDecimal[] values = new BigDecimal[] { + BigDecimal.valueOf(-123.123456789D), + BigDecimal.ZERO, + BigDecimal.valueOf(123.123456789D) + }; + statement.sendRowBinaryStream("insert into table test.test_big_decimals", new ClickHouseStreamCallback() { + @Override + public void writeTo(ClickHouseRowBinaryStream stream) throws IOException { + for (int i = 0; i < values.length; i++) { + stream.writeDecimal128(values[i], 6); + stream.writeDecimal256(values[i], 12); + } + } + }); + + try (ResultSet rs = statement.executeQuery("select * from test.test_big_decimals order by d128")) { + int rowCounter = 0; + while (rs.next()) { + rowCounter++; + assertEquals(rs.getBigDecimal(1, 6), values[rowCounter - 1].setScale(6, BigDecimal.ROUND_DOWN)); + assertEquals(rs.getBigDecimal(2, 12), values[rowCounter - 1].setScale(12, BigDecimal.ROUND_DOWN)); + } + + assertEquals(rowCounter, values.length); + } + + statement.execute("drop table if exists test.test_big_decimals"); + } + } + private void testRowBinaryStream(boolean rowBinaryResult) throws Exception { createTable("test.raw_binary"); ClickHouseStatement statement = connection.createStatement(); diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryStreamTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryStreamTest.java index b55f9a590..b7469055d 100644 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryStreamTest.java +++ b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/util/ClickHouseRowBinaryStreamTest.java @@ -112,9 +112,32 @@ public void testDecimal128() throws Exception { @Override public void write(ClickHouseRowBinaryStream stream) throws Exception { stream.writeDecimal128(new BigDecimal(10.23), 3); + stream.writeDecimal128(new BigDecimal(-10.23), 3); } }, - new byte[]{-10, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + new byte[] { + -10, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, -40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + } + ); + } + + @Test + public void testDecimal256() throws Exception { + check( + new StreamWriter() { + @Override + public void write(ClickHouseRowBinaryStream stream) throws Exception { + stream.writeDecimal256(new BigDecimal(10.23), 3); + stream.writeDecimal256(new BigDecimal(-10.23), 3); + } + }, + new byte[] { + -10, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, -40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + } ); } From 7e3ccd072bc652128981840dbe14da38dcfc1194 Mon Sep 17 00:00:00 2001 From: Zhichun Wu Date: Mon, 7 Jun 2021 11:02:10 +0800 Subject: [PATCH 9/9] Fix build failure caused by new version of ClickHouse --- .../ClickHouseDatabaseMetadataTest.java | 11 ++++- .../integration/ClickHouseMapTest.java | 43 ++++++++++++------- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseDatabaseMetadataTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseDatabaseMetadataTest.java index cb55e943d..9b005be9e 100644 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseDatabaseMetadataTest.java +++ b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseDatabaseMetadataTest.java @@ -19,6 +19,7 @@ import ru.yandex.clickhouse.ClickHouseContainerForTest; import ru.yandex.clickhouse.ClickHouseDataSource; import ru.yandex.clickhouse.ClickHouseDatabaseMetadata; +import ru.yandex.clickhouse.util.ClickHouseVersionNumberUtil; public class ClickHouseDatabaseMetadataTest { @@ -159,7 +160,15 @@ public void testToDateTimeTZ() throws Exception { ResultSetMetaData meta = rs.getMetaData(); Assert.assertEquals(meta.getColumnClassName(1), Timestamp.class.getCanonicalName()); TimeZone timezone = ((ClickHouseConnection) connection).getTimeZone(); - Assert.assertEquals(meta.getColumnTypeName(1), "DateTime('" + timezone.getID() + "')"); + String version = ((ClickHouseConnection) connection).getServerVersion(); + int majorVersion = ClickHouseVersionNumberUtil.getMajorVersion(version); + int minorVersion = ClickHouseVersionNumberUtil.getMinorVersion(version); + if (majorVersion > 21 || (majorVersion == 21 && minorVersion >= 6)) { + Assert.assertEquals(meta.getColumnTypeName(1), "DateTime"); + } else { + Assert.assertEquals(meta.getColumnTypeName(1), "DateTime('" + timezone.getID() + "')"); + } + Assert.assertEquals(meta.getColumnType(1), Types.TIMESTAMP); } diff --git a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseMapTest.java b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseMapTest.java index fe19bd933..c056710a4 100644 --- a/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseMapTest.java +++ b/clickhouse-jdbc/src/test/java/ru/yandex/clickhouse/integration/ClickHouseMapTest.java @@ -111,44 +111,55 @@ public void testMaps() throws Exception { return; } - // skip 21.4 - String serverVersion = conn.getServerVersion(); - if (ClickHouseVersionNumberUtil.getMajorVersion(serverVersion) == 21 - && ClickHouseVersionNumberUtil.getMinorVersion(serverVersion) == 4) { + String columns = ", ma Map(Integer, Array(String)), mi Map(Integer, Integer)"; + String values = ",1:['11','12'],2:['22','23']},{1:11,2:22}"; + String version = ((ClickHouseConnection) conn).getServerVersion(); + int majorVersion = ClickHouseVersionNumberUtil.getMajorVersion(version); + int minorVersion = ClickHouseVersionNumberUtil.getMinorVersion(version); + if (majorVersion > 21 || (majorVersion == 21 && minorVersion >= 3)) { + // https://github.com/ClickHouse/ClickHouse/issues/25026 + columns = ""; + values = ""; + return; } try (Statement s = conn.createStatement()) { s.execute("DROP TABLE IF EXISTS test_maps"); - s.execute( - "CREATE TABLE IF NOT EXISTS test_maps(ma Map(Integer, Array(String)), mi Map(Integer, Integer), ms Map(String, String)) ENGINE = Memory"); - s.execute("insert into test_maps values ({1:['11','12'],2:['22','23']},{1:11,2:22},{'k1':'v1','k2':'v2'})"); + s.execute("CREATE TABLE IF NOT EXISTS test_maps(ms Map(String, String)" + columns + ") ENGINE = Memory"); + s.execute("insert into test_maps values ({{'k1':'v1','k2':'v2'}" + values + ")"); try (ResultSet rs = s.executeQuery("select * from test_maps")) { assertTrue(rs.next()); - assertMap(rs.getObject("ma"), - Utils.mapOf(1, new String[] { "11", "12" }, 2, new String[] { "22", "23" })); - assertMap(rs.getObject("mi"), Utils.mapOf(1, 11, 2, 22)); assertMap(rs.getObject("ms"), Utils.mapOf("k1", "v1", "k2", "v2")); + if (!columns.isEmpty()) { + assertMap(rs.getObject("ma"), + Utils.mapOf(1, new String[] { "11", "12" }, 2, new String[] { "22", "23" })); + assertMap(rs.getObject("mi"), Utils.mapOf(1, 11, 2, 22)); + } } s.execute("truncate table test_maps"); } try (PreparedStatement s = conn.prepareStatement("insert into test_maps values(?,?,?)")) { - s.setObject(1, Utils.mapOf(1, new String[] { "11", "12" }, 2, new String[] { "22", "23" })); - s.setObject(2, Utils.mapOf(1, 11, 2, 22)); - s.setObject(3, Utils.mapOf("k1", "v1", "k2", "v2")); + s.setObject(1, Utils.mapOf("k1", "v1", "k2", "v2")); + if (!columns.isEmpty()) { + s.setObject(2, Utils.mapOf(1, new String[] { "11", "12" }, 2, new String[] { "22", "23" })); + s.setObject(3, Utils.mapOf(1, 11, 2, 22)); + } s.execute(); } try (Statement s = conn.createStatement()) { try (ResultSet rs = s.executeQuery("select * from test_maps")) { assertTrue(rs.next()); - assertMap(rs.getObject("ma"), - Utils.mapOf(1, new String[] { "11", "12" }, 2, new String[] { "22", "23" })); - assertMap(rs.getObject("mi"), Utils.mapOf(1, 11, 2, 22)); assertMap(rs.getObject("ms"), Utils.mapOf("k1", "v1", "k2", "v2")); + if (!columns.isEmpty()) { + assertMap(rs.getObject("ma"), + Utils.mapOf(1, new String[] { "11", "12" }, 2, new String[] { "22", "23" })); + assertMap(rs.getObject("mi"), Utils.mapOf(1, 11, 2, 22)); + } } } }