From fe6ca21d18a343d1176ec429e30ffb8c7edaaaae Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Mon, 4 Aug 2025 20:44:43 -0700 Subject: [PATCH 1/3] enabled tests. added some more for ConnectionImpl. implementated nativeSQL method --- CHANGELOG.md | 2 +- .../{internal => }/ClientInfoProperties.java | 2 +- .../com/clickhouse/jdbc/ConnectionImpl.java | 120 ++++++++++-------- .../jdbc/{internal => }/DriverProperties.java | 4 +- .../com/clickhouse/jdbc/StatementImpl.java | 50 ++++---- .../clickhouse/jdbc/WriterStatementImpl.java | 4 +- .../jdbc/internal/JdbcConfiguration.java | 2 +- .../jdbc/metadata/DatabaseMetaDataImpl.java | 6 +- .../com/clickhouse/jdbc/ConnectionTest.java | 117 +++++++++++++---- .../clickhouse/jdbc/JdbcIntegrationTest.java | 4 +- .../jdbc/PreparedStatementTest.java | 1 - .../com/clickhouse/jdbc/StatementTest.java | 41 +++++- .../jdbc/WriterStatementImplTest.java | 1 - .../jdbc/internal/JdbcConfigurationTest.java | 1 + .../jdbc/metadata/DatabaseMetaDataTest.java | 4 +- 15 files changed, 234 insertions(+), 125 deletions(-) rename jdbc-v2/src/main/java/com/clickhouse/jdbc/{internal => }/ClientInfoProperties.java (95%) rename jdbc-v2/src/main/java/com/clickhouse/jdbc/{internal => }/DriverProperties.java (93%) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca4b16652..88f55b816 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ After the fix array values contain primitive types. (https://github.com/ClickHou ### Improvements - [jdbc-v2] Now using Antlr4 to parse SQL statements to get meta information about it. Invalid SQL still possible to execute if logic able to get all required information. (https://github.com/ClickHouse/clickhouse-java/pull/2351) -- [jdbc-v2] Now possible to use `RowBinaryWriter` if enabled by property `com.clickhouse.jdbc.internal.DriverProperties.BETA_ROW_BINARY_WRITER`. +- [jdbc-v2] Now possible to use `RowBinaryWriter` if enabled by property `com.clickhouse.jdbc.DriverProperties.BETA_ROW_BINARY_WRITER`. This works well for batches. Single statements may get no benefits. (https://github.com/ClickHouse/clickhouse-java/pull/2316) ### Bug Fixes diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/ClientInfoProperties.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/ClientInfoProperties.java similarity index 95% rename from jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/ClientInfoProperties.java rename to jdbc-v2/src/main/java/com/clickhouse/jdbc/ClientInfoProperties.java index ada5139d6..7a3fbaa1a 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/ClientInfoProperties.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/ClientInfoProperties.java @@ -1,4 +1,4 @@ -package com.clickhouse.jdbc.internal; +package com.clickhouse.jdbc; public enum ClientInfoProperties { diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/ConnectionImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/ConnectionImpl.java index cdc8ffb06..9d86c8f1e 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/ConnectionImpl.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/ConnectionImpl.java @@ -7,15 +7,12 @@ import com.clickhouse.client.api.query.GenericRecord; import com.clickhouse.client.api.query.QuerySettings; import com.clickhouse.data.ClickHouseDataType; -import com.clickhouse.jdbc.internal.ClientInfoProperties; -import com.clickhouse.jdbc.internal.DriverProperties; import com.clickhouse.jdbc.internal.ExceptionUtils; import com.clickhouse.jdbc.internal.JdbcConfiguration; import com.clickhouse.jdbc.internal.JdbcUtils; import com.clickhouse.jdbc.internal.ParsedPreparedStatement; import com.clickhouse.jdbc.internal.SqlParser; import com.clickhouse.jdbc.metadata.DatabaseMetaDataImpl; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,7 +49,7 @@ public class ConnectionImpl implements Connection, JdbcV2Wrapper { private static final Logger log = LoggerFactory.getLogger(ConnectionImpl.class); protected final String url; - protected final Client client; + private final Client client; // this member is private to force using getClient() protected final JdbcConfiguration config; private boolean closed = false; @@ -127,7 +124,6 @@ public SqlParser getSqlParser() { } public QuerySettings getDefaultQuerySettings() { - defaultQuerySettings.setDatabase(schema); return defaultQuerySettings; } @@ -153,19 +149,19 @@ public JdbcConfiguration getJdbcConfig() { @Override public Statement createStatement() throws SQLException { - checkOpen(); + ensureOpen(); return createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT); } @Override public PreparedStatement prepareStatement(String sql) throws SQLException { - checkOpen(); + ensureOpen(); return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT); } @Override public CallableStatement prepareCall(String sql) throws SQLException { - checkOpen(); + ensureOpen(); if (!config.isIgnoreUnsupportedRequests()) { throw new SQLFeatureNotSupportedException("CallableStatement not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); } @@ -175,18 +171,14 @@ public CallableStatement prepareCall(String sql) throws SQLException { @Override public String nativeSQL(String sql) throws SQLException { - checkOpen(); - /// TODO: this is not implemented according to JDBC spec and may not be used. - if (!config.isIgnoreUnsupportedRequests()) { - throw new SQLFeatureNotSupportedException("nativeSQL not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); - } - - return null; + ensureOpen(); + // Currently it replaces escaped functions with real ones. + return StatementImpl.escapedSQLToNative(sql); } @Override public void setAutoCommit(boolean autoCommit) throws SQLException { - checkOpen(); + ensureOpen(); if (!config.isIgnoreUnsupportedRequests() && !autoCommit) { throw new SQLFeatureNotSupportedException("setAutoCommit = false not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); @@ -195,7 +187,7 @@ public void setAutoCommit(boolean autoCommit) throws SQLException { @Override public boolean getAutoCommit() throws SQLException { - checkOpen(); + ensureOpen(); return true; } @@ -230,13 +222,13 @@ public boolean isClosed() throws SQLException { @Override public DatabaseMetaData getMetaData() throws SQLException { - checkOpen(); + ensureOpen(); return this.metadata; } @Override public void setReadOnly(boolean readOnly) throws SQLException { - checkOpen(); + ensureOpen(); if (!config.isIgnoreUnsupportedRequests() && readOnly) { throw new SQLFeatureNotSupportedException("read-only=true unsupported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); } @@ -244,13 +236,13 @@ public void setReadOnly(boolean readOnly) throws SQLException { @Override public boolean isReadOnly() throws SQLException { - checkOpen(); + ensureOpen(); return false; } @Override public void setCatalog(String catalog) throws SQLException { - checkOpen(); + ensureOpen(); // this.catalog = catalog; currently not supported } @@ -261,7 +253,7 @@ public String getCatalog() throws SQLException { @Override public void setTransactionIsolation(int level) throws SQLException { - checkOpen(); + ensureOpen(); if (!config.isIgnoreUnsupportedRequests() && TRANSACTION_NONE != level) { throw new SQLFeatureNotSupportedException("setTransactionIsolation not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); } @@ -269,36 +261,36 @@ public void setTransactionIsolation(int level) throws SQLException { @Override public int getTransactionIsolation() throws SQLException { - checkOpen(); + ensureOpen(); return TRANSACTION_NONE; } @Override public SQLWarning getWarnings() throws SQLException { - checkOpen(); + ensureOpen(); return null; } @Override public void clearWarnings() throws SQLException { - checkOpen(); + ensureOpen(); } @Override public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { - checkOpen(); + ensureOpen(); return createStatement(resultSetType, resultSetConcurrency, ResultSet.CLOSE_CURSORS_AT_COMMIT); } @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - checkOpen(); + ensureOpen(); return prepareStatement(sql, resultSetType, resultSetConcurrency, ResultSet.CLOSE_CURSORS_AT_COMMIT); } @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - checkOpen(); + ensureOpen(); if (!config.isIgnoreUnsupportedRequests()) { throw new SQLFeatureNotSupportedException("CallableStatement not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); } @@ -308,7 +300,7 @@ public CallableStatement prepareCall(String sql, int resultSetType, int resultSe @Override public Map> getTypeMap() throws SQLException { - checkOpen(); + ensureOpen(); if (!config.isIgnoreUnsupportedRequests()) { throw new SQLFeatureNotSupportedException("getTypeMap not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); } @@ -318,7 +310,7 @@ public Map> getTypeMap() throws SQLException { @Override public void setTypeMap(Map> map) throws SQLException { - checkOpen(); + ensureOpen(); if (!config.isIgnoreUnsupportedRequests()) { throw new SQLFeatureNotSupportedException("setTypeMap not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); } @@ -326,19 +318,19 @@ public void setTypeMap(Map> map) throws SQLException { @Override public void setHoldability(int holdability) throws SQLException { - checkOpen(); + ensureOpen(); //TODO: Should this be supported? } @Override public int getHoldability() throws SQLException { - checkOpen(); + ensureOpen(); return ResultSet.HOLD_CURSORS_OVER_COMMIT;//TODO: Check if this is correct } @Override public Savepoint setSavepoint() throws SQLException { - checkOpen(); + ensureOpen(); if (!config.isIgnoreUnsupportedRequests()) { throw new SQLFeatureNotSupportedException("Savepoint not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); } @@ -348,7 +340,7 @@ public Savepoint setSavepoint() throws SQLException { @Override public Savepoint setSavepoint(String name) throws SQLException { - checkOpen(); + ensureOpen(); if (!config.isIgnoreUnsupportedRequests()) { throw new SQLFeatureNotSupportedException("Savepoint not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); } @@ -358,7 +350,7 @@ public Savepoint setSavepoint(String name) throws SQLException { @Override public void rollback(Savepoint savepoint) throws SQLException { - checkOpen(); + ensureOpen(); if (!config.isIgnoreUnsupportedRequests()) { throw new SQLFeatureNotSupportedException("Commit/Rollback not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); } @@ -366,7 +358,7 @@ public void rollback(Savepoint savepoint) throws SQLException { @Override public void releaseSavepoint(Savepoint savepoint) throws SQLException { - checkOpen(); + ensureOpen(); if (!config.isIgnoreUnsupportedRequests()) { throw new SQLFeatureNotSupportedException("Savepoint not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); } @@ -374,14 +366,32 @@ public void releaseSavepoint(Savepoint savepoint) throws SQLException { @Override public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - checkOpen(); + ensureOpen(); + checkResultSetFlags(resultSetType, resultSetConcurrency, resultSetHoldability); return new StatementImpl(this); } + private void checkResultSetFlags(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + if (!config.isIgnoreUnsupportedRequests()) { + if (resultSetType != ResultSet.TYPE_FORWARD_ONLY) { + throw new SQLFeatureNotSupportedException("Cannot create statement with result set type other then ResultSet.TYPE_FORWARD_ONLY", + ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); + } + if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY) { + throw new SQLFeatureNotSupportedException("Cannot create statement with result set concurrency other then ResultSet.CONCUR_READ_ONLY", + ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); + } + if (resultSetHoldability != ResultSet.CLOSE_CURSORS_AT_COMMIT) { + throw new SQLFeatureNotSupportedException("Cannot create statement with result set holdability other then ResultSet.CLOSE_CURSORS_AT_COMMIT", + ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); + } + } + } + @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - checkOpen(); - + ensureOpen(); + checkResultSetFlags(resultSetType, resultSetConcurrency, resultSetHoldability); ParsedPreparedStatement parsedStatement = sqlParser.parsePreparedStatement(sql); if (parsedStatement.isInsert() && config.isBetaFeatureEnabled(DriverProperties.BETA_ROW_BINARY_WRITER)) { @@ -406,7 +416,7 @@ public PreparedStatement prepareStatement(String sql, int resultSetType, int res @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - checkOpen(); + ensureOpen(); if (!config.isIgnoreUnsupportedRequests()) { throw new SQLFeatureNotSupportedException("CallableStatement not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); } @@ -416,7 +426,7 @@ public CallableStatement prepareCall(String sql, int resultSetType, int resultSe @Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { - checkOpen(); + ensureOpen(); //TODO: Should this be supported? if (!config.isIgnoreUnsupportedRequests()) { throw new SQLFeatureNotSupportedException("prepareStatement(String sql, int autoGeneratedKeys) not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); @@ -427,7 +437,7 @@ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) thr @Override public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { - checkOpen(); + ensureOpen(); //TODO: Should this be supported? if (!config.isIgnoreUnsupportedRequests()) { throw new SQLFeatureNotSupportedException("prepareStatement(String sql, int[] columnIndexes) not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); @@ -438,7 +448,7 @@ public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throw @Override public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { - checkOpen(); + ensureOpen(); //TODO: Should this be supported? if (!config.isIgnoreUnsupportedRequests()) { throw new SQLFeatureNotSupportedException("prepareStatement(String sql, String[] columnNames) not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); @@ -449,7 +459,7 @@ public PreparedStatement prepareStatement(String sql, String[] columnNames) thro @Override public Clob createClob() throws SQLException { - checkOpen(); + ensureOpen(); if (!config.isIgnoreUnsupportedRequests()) { throw new SQLFeatureNotSupportedException("Clob not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); } @@ -459,7 +469,7 @@ public Clob createClob() throws SQLException { @Override public Blob createBlob() throws SQLException { - checkOpen(); + ensureOpen(); if (!config.isIgnoreUnsupportedRequests()) { throw new SQLFeatureNotSupportedException("Blob not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); } @@ -469,7 +479,7 @@ public Blob createBlob() throws SQLException { @Override public NClob createNClob() throws SQLException { - checkOpen(); + ensureOpen(); if (!config.isIgnoreUnsupportedRequests()) { throw new SQLFeatureNotSupportedException("NClob not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); } @@ -479,7 +489,7 @@ public NClob createNClob() throws SQLException { @Override public SQLXML createSQLXML() throws SQLException { - checkOpen(); + ensureOpen(); if (!config.isIgnoreUnsupportedRequests()) { throw new SQLFeatureNotSupportedException("SQLXML not supported", ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED); } @@ -535,7 +545,7 @@ public void setClientInfo(Properties properties) throws SQLClientInfoException { @Override public String getClientInfo(String name) throws SQLException { - checkOpen(); + ensureOpen(); if (ClientInfoProperties.APPLICATION_NAME.getKey().equals(name)) { return appName; } else { @@ -545,9 +555,9 @@ public String getClientInfo(String name) throws SQLException { @Override public Properties getClientInfo() throws SQLException { - checkOpen(); + ensureOpen(); Properties clientInfo = new Properties(); - clientInfo.put(ClientInfoProperties.APPLICATION_NAME.getKey(), getClientInfo(ClientInfoProperties.APPLICATION_NAME.getKey())); + clientInfo.put(ClientInfoProperties.APPLICATION_NAME.getKey(), appName); return clientInfo; } @@ -574,13 +584,14 @@ public Struct createStruct(String typeName, Object[] attributes) throws SQLExcep @Override public void setSchema(String schema) throws SQLException { - checkOpen(); + ensureOpen(); this.schema = schema; + defaultQuerySettings.setDatabase(this.schema); } @Override public String getSchema() throws SQLException { - checkOpen(); + ensureOpen(); return schema; } @@ -613,11 +624,12 @@ public int getNetworkTimeout() throws SQLException { * Returns instance of the client used to execute queries by this connection. * @return - client instance */ - public Client getClient() { + public Client getClient() throws SQLException { + ensureOpen(); return client; } - private void checkOpen() throws SQLException { + private void ensureOpen() throws SQLException { if (isClosed()) { throw new SQLException("Connection is closed", ExceptionUtils.SQL_STATE_CONNECTION_EXCEPTION); } diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/DriverProperties.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/DriverProperties.java similarity index 93% rename from jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/DriverProperties.java rename to jdbc-v2/src/main/java/com/clickhouse/jdbc/DriverProperties.java index 6d57f6bfd..1f138cb47 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/DriverProperties.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/DriverProperties.java @@ -1,10 +1,10 @@ -package com.clickhouse.jdbc.internal; +package com.clickhouse.jdbc; import java.util.Collections; import java.util.List; /** - * JDBC driver specific properties. Should not include any of ClientConfigProperties. + * JDBC driver specific properties. Does not include anything from ClientConfigProperties. * Processing logic should be the follows * 1. If property is among DriverProperties then Driver handles it specially and will not pass to a client * 2. If property is not among DriverProperties then it is passed to a client 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 4f5422104..ef2ec3086 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/StatementImpl.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/StatementImpl.java @@ -6,7 +6,6 @@ import com.clickhouse.client.api.query.QueryResponse; import com.clickhouse.client.api.query.QuerySettings; import com.clickhouse.client.api.sql.SQLUtils; -import com.clickhouse.jdbc.internal.DriverProperties; import com.clickhouse.jdbc.internal.ExceptionUtils; import com.clickhouse.jdbc.internal.ParsedStatement; import org.slf4j.Logger; @@ -66,27 +65,34 @@ protected void ensureOpen() throws SQLException { } } - private String parseJdbcEscapeSyntax(String sql) { LOG.trace("Original SQL: {}", sql); if (escapeProcessingEnabled) { - // Replace {d 'YYYY-MM-DD'} with corresponding SQL date format - sql = sql.replaceAll("\\{d '([^']*)'\\}", "toDate('$1')"); + sql = escapedSQLToNative(sql); + } + LOG.trace("Escaped SQL: {}", sql); + return sql; + } - // Replace {ts 'YYYY-MM-DD HH:mm:ss'} with corresponding SQL timestamp format - sql = sql.replaceAll("\\{ts '([^']*)'\\}", "timestamp('$1')"); + public static String escapedSQLToNative(String sql) { + if (sql == null) { + throw new IllegalArgumentException("SQL may not be null"); + } + // Replace {d 'YYYY-MM-DD'} with corresponding SQL date format + sql = sql.replaceAll("\\{d '([^']*)'\\}", "toDate('$1')"); - // Replace function escape syntax {fn } (e.g., {fn UCASE(name)}) - sql = sql.replaceAll("\\{fn ([^\\}]*)\\}", "$1"); + // Replace {ts 'YYYY-MM-DD HH:mm:ss'} with corresponding SQL timestamp format + sql = sql.replaceAll("\\{ts '([^']*)'\\}", "timestamp('$1')"); - // Handle outer escape syntax - //sql = sql.replaceAll("\\{escape '([^']*)'\\}", "'$1'"); + // Replace function escape syntax {fn } (e.g., {fn UCASE(name)}) + sql = sql.replaceAll("\\{fn ([^\\}]*)\\}", "$1"); + + // Handle outer escape syntax + //sql = sql.replaceAll("\\{escape '([^']*)'\\}", "'$1'"); + + // Note: do not remove new lines because they may be used to delimit comments + // Add more replacements as needed for other JDBC escape sequences - // Clean new empty lines in sql - sql = sql.replaceAll("(?m)^\\s*$\\n?", ""); - // Add more replacements as needed for other JDBC escape sequences - } - LOG.trace("Escaped SQL: {}", sql); return sql; } @@ -138,16 +144,16 @@ protected ResultSetImpl executeQueryImpl(String sql, QuerySettings settings) thr lastStatementSql = parseJdbcEscapeSyntax(sql); LOG.trace("SQL Query: {}", lastStatementSql); // this is not secure for create statements because of passwords if (queryTimeout == 0) { - response = connection.client.query(lastStatementSql, mergedSettings).get(); + response = connection.getClient().query(lastStatementSql, mergedSettings).get(); } else { - response = connection.client.query(lastStatementSql, mergedSettings).get(queryTimeout, TimeUnit.SECONDS); + response = connection.getClient().query(lastStatementSql, mergedSettings).get(queryTimeout, TimeUnit.SECONDS); } if (response.getFormat().isText()) { throw new SQLException("Only RowBinaryWithNameAndTypes is supported for output format. Please check your query.", ExceptionUtils.SQL_STATE_CLIENT_ERROR); } - ClickHouseBinaryFormatReader reader = connection.client.newBinaryFormatReader(response); + ClickHouseBinaryFormatReader reader = connection.getClient().newBinaryFormatReader(response); if (reader.getSchema() == null) { throw new SQLException("Called method expects empty or filled result set but query has returned none. Consider using `java.sql.Statement.execute(java.lang.String)`", ExceptionUtils.SQL_STATE_CLIENT_ERROR); } @@ -191,8 +197,8 @@ protected long executeUpdateImpl(String sql, QuerySettings settings) throws SQLE lastStatementSql = parseJdbcEscapeSyntax(sql); LOG.trace("SQL Query: {}", lastStatementSql); int updateCount = 0; - try (QueryResponse response = queryTimeout == 0 ? connection.client.query(lastStatementSql, mergedSettings).get() - : connection.client.query(lastStatementSql, mergedSettings).get(queryTimeout, TimeUnit.SECONDS)) { + try (QueryResponse response = queryTimeout == 0 ? connection.getClient().query(lastStatementSql, mergedSettings).get() + : connection.getClient().query(lastStatementSql, mergedSettings).get(queryTimeout, TimeUnit.SECONDS)) { updateCount = Math.max(0, (int) response.getWrittenRows()); // when statement alters schema no result rows returned. lastQueryId = response.getQueryId(); } catch (Exception e) { @@ -202,7 +208,7 @@ protected long executeUpdateImpl(String sql, QuerySettings settings) throws SQLE return updateCount; } - protected void postUpdateActions() { + protected void postUpdateActions() throws SQLException { if (parsedStatement.getUseDatabase() != null) { this.localSettings.setDatabase(parsedStatement.getUseDatabase()); } @@ -278,7 +284,7 @@ public void cancel() throws SQLException { return; } - try (QueryResponse response = connection.client.query(String.format("KILL QUERY%sWHERE query_id = '%s'", + try (QueryResponse response = connection.getClient().query(String.format("KILL QUERY%sWHERE query_id = '%s'", connection.onCluster ? " ON CLUSTER " + connection.cluster + " " : " ", lastQueryId), connection.getDefaultQuerySettings()).get()){ LOG.debug("Query {} was killed by {}", lastQueryId, response.getQueryId()); diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/WriterStatementImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/WriterStatementImpl.java index c0c1d719e..833a7f352 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/WriterStatementImpl.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/WriterStatementImpl.java @@ -116,8 +116,8 @@ public long executeLargeUpdate() throws SQLException { InputStream in = new ByteArrayInputStream(out.toByteArray()); InsertSettings settings = new InsertSettings(); try (InsertResponse response = queryTimeout == 0 ? - connection.client.insert(tableSchema.getTableName(),in, writer.getFormat(), settings).get() - : connection.client.insert(tableSchema.getTableName(),in, writer.getFormat(), settings).get(queryTimeout, TimeUnit.SECONDS)) { + connection.getClient().insert(tableSchema.getTableName(),in, writer.getFormat(), settings).get() + : connection.getClient().insert(tableSchema.getTableName(),in, writer.getFormat(), settings).get(queryTimeout, TimeUnit.SECONDS)) { updateCount = Math.max(0, (int) response.getWrittenRows()); // when statement alters schema no result rows returned. lastQueryId = response.getQueryId(); } catch (Exception e) { diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcConfiguration.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcConfiguration.java index 0f75db3fb..49f6d7515 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcConfiguration.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcConfiguration.java @@ -5,6 +5,7 @@ import com.clickhouse.client.api.http.ClickHouseHttpProto; import com.clickhouse.data.ClickHouseDataType; import com.clickhouse.jdbc.Driver; +import com.clickhouse.jdbc.DriverProperties; import com.google.common.collect.ImmutableMap; import java.io.UnsupportedEncodingException; @@ -12,7 +13,6 @@ import java.net.URISyntaxException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; -import java.nio.charset.UnsupportedCharsetException; import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.util.Comparator; diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataImpl.java index 44b7817e5..f31b8034f 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataImpl.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataImpl.java @@ -7,13 +7,11 @@ import com.clickhouse.jdbc.Driver; import com.clickhouse.jdbc.JdbcV2Wrapper; import com.clickhouse.jdbc.ResultSetImpl; -import com.clickhouse.jdbc.StatementImpl; -import com.clickhouse.jdbc.internal.ClientInfoProperties; -import com.clickhouse.jdbc.internal.DriverProperties; +import com.clickhouse.jdbc.ClientInfoProperties; +import com.clickhouse.jdbc.DriverProperties; import com.clickhouse.jdbc.internal.ExceptionUtils; import com.clickhouse.jdbc.internal.JdbcUtils; import com.clickhouse.jdbc.internal.MetadataResultSet; -import com.clickhouse.jdbc.internal.SqlParser; import com.clickhouse.logging.Logger; import com.clickhouse.logging.LoggerFactory; diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/ConnectionTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/ConnectionTest.java index 8ae0d27a1..497df07da 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/ConnectionTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/ConnectionTest.java @@ -7,13 +7,10 @@ import com.clickhouse.client.api.ClientConfigProperties; import com.clickhouse.client.api.ServerException; import com.clickhouse.client.api.internal.ServerSettings; -import com.clickhouse.jdbc.internal.ClientInfoProperties; -import com.clickhouse.jdbc.internal.DriverProperties; import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; import com.github.tomakehurst.wiremock.common.ConsoleNotifier; import com.github.tomakehurst.wiremock.core.WireMockConfiguration; - import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -32,31 +29,78 @@ import java.util.Properties; import java.util.UUID; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; import static org.testng.Assert.assertThrows; import static org.testng.Assert.fail; public class ConnectionTest extends JdbcIntegrationTest { - @Test(groups = { "integration" }, enabled = false) + @Test(groups = { "integration" }) public void createAndCloseStatementTest() throws SQLException { - Connection localConnection = this.getJdbcConnection(); - Statement statement = localConnection.createStatement(); - Assert.assertNotNull(statement); + Connection conn = getJdbcConnection(); + Statement stmt = conn.createStatement(); + PreparedStatement pStmt = conn.prepareStatement("SELECT ? as v"); + pStmt.setString(1, "test string"); + conn.close(); + conn.close(); // check second attempt doesn't throw anything + assertThrows(SQLException.class, () ->conn.createStatement()); + + try { + stmt.executeQuery("SELECT 1"); + fail("Exception expected"); + } catch (SQLException e) { + Assert.assertTrue(e.getMessage().contains("closed")); + } + + try { + pStmt.executeQuery(); + fail("Exception expected"); + } catch (SQLException e) { + Assert.assertTrue(e.getMessage().contains("closed")); - assertThrows(SQLFeatureNotSupportedException.class, () -> localConnection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)); - assertThrows(SQLFeatureNotSupportedException.class, () -> localConnection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT)); + } } - @Test(groups = { "integration" }, enabled = false) - public void prepareStatementTest() throws SQLException { - Connection localConnection = this.getJdbcConnection(); - PreparedStatement statement = localConnection.prepareStatement("SELECT 1"); - Assert.assertNotNull(statement); - assertThrows(SQLFeatureNotSupportedException.class, () -> localConnection.prepareStatement("SELECT 1", Statement.RETURN_GENERATED_KEYS)); - assertThrows(SQLFeatureNotSupportedException.class, () -> localConnection.prepareStatement("SELECT 1", new int[] { 1 })); - assertThrows(SQLFeatureNotSupportedException.class, () -> localConnection.prepareStatement("SELECT 1", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)); - assertThrows(SQLFeatureNotSupportedException.class, () -> localConnection.prepareStatement("SELECT 1", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT)); - assertThrows(SQLFeatureNotSupportedException.class, () -> localConnection.prepareStatement("SELECT 1", new String[] { "1" })); + @Test(groups = { "integration" }) + public void testCreateUnsupportedStatements() throws Throwable { + + boolean[] throwUnsupportedException = new boolean[] {false, true}; + + for (boolean flag : throwUnsupportedException) { + Properties props = new Properties(); + if (flag) { + props.setProperty(DriverProperties.IGNORE_UNSUPPORTED_VALUES.getKey(), "true"); + } + + try (Connection conn = this.getJdbcConnection(props)) { + Assert.ThrowingRunnable[] createStatements = new Assert.ThrowingRunnable[]{ + () -> conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY), + () -> conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE), + () -> conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT), + () -> conn.prepareStatement("SELECT 1", Statement.RETURN_GENERATED_KEYS), + () -> conn.prepareStatement("SELECT 1", new int[]{1}), + () -> conn.prepareStatement("SELECT 1", new String[]{"1"}), + () -> conn.prepareStatement("SELECT 1", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE), + () -> conn.prepareStatement("SELECT 1", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY), + () -> conn.prepareStatement("SELECT 1", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT), + () -> conn.setSavepoint(), + () -> conn.setSavepoint("save point"), + () -> conn.createStruct("simple", null), + }; + + int i = 0; + for (Assert.ThrowingRunnable createStatement : createStatements) { + System.out.println("Failed at pos " + (i)); + if (!flag) { + Assert.assertThrows(SQLFeatureNotSupportedException.class, createStatement ); + } else { + createStatement.run(); + } + i++; + } + } + } } @Test(groups = { "integration" }) @@ -67,12 +111,16 @@ public void prepareCallTest() throws SQLException { assertThrows(SQLFeatureNotSupportedException.class, () -> localConnection.prepareCall("SELECT 1", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT)); } - @Test(groups = { "integration" }, enabled = false) + @Test(groups = { "integration" }) public void nativeSQLTest() throws SQLException { - // TODO: implement - Connection localConnection = this.getJdbcConnection(); - String sql = "SELECT 1"; - Assert.assertEquals(localConnection.nativeSQL(sql), sql); + try (Connection conn = this.getJdbcConnection()) { + String escapedSQL = "SELECT \n{ts '2024-01-02 02:01:01'} as v1,\n {d '2024-01-02 02:01:01'} as v2,\n {d ?} as v3"; + String nativeSQL = "SELECT \ntimestamp('2024-01-02 02:01:01') as v1,\n toDate('2024-01-02 02:01:01') as v2,\n {d ?} as v3"; + Assert.assertEquals(conn.nativeSQL(escapedSQL), nativeSQL); + + Assert.expectThrows(IllegalArgumentException.class, () -> conn.nativeSQL(null)); + Assert.assertEquals(conn.nativeSQL("SELECT 1 as t"), "SELECT 1 as t"); + } } @Test(groups = { "integration" }) @@ -606,4 +654,25 @@ private static Object[][] createValidDatabaseNames() { }; } + @Test(groups = {"integration"}) + public void testClientInfoProperties() throws Exception { + try (Connection conn = this.getJdbcConnection()) { + + Properties properties = conn.getClientInfo(); + assertEquals(properties.get(ClientInfoProperties.APPLICATION_NAME.getKey()), ""); + + properties.put(ClientInfoProperties.APPLICATION_NAME.getKey(), "test"); + conn.setClientInfo(properties); + + assertEquals(properties.get(ClientInfoProperties.APPLICATION_NAME.getKey()), "test"); + + conn.setClientInfo(new Properties()); + assertNull(conn.getClientInfo(ClientInfoProperties.APPLICATION_NAME.getKey())); + + conn.setClientInfo(ClientInfoProperties.APPLICATION_NAME.getKey(), "test 2"); + assertEquals(conn.getClientInfo(ClientInfoProperties.APPLICATION_NAME.getKey()), "test 2"); + + assertNull(conn.getClientInfo("unknown")); + } + } } diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/JdbcIntegrationTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/JdbcIntegrationTest.java index b54e3a644..5728bc318 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/JdbcIntegrationTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/JdbcIntegrationTest.java @@ -86,9 +86,7 @@ protected boolean earlierThan(int major, int minor) { protected String getServerVersion() { try (ConnectionImpl connection = (ConnectionImpl) getJdbcConnection()) { - GenericRecord result = connection.client.queryAll("SELECT version() as server_version").stream() - .findFirst().orElseThrow(() -> new SQLException("Failed to retrieve server version.")); - return result.getString("server_version"); + return connection.getServerVersion(); } catch (SQLException e) { return null; } 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 2c87d9506..88363c6a0 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java @@ -3,7 +3,6 @@ import com.clickhouse.data.ClickHouseDataType; import com.clickhouse.data.ClickHouseVersion; import com.clickhouse.data.Tuple; -import com.clickhouse.jdbc.internal.DriverProperties; import com.clickhouse.jdbc.internal.JdbcUtils; import org.apache.commons.lang3.RandomStringUtils; import org.testng.Assert; 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 23cfe874e..0cee1cfa6 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java @@ -3,7 +3,6 @@ import com.clickhouse.client.api.ClientConfigProperties; import com.clickhouse.client.api.internal.ServerSettings; import com.clickhouse.client.api.query.GenericRecord; -import com.clickhouse.jdbc.internal.DriverProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.Assert; @@ -384,14 +383,14 @@ public void testSettingRole() throws SQLException { info.setProperty("password", userPass); try (ConnectionImpl conn = new ConnectionImpl(getEndpointString(), info)) { - GenericRecord record = conn.client.queryAll("SELECT currentRoles()").get(0); + GenericRecord record = conn.getClient().queryAll("SELECT currentRoles()").get(0); assertEquals(record.getList(1).size(), 0); try (Statement stmt = conn.createStatement()) { stmt.execute("SET ROLE role1"); } - record = conn.client.queryAll("SELECT currentRoles()").get(0); + record = conn.getClient().queryAll("SELECT currentRoles()").get(0); assertEquals(record.getList(1).size(), 1); assertEquals(record.getList(1).get(0), "role1"); @@ -399,7 +398,7 @@ record = conn.client.queryAll("SELECT currentRoles()").get(0); stmt.execute("SET ROLE role2"); } - record = conn.client.queryAll("SELECT currentRoles()").get(0); + record = conn.getClient().queryAll("SELECT currentRoles()").get(0); assertEquals(record.getList(1).size(), 1); assertEquals(record.getList(1).get(0), "role2"); @@ -407,14 +406,14 @@ record = conn.client.queryAll("SELECT currentRoles()").get(0); stmt.execute("SET ROLE NONE"); } - record = conn.client.queryAll("SELECT currentRoles()").get(0); + record = conn.getClient().queryAll("SELECT currentRoles()").get(0); assertEquals(record.getList(1).size(), 0); try (Statement stmt = conn.createStatement()) { stmt.execute("SET ROLE \"role1\",\"role2\""); } - record = conn.client.queryAll("SELECT currentRoles()").get(0); + record = conn.getClient().queryAll("SELECT currentRoles()").get(0); assertEquals(record.getList(1).size(), 2); assertEquals(record.getList(1).get(0), "role1"); assertEquals(record.getList(1).get(1), "role2"); @@ -423,7 +422,7 @@ record = conn.client.queryAll("SELECT currentRoles()").get(0); stmt.execute("SET ROLE \"role1\",\"role2\",\"role3\""); } - record = conn.client.queryAll("SELECT currentRoles()").get(0); + record = conn.getClient().queryAll("SELECT currentRoles()").get(0); assertEquals(record.getList(1).size(), 3); assertEquals(record.getList(1).get(0), "role1"); assertEquals(record.getList(1).get(1), "role2"); @@ -1019,4 +1018,32 @@ public void testExecute() throws Exception { assertEquals(rs.getInt(1), 1); } } + + @Test(groups = {"integration"}) + public void setConnectionSchema() throws Exception { + String db1 = getDatabase() + "_schema1"; + String db2 = getDatabase() + "_schema2"; + try (Connection conn = getJdbcConnection(); Statement stmt = conn.createStatement()) { + stmt.execute("CREATE DATABASE " + db1); + stmt.execute("CREATE DATABASE " + db2); + } + + try (Connection conn = getJdbcConnection()) { + conn.setSchema(db1); + + try (Statement stmt = conn.createStatement()) { + assertEquals(getDBName(stmt), db1); + conn.setSchema(db2); + assertEquals(getDBName(stmt), db1); + } + + } + } + + private static String getDBName(Statement stmt) throws SQLException { + try (ResultSet rs = stmt.executeQuery("SELECT database()")) { + rs.next(); + return rs.getString(1); + } + } } diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/WriterStatementImplTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/WriterStatementImplTest.java index abc062604..2762c76c6 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/WriterStatementImplTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/WriterStatementImplTest.java @@ -1,6 +1,5 @@ package com.clickhouse.jdbc; -import com.clickhouse.jdbc.internal.DriverProperties; import org.testng.Assert; import org.testng.annotations.Test; diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/JdbcConfigurationTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/JdbcConfigurationTest.java index 8e06aa99e..26a09793d 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/JdbcConfigurationTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/JdbcConfigurationTest.java @@ -3,6 +3,7 @@ import com.clickhouse.client.api.Client; import com.clickhouse.client.api.ClientConfigProperties; +import com.clickhouse.jdbc.DriverProperties; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataTest.java index 3c79cbabd..af3191a42 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataTest.java @@ -4,8 +4,8 @@ import com.clickhouse.data.ClickHouseDataType; import com.clickhouse.data.ClickHouseVersion; import com.clickhouse.jdbc.JdbcIntegrationTest; -import com.clickhouse.jdbc.internal.ClientInfoProperties; -import com.clickhouse.jdbc.internal.DriverProperties; +import com.clickhouse.jdbc.ClientInfoProperties; +import com.clickhouse.jdbc.DriverProperties; import com.clickhouse.jdbc.internal.JdbcUtils; import org.testng.Assert; import org.testng.annotations.Test; From 91899f00d57a643320d28a0bc16ea87871b06e73 Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Mon, 4 Aug 2025 21:07:00 -0700 Subject: [PATCH 2/3] Resolved a few lint warnings --- .../com/clickhouse/jdbc/StatementImpl.java | 1 + .../com/clickhouse/jdbc/ConnectionTest.java | 18 ++++---- .../com/clickhouse/jdbc/StatementTest.java | 42 +++++++++---------- 3 files changed, 29 insertions(+), 32 deletions(-) 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 ef2ec3086..3e1a64848 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/StatementImpl.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/StatementImpl.java @@ -155,6 +155,7 @@ protected ResultSetImpl executeQueryImpl(String sql, QuerySettings settings) thr } ClickHouseBinaryFormatReader reader = connection.getClient().newBinaryFormatReader(response); if (reader.getSchema() == null) { + reader.close(); throw new SQLException("Called method expects empty or filled result set but query has returned none. Consider using `java.sql.Statement.execute(java.lang.String)`", ExceptionUtils.SQL_STATE_CLIENT_ERROR); } return new ResultSetImpl(this, response, reader); diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/ConnectionTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/ConnectionTest.java index 497df07da..bec3d83c5 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/ConnectionTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/ConnectionTest.java @@ -44,7 +44,7 @@ public void createAndCloseStatementTest() throws SQLException { pStmt.setString(1, "test string"); conn.close(); conn.close(); // check second attempt doesn't throw anything - assertThrows(SQLException.class, () ->conn.createStatement()); + assertThrows(SQLException.class, conn::createStatement); try { stmt.executeQuery("SELECT 1"); @@ -84,20 +84,17 @@ public void testCreateUnsupportedStatements() throws Throwable { () -> conn.prepareStatement("SELECT 1", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE), () -> conn.prepareStatement("SELECT 1", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY), () -> conn.prepareStatement("SELECT 1", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT), - () -> conn.setSavepoint(), + conn::setSavepoint, () -> conn.setSavepoint("save point"), () -> conn.createStruct("simple", null), }; - int i = 0; for (Assert.ThrowingRunnable createStatement : createStatements) { - System.out.println("Failed at pos " + (i)); if (!flag) { Assert.assertThrows(SQLFeatureNotSupportedException.class, createStatement ); } else { createStatement.run(); } - i++; } } } @@ -145,8 +142,8 @@ public void setAutoCommitTest() throws SQLException { @Test(groups = { "integration" }) public void testCommitRollback() throws SQLException { try (Connection localConnection = this.getJdbcConnection()) { - assertThrows(SQLFeatureNotSupportedException.class, () -> localConnection.commit()); - assertThrows(SQLFeatureNotSupportedException.class, () -> localConnection.rollback()); + assertThrows(SQLFeatureNotSupportedException.class, localConnection::commit); + assertThrows(SQLFeatureNotSupportedException.class, localConnection::rollback); assertThrows(SQLFeatureNotSupportedException.class, () -> localConnection.rollback(null)); } @@ -231,7 +228,7 @@ public void clearWarningsTest() throws SQLException { @Test(groups = { "integration" }) public void getTypeMapTest() throws SQLException { Connection localConnection = this.getJdbcConnection(); - assertThrows(SQLFeatureNotSupportedException.class, () -> localConnection.getTypeMap()); + assertThrows(SQLFeatureNotSupportedException.class, localConnection::getTypeMap); } @Test(groups = { "integration" }) @@ -255,7 +252,7 @@ public void getHoldabilityTest() throws SQLException { @Test(groups = { "integration" }) public void setSavepointTest() throws SQLException { Connection localConnection = this.getJdbcConnection(); - assertThrows(SQLFeatureNotSupportedException.class, () -> localConnection.setSavepoint()); + assertThrows(SQLFeatureNotSupportedException.class, localConnection::setSavepoint); assertThrows(SQLFeatureNotSupportedException.class, () -> localConnection.setSavepoint("savepoint-name")); } @@ -316,7 +313,6 @@ public void setAndGetClientInfoTest(String clientName) throws SQLException { try (ResultSet rs = stmt.executeQuery(logQuery)) { Assert.assertTrue(rs.next()); String userAgent = rs.getString("http_user_agent"); - System.out.println(userAgent); if (clientName != null && !clientName.isEmpty()) { Assert.assertTrue(userAgent.startsWith(clientName), "Expected to start with '" + clientName + "' but value was '" + userAgent + "'"); } @@ -401,7 +397,7 @@ public void setNetworkTimeoutTest() throws SQLException { @Test(groups = { "integration" }) public void getNetworkTimeoutTest() throws SQLException { Connection localConnection = this.getJdbcConnection(); - assertThrows(SQLFeatureNotSupportedException.class, () -> localConnection.getNetworkTimeout()); + assertThrows(SQLFeatureNotSupportedException.class, localConnection::getNetworkTimeout); } @Test(groups = { "integration" }) 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 0cee1cfa6..fa45ab756 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java @@ -3,11 +3,11 @@ import com.clickhouse.client.api.ClientConfigProperties; import com.clickhouse.client.api.internal.ServerSettings; import com.clickhouse.client.api.query.GenericRecord; +import com.clickhouse.data.ClickHouseVersion; +import org.apache.commons.lang3.RandomStringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.Assert; -import com.clickhouse.data.ClickHouseVersion; -import org.apache.commons.lang3.RandomStringUtils; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -383,50 +383,50 @@ public void testSettingRole() throws SQLException { info.setProperty("password", userPass); try (ConnectionImpl conn = new ConnectionImpl(getEndpointString(), info)) { - GenericRecord record = conn.getClient().queryAll("SELECT currentRoles()").get(0); - assertEquals(record.getList(1).size(), 0); + GenericRecord dataRecord = conn.getClient().queryAll("SELECT currentRoles()").get(0); + assertEquals(dataRecord.getList(1).size(), 0); try (Statement stmt = conn.createStatement()) { stmt.execute("SET ROLE role1"); } - record = conn.getClient().queryAll("SELECT currentRoles()").get(0); - assertEquals(record.getList(1).size(), 1); - assertEquals(record.getList(1).get(0), "role1"); + dataRecord = conn.getClient().queryAll("SELECT currentRoles()").get(0); + assertEquals(dataRecord.getList(1).size(), 1); + assertEquals(dataRecord.getList(1).get(0), "role1"); try (Statement stmt = conn.createStatement()) { stmt.execute("SET ROLE role2"); } - record = conn.getClient().queryAll("SELECT currentRoles()").get(0); - assertEquals(record.getList(1).size(), 1); - assertEquals(record.getList(1).get(0), "role2"); + dataRecord = conn.getClient().queryAll("SELECT currentRoles()").get(0); + assertEquals(dataRecord.getList(1).size(), 1); + assertEquals(dataRecord.getList(1).get(0), "role2"); try (Statement stmt = conn.createStatement()) { stmt.execute("SET ROLE NONE"); } - record = conn.getClient().queryAll("SELECT currentRoles()").get(0); - assertEquals(record.getList(1).size(), 0); + dataRecord = conn.getClient().queryAll("SELECT currentRoles()").get(0); + assertEquals(dataRecord.getList(1).size(), 0); try (Statement stmt = conn.createStatement()) { stmt.execute("SET ROLE \"role1\",\"role2\""); } - record = conn.getClient().queryAll("SELECT currentRoles()").get(0); - assertEquals(record.getList(1).size(), 2); - assertEquals(record.getList(1).get(0), "role1"); - assertEquals(record.getList(1).get(1), "role2"); + dataRecord = conn.getClient().queryAll("SELECT currentRoles()").get(0); + assertEquals(dataRecord.getList(1).size(), 2); + assertEquals(dataRecord.getList(1).get(0), "role1"); + assertEquals(dataRecord.getList(1).get(1), "role2"); try (Statement stmt = conn.createStatement()) { stmt.execute("SET ROLE \"role1\",\"role2\",\"role3\""); } - record = conn.getClient().queryAll("SELECT currentRoles()").get(0); - assertEquals(record.getList(1).size(), 3); - assertEquals(record.getList(1).get(0), "role1"); - assertEquals(record.getList(1).get(1), "role2"); - assertEquals(record.getList(1).get(2), "role3"); + dataRecord = conn.getClient().queryAll("SELECT currentRoles()").get(0); + assertEquals(dataRecord.getList(1).size(), 3); + assertEquals(dataRecord.getList(1).get(0), "role1"); + assertEquals(dataRecord.getList(1).get(1), "role2"); + assertEquals(dataRecord.getList(1).get(2), "role3"); } } From c74f47d758babc0a69b2a2d813863838dbc36daa Mon Sep 17 00:00:00 2001 From: Sergey Chernov Date: Tue, 5 Aug 2025 07:11:12 -0700 Subject: [PATCH 3/3] reverted change in the changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88f55b816..ca4b16652 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ After the fix array values contain primitive types. (https://github.com/ClickHou ### Improvements - [jdbc-v2] Now using Antlr4 to parse SQL statements to get meta information about it. Invalid SQL still possible to execute if logic able to get all required information. (https://github.com/ClickHouse/clickhouse-java/pull/2351) -- [jdbc-v2] Now possible to use `RowBinaryWriter` if enabled by property `com.clickhouse.jdbc.DriverProperties.BETA_ROW_BINARY_WRITER`. +- [jdbc-v2] Now possible to use `RowBinaryWriter` if enabled by property `com.clickhouse.jdbc.internal.DriverProperties.BETA_ROW_BINARY_WRITER`. This works well for batches. Single statements may get no benefits. (https://github.com/ClickHouse/clickhouse-java/pull/2316) ### Bug Fixes