Skip to content

Commit 1cc71a2

Browse files
committed
fixed max rows. added check for execute method if they supported with specific parameters.
1 parent f78e975 commit 1cc71a2

File tree

5 files changed

+157
-58
lines changed

5 files changed

+157
-58
lines changed

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

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

3+
import com.clickhouse.client.api.internal.ServerSettings;
4+
35
import java.util.Collections;
46
import java.util.List;
57

@@ -35,6 +37,16 @@ public enum DriverProperties {
3537
* Enables closing result set before
3638
*/
3739
RESULTSET_AUTO_CLOSE("jdbc_resultset_auto_close", "true"),
40+
41+
/**
42+
* Enables using server property `max_result_rows` ({@link ServerSettings#MAX_RESULT_ROWS} to limit number of rows returned by query.
43+
* Enabling this property will override user set overflow mode. It may cause error if server doesn't allow changing properties.
44+
* When this property is not enabled then result set will stop reading data once limit is reached. As server may have
45+
* more in a result set then it will require time to read all data to make HTTP connection usable again. In most cases
46+
* this is fine. It is recommended to set limit in SQL query.
47+
*
48+
*/
49+
USE_MAX_RESULT_ROWS("jdbc_use_max_result_rows", "false"),
3850
;
3951

4052

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

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ public class ResultSetImpl implements ResultSet, JdbcV2Wrapper {
5757
private int rowPos;
5858

5959
private int fetchSize;
60+
private int fetchDirection;
61+
final private int maxFieldSize;
62+
final private int maxRows;
6063

6164
private Consumer<Exception> onDataTransferException;
6265

@@ -77,6 +80,9 @@ public ResultSetImpl(StatementImpl parentStatement, QueryResponse response, Clic
7780
this.defaultCalendar = parentStatement.getConnection().defaultCalendar;
7881
this.rowPos = BEFORE_FIRST;
7982
this.fetchSize = parentStatement.getFetchSize();
83+
this.fetchDirection = parentStatement.getFetchDirection();
84+
this.maxFieldSize = parentStatement.getMaxFieldSize();
85+
this.maxRows = parentStatement.getMaxRows();
8086
this.onDataTransferException = onDataTransferException;
8187
}
8288

@@ -103,6 +109,15 @@ private String columnIndexToName(int index) throws SQLException {
103109
public boolean next() throws SQLException {
104110
checkClosed();
105111

112+
if (rowPos == AFTER_LAST) {
113+
return false;
114+
}
115+
116+
if (maxRows > 0 && rowPos == maxRows) {
117+
rowPos = AFTER_LAST;
118+
return false;
119+
}
120+
106121
try {
107122
Object readerRow = reader.next();
108123
if (readerRow != null) {
@@ -543,7 +558,7 @@ public boolean isFirst() throws SQLException {
543558
@Override
544559
public boolean isLast() throws SQLException {
545560
checkClosed();
546-
return !reader.hasNext() && rowPos != AFTER_LAST && rowPos != BEFORE_FIRST;
561+
return (!reader.hasNext() || rowPos == maxRows) && rowPos != AFTER_LAST && rowPos != BEFORE_FIRST;
547562
}
548563

549564
@Override
@@ -607,15 +622,16 @@ public boolean previous() throws SQLException {
607622
@Override
608623
public int getFetchDirection() throws SQLException {
609624
checkClosed();
610-
return FETCH_FORWARD;
625+
return fetchDirection;
611626
}
612627

613628
@Override
614629
public void setFetchDirection(int direction) throws SQLException {
615630
checkClosed();
616-
if (direction != ResultSet.FETCH_FORWARD) {
631+
if (getType() == TYPE_FORWARD_ONLY && direction != ResultSet.FETCH_FORWARD) {
617632
throw new SQLException("This result set object is of FORWARD ONLY type. Only ResultSet.FETCH_FORWARD is allowed as fetchDirection.");
618633
}
634+
fetchDirection = direction;
619635
}
620636

621637
@Override

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

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.clickhouse.client.api.query.QuerySettings;
88
import com.clickhouse.client.api.sql.SQLUtils;
99
import com.clickhouse.jdbc.internal.ExceptionUtils;
10+
import com.clickhouse.jdbc.internal.FeatureManager;
1011
import com.clickhouse.jdbc.internal.ParsedStatement;
1112
import org.slf4j.Logger;
1213
import org.slf4j.LoggerFactory;
@@ -29,6 +30,7 @@ public class StatementImpl implements Statement, JdbcV2Wrapper {
2930
ConnectionImpl connection;
3031
protected int queryTimeout;
3132
protected boolean isPoolable = false; // Statement is not poolable by default
33+
private final FeatureManager featureManager;
3234

3335
// State
3436
private volatile boolean closed;
@@ -60,6 +62,7 @@ public StatementImpl(ConnectionImpl connection) throws SQLException {
6062
this.resultSets= new ConcurrentLinkedQueue<>();
6163
this.resultSetAutoClose = connection.getJdbcConfig().isSet(DriverProperties.RESULTSET_AUTO_CLOSE);
6264
this.escapeProcessingEnabled = true;
65+
this.featureManager = new FeatureManager(connection.getJdbcConfig());
6366
}
6467

6568
protected void ensureOpen() throws SQLException {
@@ -458,22 +461,22 @@ public boolean getMoreResults(int current) throws SQLException {
458461
return false; // false indicates that no more results (or it is an update count)
459462
}
460463

461-
// @Override
464+
// @Override -- because doesn't exist in Java 8
462465
public String enquoteLiteral(String val) throws SQLException {
463466
return SQLUtils.enquoteLiteral(val);
464467
}
465468

466-
// @Override
469+
// @Override -- because doesn't exist in Java 8
467470
public String enquoteIdentifier(String identifier, boolean alwaysQuote) throws SQLException {
468471
return SQLUtils.enquoteIdentifier(identifier, alwaysQuote);
469472
}
470473

471-
// @Override
474+
// @Override -- because doesn't exist in Java 8
472475
public boolean isSimpleIdentifier(String identifier) throws SQLException {
473476
return SQLUtils.isSimpleIdentifier(identifier);
474477
}
475478

476-
// @Override
479+
// @Override -- because doesn't exist in Java 8
477480
public String enquoteNCharLiteral(String val) throws SQLException {
478481
if (val == null) {
479482
throw new NullPointerException();
@@ -489,31 +492,37 @@ public ResultSet getGeneratedKeys() throws SQLException {
489492

490493
@Override
491494
public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
495+
featureManager.unsupportedFeatureThrow("executeUpdate(String, int)", autoGeneratedKeys != Statement.NO_GENERATED_KEYS);
492496
return executeUpdate(sql);
493497
}
494498

495499
@Override
496500
public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
501+
featureManager.unsupportedFeatureThrow("executeUpdate(String, int[])");
497502
return executeUpdate(sql);
498503
}
499504

500505
@Override
501506
public int executeUpdate(String sql, String[] columnNames) throws SQLException {
507+
featureManager.unsupportedFeatureThrow("executeUpdate(String, String[])");
502508
return executeUpdate(sql);
503509
}
504510

505511
@Override
506512
public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
513+
featureManager.unsupportedFeatureThrow("execute(String, int)", autoGeneratedKeys != Statement.NO_GENERATED_KEYS);
507514
return execute(sql);
508515
}
509516

510517
@Override
511518
public boolean execute(String sql, int[] columnIndexes) throws SQLException {
519+
featureManager.unsupportedFeatureThrow("execute(String, int[])");
512520
return execute(sql);
513521
}
514522

515523
@Override
516524
public boolean execute(String sql, String[] columnNames) throws SQLException {
525+
featureManager.unsupportedFeatureThrow("execute(String, String[])");
517526
return execute(sql);
518527
}
519528

@@ -573,20 +582,23 @@ public long getLargeUpdateCount() throws SQLException {
573582
public void setLargeMaxRows(long max) throws SQLException {
574583
ensureOpen();
575584
maxRows = max;
576-
// This method override user set overflow mode on purpose:
577-
// 1. Spec clearly states that after calling this method with a limit > 0 all rows over limit are dropped.
578-
// 2. Calling this method should not cause throwing exception for future queries what only `break` can guarantee
579-
// 3. If user wants different behavior then they are can use connection properties.
580-
if (max > 0) {
581-
localSettings.setOption(ClientConfigProperties.serverSetting(ServerSettings.MAX_RESULT_ROWS), maxRows);
582-
localSettings.setOption(ClientConfigProperties.serverSetting(ServerSettings.RESULT_OVERFLOW_MODE),
583-
ServerSettings.RESULT_OVERFLOW_MODE_BREAK);
584-
} else {
585-
// overriding potential client settings (set thru connection setup)
586-
// there is no no limit value so we use very large limit.
587-
localSettings.setOption(ClientConfigProperties.serverSetting(ServerSettings.MAX_RESULT_ROWS), Long.MAX_VALUE);
588-
localSettings.setOption(ClientConfigProperties.serverSetting(ServerSettings.RESULT_OVERFLOW_MODE),
589-
ServerSettings.RESULT_OVERFLOW_MODE_BREAK);
585+
586+
if (connection.getJdbcConfig().isFlagSet(DriverProperties.USE_MAX_RESULT_ROWS)) {
587+
// This method override user set overflow mode on purpose:
588+
// 1. Spec clearly states that after calling this method with a limit > 0 all rows over limit are dropped.
589+
// 2. Calling this method should not cause throwing exception for future queries what only `break` can guarantee
590+
// 3. If user wants different behavior then they are can use connection properties.
591+
if (max > 0) {
592+
localSettings.setOption(ClientConfigProperties.serverSetting(ServerSettings.MAX_RESULT_ROWS), maxRows);
593+
localSettings.setOption(ClientConfigProperties.serverSetting(ServerSettings.RESULT_OVERFLOW_MODE),
594+
ServerSettings.RESULT_OVERFLOW_MODE_BREAK);
595+
} else {
596+
// overriding potential client settings (set thru connection setup)
597+
// there is no no limit value so we use very large limit.
598+
localSettings.setOption(ClientConfigProperties.serverSetting(ServerSettings.MAX_RESULT_ROWS), Long.MAX_VALUE);
599+
localSettings.setOption(ClientConfigProperties.serverSetting(ServerSettings.RESULT_OVERFLOW_MODE),
600+
ServerSettings.RESULT_OVERFLOW_MODE_BREAK);
601+
}
590602
}
591603
}
592604

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,10 @@ public static String getDefaultClientName() {
309309
}
310310

311311
public boolean isBetaFeatureEnabled(DriverProperties prop) {
312+
return isFlagSet(prop);
313+
}
314+
315+
public boolean isFlagSet(DriverProperties prop) {
312316
String value = driverProperties.getOrDefault(prop.getKey(), prop.getDefaultValue());
313317
return Boolean.parseBoolean(value);
314318
}
@@ -318,4 +322,8 @@ private Map<ClickHouseDataType, Class<?>> defaultTypeHintMapping() {
318322
mapping.put(ClickHouseDataType.Array, List.class);
319323
return mapping;
320324
}
325+
326+
public boolean useMaxResultRows() {
327+
return isFlagSet(DriverProperties.USE_MAX_RESULT_ROWS);
328+
}
321329
}

0 commit comments

Comments
 (0)