From 0a0628520e67ec40640d20b27c5f72f94ff1dc20 Mon Sep 17 00:00:00 2001 From: Oleg Zinoviev Date: Sat, 12 Apr 2025 14:58:50 +0300 Subject: [PATCH 1/2] improvements: - PreparedStatementImpl: getMetaData returns result set metadata using describe query - StatementImpl: maxRows handling - Driver: unload method fixed (DriverManager search driver for unregister by reference equality) - HttpAPIClientHelper: added sslmode option (presents in v1), support to skip ssl validation fixes: - PreparedStatementImpl: ignores question mark (?) in comments, string literals and quoted identifiers - StatementImpl: multiline block comments trim - HttpAPIClientHelper: null pointer exception with unpooled connection (poolControl is null) --- .../client/api/ClientConfigProperties.java | 2 + .../api/internal/HttpAPIClientHelper.java | 33 +++++- .../com/clickhouse/client/ClientTests.java | 14 +++ .../main/java/com/clickhouse/jdbc/Driver.java | 8 +- .../jdbc/PreparedStatementImpl.java | 109 +++++++++++++++--- .../com/clickhouse/jdbc/StatementImpl.java | 12 +- .../jdbc/metadata/ResultSetMetaData.java | 16 ++- .../jdbc/PreparedStatementTest.java | 55 +++++++++ .../com/clickhouse/jdbc/StatementTest.java | 19 +++ 9 files changed, 247 insertions(+), 21 deletions(-) diff --git a/client-v2/src/main/java/com/clickhouse/client/api/ClientConfigProperties.java b/client-v2/src/main/java/com/clickhouse/client/api/ClientConfigProperties.java index c2137b736..8a733b187 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/ClientConfigProperties.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/ClientConfigProperties.java @@ -92,6 +92,8 @@ public enum ClientConfigProperties { SSL_KEY_STORE_PASSWORD("key_store_password"), + SSL_MODE("sslmode", "strict", Arrays.asList("strict", "none")), + SSL_KEY("ssl_key"), CA_CERTIFICATE("sslrootcert"), diff --git a/client-v2/src/main/java/com/clickhouse/client/api/internal/HttpAPIClientHelper.java b/client-v2/src/main/java/com/clickhouse/client/api/internal/HttpAPIClientHelper.java index 0ec6144db..a84fba16f 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/internal/HttpAPIClientHelper.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/internal/HttpAPIClientHelper.java @@ -58,8 +58,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -74,7 +77,10 @@ import java.net.URL; import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; +import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; import java.util.Base64; import java.util.Collection; import java.util.Collections; @@ -169,6 +175,13 @@ public SSLContext createSSLContext() { } catch (SSLException e) { throw new ClientMisconfigurationException("Failed to create SSL context from certificates", e); } + } else if ("none".equals(chConfiguration.get(ClientConfigProperties.SSL_MODE.getKey()))) { + try { + sslContext = SSLContext.getInstance("TLS"); + sslContext.init(new KeyManager[0], new TrustManager[]{new TrustAllManager()}, new SecureRandom()); + } catch (NoSuchAlgorithmException | KeyManagementException e) { + throw new ClientException("Failed to create none validating SSL context", e); + } } return sslContext; } @@ -380,7 +393,7 @@ public Exception readError(ClassicHttpResponse httpResponse) { public ClassicHttpResponse executeRequest(ClickHouseNode server, Map requestConfig, LZ4Factory lz4Factory, IOCallback writeCallback) throws IOException { - if (timeToPoolVent.get() < System.currentTimeMillis()) { + if (poolControl != null && timeToPoolVent.get() < System.currentTimeMillis()) { timeToPoolVent.set(System.currentTimeMillis() + POOL_VENT_TIMEOUT); poolControl.closeExpired(); } @@ -828,4 +841,22 @@ public long getTime() { return count > 0 ? runningAverage / count : 0; } } + + private static final class TrustAllManager implements X509TrustManager { + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) { + // ignore + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) { + // ignore + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + } } diff --git a/client-v2/src/test/java/com/clickhouse/client/ClientTests.java b/client-v2/src/test/java/com/clickhouse/client/ClientTests.java index 4be112ba9..90830ed62 100644 --- a/client-v2/src/test/java/com/clickhouse/client/ClientTests.java +++ b/client-v2/src/test/java/com/clickhouse/client/ClientTests.java @@ -1,6 +1,7 @@ package com.clickhouse.client; import com.clickhouse.client.api.Client; +import com.clickhouse.client.api.ClientConfigProperties; import com.clickhouse.client.api.ClientException; import com.clickhouse.client.api.enums.Protocol; import com.clickhouse.client.api.query.GenericRecord; @@ -64,6 +65,12 @@ private static Client[] secureClientProvider() throws Exception { .setPassword("") .setRootCertificate("containers/clickhouse-server/certs/localhost.crt") .build(), + new Client.Builder() + .addEndpoint("https://" + node.getHost() + ":" + node.getPort()) + .setUsername("default") + .setPassword("") + .setOption(ClientConfigProperties.SSL_MODE.getKey(), "none") + .build(), new Client.Builder() .addEndpoint(Protocol.HTTP, node.getHost(), node.getPort(), true) .setUsername("default") @@ -108,6 +115,13 @@ public void testPing() { } } + @Test + public void testPingUnpooled() { + try (Client client = newClient().enableConnectionPool(false).build()) { + Assert.assertTrue(client.ping()); + } + } + @Test public void testPingFailure() { try (Client client = new Client.Builder() diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/Driver.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/Driver.java index 6ba7319ef..566653959 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/Driver.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/Driver.java @@ -98,7 +98,7 @@ public Driver(DataSourceImpl dataSourceImpl) { public static void load() { try { - DriverManager.registerDriver(new Driver()); + DriverManager.registerDriver(DriverHolder.INSTANCE); } catch (SQLException e) { log.error("Failed to register ClickHouse JDBC driver", e); } @@ -106,7 +106,7 @@ public static void load() { public static void unload() { try { - DriverManager.deregisterDriver(new Driver()); + DriverManager.deregisterDriver(DriverHolder.INSTANCE); } catch (SQLException e) { log.error("Failed to deregister ClickHouse JDBC driver", e); } @@ -163,4 +163,8 @@ public static String chSettingKey(String key) { public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException("Method not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); } + + private static final class DriverHolder { + private static final Driver INSTANCE = new Driver(); + } } diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java index 2af908edf..8a2fcb617 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java @@ -1,5 +1,7 @@ package com.clickhouse.jdbc; +import com.clickhouse.client.api.metadata.TableSchema; +import com.clickhouse.data.ClickHouseColumn; import com.clickhouse.data.Tuple; import com.clickhouse.jdbc.internal.ExceptionUtils; import org.slf4j.Logger; @@ -26,6 +28,7 @@ import java.sql.SQLFeatureNotSupportedException; import java.sql.SQLType; import java.sql.SQLXML; +import java.sql.Statement; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; @@ -42,7 +45,6 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; -import java.util.GregorianCalendar; import java.util.List; import java.util.Map; @@ -64,11 +66,12 @@ public class PreparedStatementImpl extends StatementImpl implements PreparedStat String insertIntoSQL; StatementType statementType; + public PreparedStatementImpl(ConnectionImpl connection, String sql) throws SQLException { super(connection); this.originalSql = sql.trim(); //Split the sql string into an array of strings around question mark tokens - this.sqlSegments = originalSql.split("\\?"); + this.sqlSegments = splitStatement(originalSql); this.statementType = parseStatementType(originalSql); if (statementType == StatementType.INSERT) { @@ -77,17 +80,11 @@ public PreparedStatementImpl(ConnectionImpl connection, String sql) throws SQLEx } //Create an array of objects to store the parameters - if (originalSql.contains("?")) { - int count = originalSql.length() - originalSql.replace("?", "").length(); - this.parameters = new Object[count]; - } else { - this.parameters = new Object[0]; - } - + this.parameters = new Object[sqlSegments.length - 1]; this.defaultCalendar = connection.defaultCalendar; } - private String compileSql(String []segments) { + private String compileSql(String [] segments) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < segments.length; i++) { sb.append(segments[i]); @@ -98,6 +95,7 @@ private String compileSql(String []segments) { LOG.trace("Compiled SQL: {}", sb); return sb.toString(); } + @Override public ResultSet executeQuery() throws SQLException { checkClosed(); @@ -305,7 +303,26 @@ public void setArray(int parameterIndex, Array x) throws SQLException { @Override public ResultSetMetaData getMetaData() throws SQLException { checkClosed(); - return null; + if (this.currentResultSet != null) { + return currentResultSet.getMetaData(); + } else if (statementType != StatementType.SELECT) { + return null; + } + + String sql = compileSql(sqlSegments); + String describe = String.format("describe (\n%s\n)", sql); + + List columns = new ArrayList<>(); + try (Statement stmt = connection.createStatement()) { + try (ResultSet rs = stmt.executeQuery(describe)) { + while (rs.next()) { + ClickHouseColumn column = ClickHouseColumn.of(rs.getString(1), rs.getString(2)); + columns.add(column); + } + } + } + TableSchema schema = new TableSchema(columns); + return new com.clickhouse.jdbc.metadata.ResultSetMetaData(schema); } @Override @@ -517,14 +534,14 @@ private static String encodeObject(Object x) throws SQLException { } else if (x instanceof ZonedDateTime) { return encodeObject(((ZonedDateTime) x).toInstant()); } else if (x instanceof Instant) { - return "fromUnixTimestamp64Nano(" + (((Instant) x).getEpochSecond() * 1_000_000_000L + ((Instant) x).getNano())+ ")"; + return "fromUnixTimestamp64Nano(" + (((Instant) x).getEpochSecond() * 1_000_000_000L + ((Instant) x).getNano()) + ")"; } else if (x instanceof InetAddress) { return "'" + ((InetAddress) x).getHostAddress() + "'"; } else if (x instanceof Array) { StringBuilder listString = new StringBuilder(); listString.append("["); int i = 0; - for (Object item : (Object[])((Array) x).getArray()) { + for (Object item : (Object[]) ((Array) x).getArray()) { if (i > 0) { listString.append(", "); } @@ -616,4 +633,70 @@ private static String encodeObject(Object x) throws SQLException { private static String escapeString(String x) { return x.replace("\\", "\\\\").replace("'", "\\'");//Escape single quotes } + + private static String [] splitStatement(String sql) { + List segments = new ArrayList<>(); + char[] chars = sql.toCharArray(); + int segmentStart = 0; + for (int i = 0; i < chars.length; i++) { + char c = chars[i]; + if (c == '\'' || c == '"' || c == '`') { + // string literal or identifier + i = skip(chars, i + 1, c, true); + } else if (c == '/' && lookahead(chars, i) == '*') { + // block comment + int end = sql.indexOf("*/", i); + if (end == -1) { + // missing comment end + break; + } + i = end + 1; + } else if (c == '#' || (c == '-' && lookahead(chars, i) == '-')) { + // line comment + i = skip(chars, i + 1, '\n', false); + } else if (c == '?') { + // question mark + segments.add(sql.substring(segmentStart, i)); + segmentStart = i + 1; + } + } + if (segmentStart < chars.length) { + segments.add(sql.substring(segmentStart)); + } else { + // add empty segment in case question mark was last char of sql + segments.add(""); + } + return segments.toArray(new String[0]); + } + + private static int skip(char[] chars, int from, char until, boolean escape) { + for (int i = from; i < chars.length; i++) { + char curr = chars[i]; + if (escape) { + char next = lookahead(chars, i); + if ((curr == '\\' && (next == '\\' || next == until)) || (curr == until && next == until)) { + // should skip: + // 1) double \\ (backslash escaped with backslash) + // 2) \[until] ([until] char, escaped with backslash) + // 3) [until][until] ([until] char, escaped with [until]) + i++; + continue; + } + } + + if (curr == until) { + return i; + } + } + return chars.length; + } + + private static char lookahead(char[] chars, int pos) { + pos = pos + 1; + if (pos >= chars.length) { + return '\0'; + } + return chars[pos]; + } + } diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/StatementImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/StatementImpl.java index d6b04effc..a3a8f08ab 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/StatementImpl.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/StatementImpl.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.UUID; import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; public class StatementImpl implements Statement, JdbcV2Wrapper { private static final Logger LOG = LoggerFactory.getLogger(StatementImpl.class); @@ -31,7 +32,7 @@ public class StatementImpl implements Statement, JdbcV2Wrapper { ConnectionImpl connection; private int queryTimeout; protected boolean closed; - private ResultSetImpl currentResultSet; + protected ResultSetImpl currentResultSet; private OperationMetrics metrics; protected List batch; private String lastSql; @@ -70,7 +71,7 @@ protected static StatementType parseStatementType(String sql) { return StatementType.OTHER; } - trimmedSql = trimmedSql.replaceAll("/\\*.*?\\*/", "").trim(); // remove comments + trimmedSql = BLOCK_COMMENT.matcher(trimmedSql).replaceAll("").trim(); // remove comments String[] lines = trimmedSql.split("\n"); for (String line : lines) { String trimmedLine = line.trim(); @@ -172,7 +173,10 @@ public ResultSetImpl executeQuery(String sql, QuerySettings settings) throws SQL closePreviousResultSet(); QuerySettings mergedSettings = QuerySettings.merge(connection.getDefaultQuerySettings(), settings); - + if (maxRows > 0) { + mergedSettings.setOption(ClientConfigProperties.serverSetting(ServerSettings.MAX_RESULT_ROWS), maxRows); + mergedSettings.setOption(ClientConfigProperties.serverSetting(ServerSettings.RESULT_OVERFLOW_MODE), "break"); + } if (mergedSettings.getQueryId() != null) { lastQueryId = mergedSettings.getQueryId(); @@ -627,4 +631,6 @@ public String enquoteNCharLiteral(String val) throws SQLException { public String getLastQueryId() { return lastQueryId; } + + private static final Pattern BLOCK_COMMENT = Pattern.compile("/\\*.*?\\*/", Pattern.DOTALL); } diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ResultSetMetaData.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ResultSetMetaData.java index ab759c685..8810fd835 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ResultSetMetaData.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ResultSetMetaData.java @@ -1,6 +1,7 @@ package com.clickhouse.jdbc.metadata; import java.sql.SQLException; +import java.util.Objects; import com.clickhouse.client.api.metadata.TableSchema; import com.clickhouse.data.ClickHouseColumn; @@ -11,21 +12,32 @@ public class ResultSetMetaData implements java.sql.ResultSetMetaData, JdbcV2Wrapper { private final ResultSetImpl resultSet; + private final TableSchema schema; + public ResultSetMetaData(ResultSetImpl resultSet) { this.resultSet = resultSet; + this.schema = null; // result set schema is lazy + } + + public ResultSetMetaData(TableSchema schema) { + this.resultSet = null; + this.schema = schema; } private ClickHouseColumn getColumn(int column) throws SQLException { if (column < 1 || column > getColumnCount()) { throw new SQLException("Column index out of range: " + column, ExceptionUtils.SQL_STATE_CLIENT_ERROR); } - return resultSet.getSchema().getColumns().get(column - 1); + TableSchema schema = resultSet != null ? resultSet.getSchema() : this.schema; + assert schema != null : "Schema is null"; + return schema.getColumns().get(column - 1); } @Override public int getColumnCount() throws SQLException { try { - TableSchema schema = resultSet.getSchema(); + TableSchema schema = resultSet != null ? resultSet.getSchema() : this.schema; + assert schema != null : "Schema is null"; return schema.getColumns().size(); } catch (Exception e) { throw ExceptionUtils.toSqlState(e); 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 141244045..3959c494a 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java @@ -6,8 +6,10 @@ import java.sql.Array; import java.sql.Connection; +import java.sql.JDBCType; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.sql.ResultSetMetaData; import java.sql.Statement; import java.sql.Types; import java.util.Arrays; @@ -449,4 +451,57 @@ void testMetabaseBug01() throws Exception { } } } + + @Test(groups = { "integration" }) + void testStatementSplit() throws Exception { + try (Connection conn = getJdbcConnection()) { + try (Statement stmt = conn.createStatement()) { + stmt.execute("CREATE TABLE `with_complex_id` (`v?``1` Int32, \"v?\"\"2\" Int32,`v?\\`3` Int32, \"v?\\\"4\" Int32) ENGINE Memory;"); + } + String insertQuery = "-- line comment1 ?\n" + + "# line comment2 ?\n" + + "#! line comment3 ?\n" + + "/* block comment ? \n */" + + "INSERT INTO `with_complex_id`(`v?``1`, \"v?\"\"2\",`v?\\`3`, \"v?\\\"4\") VALUES (?, ?, ?, ?);"; + try (PreparedStatement stmt = conn.prepareStatement(insertQuery)) { + stmt.setInt(1, 1); + stmt.setInt(2, 2); + stmt.setInt(3, 3); + stmt.setInt(4, 4); + stmt.execute(); + } + String selectQuery = "-- line comment ?\n" + + "/* block comment ? \n */" + + "SELECT `v?``1`, \"v?\"\"2\",`v?\\`3`, \"v?\\\"4\", 'test '' string1 ?', 'test \\' string2 ?', 'test string3 ?\\\\' FROM `with_complex_id` WHERE `v?``1` = ? AND \"v?\"\"2\" = ? AND `v?\\`3` = ? AND \"v?\\\"4\" = ?"; + try (PreparedStatement stmt = conn.prepareStatement(selectQuery)) { + stmt.setInt(1, 1); + stmt.setInt(2, 2); + stmt.setInt(3, 3); + stmt.setInt(4, 4); + try (ResultSet rs = stmt.executeQuery()) { + assertTrue(rs.next()); + assertEquals(rs.getInt(1), 1); + assertEquals(rs.getInt(2), 2); + assertEquals(rs.getInt(3), 3); + assertEquals(rs.getInt(4), 4); + assertEquals(rs.getString(5), "test ' string1 ?"); + assertEquals(rs.getString(6), "test ' string2 ?"); + assertEquals(rs.getString(7), "test string3 ?\\"); + } + } + } + } + + @Test(groups = { "integration" }) + void testPreparedStatementMd() throws Exception { + try (Connection conn = getJdbcConnection()) { + try (PreparedStatement stmt = conn.prepareStatement("select 1::Int32 as value")) { + ResultSetMetaData md = stmt.getMetaData(); + assertNotNull(md); + assertEquals(md.getColumnCount(), 1); + assertEquals(md.getColumnName(1), "value"); + assertEquals(md.getColumnType(1), Types.INTEGER); + } + } + } } diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java index 741946fd3..8b5cca1f9 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java @@ -711,4 +711,23 @@ public void testWasNullFlagArray() throws Exception { } } + @Test(groups = { "integration" }) + public void testExecuteWithMaxRows() throws Exception { + try (Connection conn = getJdbcConnection()) { + try (Statement stmt = conn.createStatement()) { + stmt.setMaxRows(1); + int count = 0; + try (ResultSet rs = stmt.executeQuery("SELECT * FROM generate_series(0, 100000)")) { + while (rs.next()) { + count++; + } + } + // MaxRows limits the number of row with rounding to the size of the block + // https://clickhouse.com/docs/en/operations/settings/query-complexity#setting-max_result_rows + // https://clickhouse.com/docs/en/operations/settings/query-complexity#result-overflow-mode + assertTrue(count > 0 && count < 100000); + } + } + } + } From 2e57790e66dd95aae09c6cf7124068298445b09d Mon Sep 17 00:00:00 2001 From: Oleg Zinoviev Date: Tue, 15 Apr 2025 20:36:32 +0300 Subject: [PATCH 2/2] removed: - PreparedStatementImpl:getMetadata - sslmode --- .../client/api/ClientConfigProperties.java | 2 -- .../api/internal/HttpAPIClientHelper.java | 7 ------- .../com/clickhouse/client/ClientTests.java | 6 ------ .../main/java/com/clickhouse/jdbc/Driver.java | 17 +++++++-------- .../jdbc/PreparedStatementImpl.java | 21 +------------------ .../jdbc/metadata/ResultSetMetaData.java | 16 ++------------ .../jdbc/PreparedStatementTest.java | 13 ------------ 7 files changed, 11 insertions(+), 71 deletions(-) diff --git a/client-v2/src/main/java/com/clickhouse/client/api/ClientConfigProperties.java b/client-v2/src/main/java/com/clickhouse/client/api/ClientConfigProperties.java index 8a733b187..c2137b736 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/ClientConfigProperties.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/ClientConfigProperties.java @@ -92,8 +92,6 @@ public enum ClientConfigProperties { SSL_KEY_STORE_PASSWORD("key_store_password"), - SSL_MODE("sslmode", "strict", Arrays.asList("strict", "none")), - SSL_KEY("ssl_key"), CA_CERTIFICATE("sslrootcert"), diff --git a/client-v2/src/main/java/com/clickhouse/client/api/internal/HttpAPIClientHelper.java b/client-v2/src/main/java/com/clickhouse/client/api/internal/HttpAPIClientHelper.java index a84fba16f..939f7ad0e 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/internal/HttpAPIClientHelper.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/internal/HttpAPIClientHelper.java @@ -175,13 +175,6 @@ public SSLContext createSSLContext() { } catch (SSLException e) { throw new ClientMisconfigurationException("Failed to create SSL context from certificates", e); } - } else if ("none".equals(chConfiguration.get(ClientConfigProperties.SSL_MODE.getKey()))) { - try { - sslContext = SSLContext.getInstance("TLS"); - sslContext.init(new KeyManager[0], new TrustManager[]{new TrustAllManager()}, new SecureRandom()); - } catch (NoSuchAlgorithmException | KeyManagementException e) { - throw new ClientException("Failed to create none validating SSL context", e); - } } return sslContext; } diff --git a/client-v2/src/test/java/com/clickhouse/client/ClientTests.java b/client-v2/src/test/java/com/clickhouse/client/ClientTests.java index 90830ed62..9f0aa0510 100644 --- a/client-v2/src/test/java/com/clickhouse/client/ClientTests.java +++ b/client-v2/src/test/java/com/clickhouse/client/ClientTests.java @@ -65,12 +65,6 @@ private static Client[] secureClientProvider() throws Exception { .setPassword("") .setRootCertificate("containers/clickhouse-server/certs/localhost.crt") .build(), - new Client.Builder() - .addEndpoint("https://" + node.getHost() + ":" + node.getPort()) - .setUsername("default") - .setPassword("") - .setOption(ClientConfigProperties.SSL_MODE.getKey(), "none") - .build(), new Client.Builder() .addEndpoint(Protocol.HTTP, node.getHost(), node.getPort(), true) .setUsername("default") diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/Driver.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/Driver.java index 566653959..c863799fd 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/Driver.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/Driver.java @@ -3,12 +3,11 @@ import com.clickhouse.client.api.ClientConfigProperties; import com.clickhouse.client.config.ClickHouseClientOption; -import com.clickhouse.jdbc.internal.JdbcConfiguration; import com.clickhouse.jdbc.internal.ExceptionUtils; +import com.clickhouse.jdbc.internal.JdbcConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.DriverPropertyInfo; @@ -33,11 +32,14 @@ public class Driver implements java.sql.Driver { private final DataSourceImpl dataSource; public static String frameworksDetected = null; + public static class FrameworksDetection { private static final List FRAMEWORKS_TO_DETECT = Arrays.asList("apache.spark"); static volatile String frameworksDetected = null; - private FrameworksDetection() {} + private FrameworksDetection() { + } + public static String getFrameworksDetected() { if (frameworksDetected == null) {//Only detect frameworks once Set inferredFrameworks = new LinkedHashSet<>(); @@ -98,7 +100,7 @@ public Driver(DataSourceImpl dataSourceImpl) { public static void load() { try { - DriverManager.registerDriver(DriverHolder.INSTANCE); + DriverManager.registerDriver(INSTANCE); } catch (SQLException e) { log.error("Failed to register ClickHouse JDBC driver", e); } @@ -106,14 +108,13 @@ public static void load() { public static void unload() { try { - DriverManager.deregisterDriver(DriverHolder.INSTANCE); + DriverManager.deregisterDriver(INSTANCE); } catch (SQLException e) { log.error("Failed to deregister ClickHouse JDBC driver", e); } } - @Override public Connection connect(String url, Properties info) throws SQLException { if (!acceptsURL(url)) { @@ -164,7 +165,5 @@ public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedE throw new SQLFeatureNotSupportedException("Method not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); } - private static final class DriverHolder { - private static final Driver INSTANCE = new Driver(); - } + private static final Driver INSTANCE = new Driver(); } diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java index 8a2fcb617..a534b5556 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java @@ -303,26 +303,7 @@ public void setArray(int parameterIndex, Array x) throws SQLException { @Override public ResultSetMetaData getMetaData() throws SQLException { checkClosed(); - if (this.currentResultSet != null) { - return currentResultSet.getMetaData(); - } else if (statementType != StatementType.SELECT) { - return null; - } - - String sql = compileSql(sqlSegments); - String describe = String.format("describe (\n%s\n)", sql); - - List columns = new ArrayList<>(); - try (Statement stmt = connection.createStatement()) { - try (ResultSet rs = stmt.executeQuery(describe)) { - while (rs.next()) { - ClickHouseColumn column = ClickHouseColumn.of(rs.getString(1), rs.getString(2)); - columns.add(column); - } - } - } - TableSchema schema = new TableSchema(columns); - return new com.clickhouse.jdbc.metadata.ResultSetMetaData(schema); + return null; } @Override diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ResultSetMetaData.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ResultSetMetaData.java index 8810fd835..ab759c685 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ResultSetMetaData.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ResultSetMetaData.java @@ -1,7 +1,6 @@ package com.clickhouse.jdbc.metadata; import java.sql.SQLException; -import java.util.Objects; import com.clickhouse.client.api.metadata.TableSchema; import com.clickhouse.data.ClickHouseColumn; @@ -12,32 +11,21 @@ public class ResultSetMetaData implements java.sql.ResultSetMetaData, JdbcV2Wrapper { private final ResultSetImpl resultSet; - private final TableSchema schema; - public ResultSetMetaData(ResultSetImpl resultSet) { this.resultSet = resultSet; - this.schema = null; // result set schema is lazy - } - - public ResultSetMetaData(TableSchema schema) { - this.resultSet = null; - this.schema = schema; } private ClickHouseColumn getColumn(int column) throws SQLException { if (column < 1 || column > getColumnCount()) { throw new SQLException("Column index out of range: " + column, ExceptionUtils.SQL_STATE_CLIENT_ERROR); } - TableSchema schema = resultSet != null ? resultSet.getSchema() : this.schema; - assert schema != null : "Schema is null"; - return schema.getColumns().get(column - 1); + return resultSet.getSchema().getColumns().get(column - 1); } @Override public int getColumnCount() throws SQLException { try { - TableSchema schema = resultSet != null ? resultSet.getSchema() : this.schema; - assert schema != null : "Schema is null"; + TableSchema schema = resultSet.getSchema(); return schema.getColumns().size(); } catch (Exception e) { throw ExceptionUtils.toSqlState(e); 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 3959c494a..7f3f61ce5 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java @@ -491,17 +491,4 @@ void testStatementSplit() throws Exception { } } } - - @Test(groups = { "integration" }) - void testPreparedStatementMd() throws Exception { - try (Connection conn = getJdbcConnection()) { - try (PreparedStatement stmt = conn.prepareStatement("select 1::Int32 as value")) { - ResultSetMetaData md = stmt.getMetaData(); - assertNotNull(md); - assertEquals(md.getColumnCount(), 1); - assertEquals(md.getColumnName(1), "value"); - assertEquals(md.getColumnType(1), Types.INTEGER); - } - } - } }