Skip to content

Commit 48ce367

Browse files
committed
Merge branch 'main' into jdbc_v2_row_binary_writer
2 parents c11a581 + 49d5322 commit 48ce367

File tree

8 files changed

+265
-48
lines changed

8 files changed

+265
-48
lines changed

client-v2/src/main/java/com/clickhouse/client/api/Client.java

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -192,16 +192,24 @@ private Client(Set<String> endpoints, Map<String,String> configuration, boolean
192192
*
193193
*/
194194
public void loadServerInfo() {
195-
try (QueryResponse response = this.query("SELECT currentUser() AS user, timezone() AS timezone, version() AS version LIMIT 1").get()) {
196-
try (ClickHouseBinaryFormatReader reader = this.newBinaryFormatReader(response)) {
197-
if (reader.next() != null) {
198-
this.configuration.put(ClientConfigProperties.USER.getKey(), reader.getString("user"));
199-
this.configuration.put(ClientConfigProperties.SERVER_TIMEZONE.getKey(), reader.getString("timezone"));
200-
serverVersion = reader.getString("version");
195+
// only if 2 properties are set disable retrieval from server
196+
if (!this.configuration.containsKey(ClientConfigProperties.SERVER_TIMEZONE.getKey()) && !this.configuration.containsKey(ClientConfigProperties.SERVER_VERSION.getKey())) {
197+
try (QueryResponse response = this.query("SELECT currentUser() AS user, timezone() AS timezone, version() AS version LIMIT 1").get()) {
198+
try (ClickHouseBinaryFormatReader reader = this.newBinaryFormatReader(response)) {
199+
if (reader.next() != null) {
200+
this.configuration.put(ClientConfigProperties.USER.getKey(), reader.getString("user"));
201+
this.configuration.put(ClientConfigProperties.SERVER_TIMEZONE.getKey(), reader.getString("timezone"));
202+
serverVersion = reader.getString("version");
203+
}
201204
}
205+
} catch (Exception e) {
206+
throw new ClientException("Failed to get server info", e);
207+
}
208+
} else {
209+
LOG.info("Using server version " + this.configuration.get(ClientConfigProperties.SERVER_VERSION.getKey()) + " and timezone " + this.configuration.get(ClientConfigProperties.SERVER_TIMEZONE.getKey()) );
210+
if (this.configuration.containsKey(ClientConfigProperties.SERVER_VERSION.getKey())) {
211+
serverVersion = this.configuration.get(ClientConfigProperties.SERVER_VERSION.getKey());
202212
}
203-
} catch (Exception e) {
204-
throw new ClientException("Failed to get server info", e);
205213
}
206214
}
207215

@@ -991,6 +999,17 @@ public Builder registerClientMetrics(Object registry, String name) {
991999
return this;
9921000
}
9931001

1002+
/**
1003+
* Sets server version that the client is interacting with.
1004+
*
1005+
* @param serverVersion - ClickHouse server version
1006+
* @return same instance of the builder
1007+
*/
1008+
public Builder setServerVersion(String serverVersion) {
1009+
this.configuration.put(ClientConfigProperties.SERVER_VERSION.getKey(), serverVersion);
1010+
return this;
1011+
}
1012+
9941013
public Client build() {
9951014
setDefaults();
9961015

@@ -2174,6 +2193,10 @@ public String getServerVersion() {
21742193
return this.serverVersion;
21752194
}
21762195

2196+
public String getServerTimeZone() {
2197+
return this.configuration.get(ClientConfigProperties.SERVER_TIMEZONE.getKey());
2198+
}
2199+
21772200
public String getClientVersion() {
21782201
return clientVersion;
21792202
}

client-v2/src/main/java/com/clickhouse/client/api/ClientConfigProperties.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ public enum ClientConfigProperties {
3636

3737
USE_TIMEZONE("use_time_zone"),
3838

39+
SERVER_VERSION("server_version"),
40+
3941
SERVER_TIMEZONE("server_time_zone"),
4042

4143
ASYNC_OPERATIONS("async"),

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

Lines changed: 137 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.clickhouse.jdbc;
22

33
import com.clickhouse.client.api.metadata.TableSchema;
4+
import com.clickhouse.client.api.query.QuerySettings;
45
import com.clickhouse.data.Tuple;
56
import com.clickhouse.jdbc.internal.ExceptionUtils;
67
import com.clickhouse.jdbc.internal.JdbcUtils;
@@ -113,13 +114,14 @@ private String compileSql(String []segments) {
113114
@Override
114115
public ResultSet executeQuery() throws SQLException {
115116
checkClosed();
116-
return executeQuery(compileSql(sqlSegments));
117+
return super.executeQueryImpl(compileSql(sqlSegments), new QuerySettings().setDatabase(connection.getSchema()));
117118
}
118119

119120
@Override
120121
public int executeUpdate() throws SQLException {
121122
checkClosed();
122-
return executeUpdate(compileSql(sqlSegments));
123+
return super.executeUpdateImpl(compileSql(sqlSegments), statementType,
124+
new QuerySettings().setDatabase(connection.getSchema()));
123125
}
124126

125127
@Override
@@ -246,17 +248,18 @@ public void setObject(int parameterIndex, Object x) throws SQLException {
246248
@Override
247249
public boolean execute() throws SQLException {
248250
checkClosed();
249-
return execute(compileSql(sqlSegments));
251+
return super.executeImpl(compileSql(sqlSegments), statementType,
252+
new QuerySettings().setDatabase(connection.getSchema()));
250253
}
251254

252255
@Override
253256
public void addBatch() throws SQLException {
254257
checkClosed();
255258
if (statementType == StatementParser.StatementType.INSERT) {
256259
// adding values to the end of big INSERT statement.
257-
addBatch(compileSql(valueSegments));
260+
super.addBatch(compileSql(valueSegments));
258261
} else {
259-
addBatch(compileSql(sqlSegments));
262+
super.addBatch(compileSql(sqlSegments));
260263
}
261264
}
262265

@@ -271,7 +274,8 @@ public int[] executeBatch() throws SQLException {
271274
sb.append(sql).append(",");
272275
}
273276
sb.setCharAt(sb.length() - 1, ';');
274-
int rowsInserted = executeUpdate(sb.toString());
277+
int rowsInserted = executeUpdateImpl(sb.toString(), statementType,
278+
new QuerySettings().setDatabase(connection.getSchema()));
275279
// clear batch and re-add insert into
276280
int[] results = new int[batch.size()];
277281
if (rowsInserted == batch.size()) {
@@ -286,18 +290,22 @@ public int[] executeBatch() throws SQLException {
286290
return results;
287291
} else {
288292
// run executeBatch
289-
return super.executeBatch();
293+
return executeBatchImpl().stream().mapToInt(Integer::intValue).toArray();
290294
}
291295
}
292296

293297
@Override
294298
public long[] executeLargeBatch() throws SQLException {
295-
int[] results = executeBatch();
296-
long[] longResults = new long[results.length];
297-
for (int i = 0; i < results.length; i++) {
298-
longResults[i] = results[i];
299+
return executeBatchImpl().stream().mapToLong(Integer::longValue).toArray();
300+
}
301+
302+
private List<Integer> executeBatchImpl() throws SQLException {
303+
List<Integer> results = new ArrayList<>();
304+
QuerySettings settings = new QuerySettings().setDatabase(connection.getSchema());
305+
for (String sql : batch) {
306+
results.add(executeUpdateImpl(sql, statementType, settings));
299307
}
300-
return longResults;
308+
return results;
301309
}
302310

303311
@Override
@@ -434,7 +442,8 @@ public ParameterMetaData getParameterMetaData() throws SQLException {
434442
@Override
435443
public void setRowId(int parameterIndex, RowId x) throws SQLException {
436444
checkClosed();
437-
parameters[parameterIndex - 1] = encodeObject(x);
445+
throw new SQLException("ROWID type is not supported by ClickHouse.",
446+
ExceptionUtils.SQL_STATE_FEATURE_NOT_SUPPORTED);
438447
}
439448

440449
@Override
@@ -562,6 +571,118 @@ public long executeLargeUpdate() throws SQLException {
562571
return executeUpdate();
563572
}
564573

574+
@Override
575+
public final void addBatch(String sql) throws SQLException {
576+
checkClosed();
577+
throw new SQLException(
578+
"addBatch(String) cannot be called in PreparedStatement or CallableStatement!",
579+
ExceptionUtils.SQL_STATE_WRONG_OBJECT_TYPE);
580+
}
581+
582+
@Override
583+
public final boolean execute(String sql) throws SQLException {
584+
checkClosed();
585+
throw new SQLException(
586+
"execute(String) cannot be called in PreparedStatement or CallableStatement!",
587+
ExceptionUtils.SQL_STATE_WRONG_OBJECT_TYPE);
588+
}
589+
590+
@Override
591+
public final boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
592+
checkClosed();
593+
throw new SQLException(
594+
"execute(String, int) cannot be called in PreparedStatement or CallableStatement!",
595+
ExceptionUtils.SQL_STATE_WRONG_OBJECT_TYPE);
596+
}
597+
598+
@Override
599+
public final boolean execute(String sql, int[] columnIndexes) throws SQLException {
600+
checkClosed();
601+
throw new SQLException(
602+
"execute(String, int[]) cannot be called in PreparedStatement or CallableStatement!",
603+
ExceptionUtils.SQL_STATE_WRONG_OBJECT_TYPE);
604+
}
605+
606+
@Override
607+
public final boolean execute(String sql, String[] columnNames) throws SQLException {
608+
checkClosed();
609+
throw new SQLException(
610+
"execute(String, String[]) cannot be called in PreparedStatement or CallableStatement!",
611+
ExceptionUtils.SQL_STATE_WRONG_OBJECT_TYPE);
612+
}
613+
614+
@Override
615+
public final long executeLargeUpdate(String sql) throws SQLException {
616+
checkClosed();
617+
throw new SQLException(
618+
"executeLargeUpdate(String) cannot be called in PreparedStatement or CallableStatement!",
619+
ExceptionUtils.SQL_STATE_WRONG_OBJECT_TYPE);
620+
}
621+
622+
@Override
623+
public final long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
624+
checkClosed();
625+
throw new SQLException(
626+
"executeLargeUpdate(String, int) cannot be called in PreparedStatement or CallableStatement!",
627+
ExceptionUtils.SQL_STATE_WRONG_OBJECT_TYPE);
628+
}
629+
630+
@Override
631+
public final long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException {
632+
checkClosed();
633+
throw new SQLException(
634+
"executeLargeUpdate(String, int[]) cannot be called in PreparedStatement or CallableStatement!",
635+
ExceptionUtils.SQL_STATE_WRONG_OBJECT_TYPE);
636+
}
637+
638+
@Override
639+
public final long executeLargeUpdate(String sql, String[] columnNames) throws SQLException {
640+
checkClosed();
641+
throw new SQLException(
642+
"executeLargeUpdate(String, String[]) cannot be called in PreparedStatement or CallableStatement!",
643+
ExceptionUtils.SQL_STATE_WRONG_OBJECT_TYPE);
644+
}
645+
646+
@Override
647+
public final ResultSet executeQuery(String sql) throws SQLException {
648+
checkClosed();
649+
throw new SQLException(
650+
"executeQuery(String) cannot be called in PreparedStatement or CallableStatement!",
651+
ExceptionUtils.SQL_STATE_WRONG_OBJECT_TYPE);
652+
}
653+
654+
@Override
655+
public final int executeUpdate(String sql) throws SQLException {
656+
checkClosed();
657+
throw new SQLException(
658+
"executeUpdate(String) cannot be called in PreparedStatement or CallableStatement!",
659+
ExceptionUtils.SQL_STATE_WRONG_OBJECT_TYPE);
660+
}
661+
662+
@Override
663+
public final int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
664+
checkClosed();
665+
throw new SQLException(
666+
"executeUpdate(String, int) cannot be called in PreparedStatement or CallableStatement!",
667+
ExceptionUtils.SQL_STATE_WRONG_OBJECT_TYPE);
668+
}
669+
670+
@Override
671+
public final int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
672+
checkClosed();
673+
throw new SQLException(
674+
"executeUpdate(String, int[]) cannot be called in PreparedStatement or CallableStatement!",
675+
ExceptionUtils.SQL_STATE_WRONG_OBJECT_TYPE);
676+
}
677+
678+
@Override
679+
public final int executeUpdate(String sql, String[] columnNames) throws SQLException {
680+
checkClosed();
681+
throw new SQLException(
682+
"executeUpdate(String, String[]) cannot be called in PreparedStatement or CallableStatement!",
683+
ExceptionUtils.SQL_STATE_WRONG_OBJECT_TYPE);
684+
}
685+
565686
private static String encodeObject(Object x) throws SQLException {
566687
LOG.trace("Encoding object: {}", x);
567688

@@ -612,7 +733,9 @@ private static String encodeObject(Object x) throws SQLException {
612733
for (Object item : (Collection<?>) x) {
613734
listString.append(encodeObject(item)).append(", ");
614735
}
615-
listString.delete(listString.length() - 2, listString.length());
736+
if (listString.length() > 1) {
737+
listString.delete(listString.length() - 2, listString.length());
738+
}
616739
listString.append("]");
617740

618741
return listString.toString();

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

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ protected String getLastSql() {
8686
@Override
8787
public ResultSet executeQuery(String sql) throws SQLException {
8888
checkClosed();
89-
return executeQuery(sql, new QuerySettings().setDatabase(schema));
89+
return executeQueryImpl(sql, new QuerySettings().setDatabase(schema));
9090
}
9191

9292
private void closePreviousResultSet() {
@@ -103,7 +103,7 @@ private void closePreviousResultSet() {
103103
}
104104
}
105105

106-
private ResultSetImpl executeQuery(String sql, QuerySettings settings) throws SQLException {
106+
private ResultSetImpl executeQueryImpl(String sql, QuerySettings settings) throws SQLException {
107107
checkClosed();
108108
// Closing before trying to do next request. Otherwise, deadlock because previous connection will not be
109109
// release before this one completes.
@@ -151,11 +151,10 @@ private ResultSetImpl executeQuery(String sql, QuerySettings settings) throws SQ
151151
@Override
152152
public int executeUpdate(String sql) throws SQLException {
153153
checkClosed();
154-
return executeUpdate(sql, new QuerySettings().setDatabase(schema));
154+
return executeUpdateImpl(sql, parseStatementType(sql), new QuerySettings().setDatabase(schema));
155155
}
156156

157-
public int executeUpdate(String sql, QuerySettings settings) throws SQLException {
158-
// TODO: close current result set?
157+
protected int executeUpdateImpl(String sql, StatementType type, QuerySettings settings) throws SQLException {
159158
checkClosed();
160159
StatementParser.StatementType type = StatementParser.parsedStatement(sql).getType();
161160
if (type == StatementParser.StatementType.SELECT || type == StatementParser.StatementType.SHOW
@@ -283,10 +282,10 @@ public void setCursorName(String name) throws SQLException {
283282
@Override
284283
public boolean execute(String sql) throws SQLException {
285284
checkClosed();
286-
return execute(sql, new QuerySettings().setDatabase(schema));
285+
return executeImpl(sql, parseStatementType(sql), new QuerySettings().setDatabase(schema));
287286
}
288287

289-
public boolean execute(String sql, QuerySettings settings) throws SQLException {
288+
public boolean executeImpl(String sql, StatementType type, QuerySettings settings) throws SQLException {
290289
checkClosed();
291290
StatementParser.ParsedStatement parsedStatement = StatementParser.parsedStatement(sql);
292291
StatementParser.StatementType type = parsedStatement.getType();
@@ -298,7 +297,7 @@ public boolean execute(String sql, QuerySettings settings) throws SQLException {
298297
currentResultSet = executeQuery(sql, settings); // keep open to allow getResultSet()
299298
return true;
300299
} else if(type == StatementParser.StatementType.SET) {
301-
executeUpdate(sql, settings);
300+
executeUpdateImpl(sql, type, settings);
302301
//SET ROLE
303302
List<String> tokens = JdbcUtils.tokenizeSQL(sql);
304303
if (JdbcUtils.containsIgnoresCase(tokens, "ROLE")) {
@@ -322,14 +321,14 @@ public boolean execute(String sql, QuerySettings settings) throws SQLException {
322321
}
323322
return false;
324323
} else if (type == StatementParser.StatementType.USE) {
325-
executeUpdate(sql, settings);
324+
executeUpdateImpl(sql, type, settings);
326325
//USE Database
327326
List<String> tokens = JdbcUtils.tokenizeSQL(sql);
328327
this.schema = tokens.get(1).replace("\"", "");
329328
LOG.debug("Changed statement schema {}", schema);
330329
return false;
331330
} else {
332-
executeUpdate(sql, settings);
331+
executeUpdateImpl(sql, type, settings);
333332
return false;
334333
}
335334
}

jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/ExceptionUtils.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ public final class ExceptionUtils {
2424
public static final String SQL_STATE_INVALID_SCHEMA = "3F000";
2525
public static final String SQL_STATE_INVALID_TX_STATE = "25000";
2626
public static final String SQL_STATE_DATA_EXCEPTION = "22000";
27+
// Used only when feature is not supported
2728
public static final String SQL_STATE_FEATURE_NOT_SUPPORTED = "0A000";
29+
// Used only when method is called on wrong object type (for example, PreparedStatement.addBatch(String))
30+
public static final String SQL_STATE_WRONG_OBJECT_TYPE = "42809";
2831

2932
private ExceptionUtils() {}//Private constructor
3033

0 commit comments

Comments
 (0)