Skip to content

Commit 5d876e5

Browse files
committed
More prepared statement enhancements
This change implements a group of `Large` methods, like `executeLargeUpdate`, that were added in Java 8 (JDBC 4.2). Testing: existing prepared statement tests are moved to a separate file and updated to cover all `Large` methods. Fixes: duckdb#205
1 parent 9118691 commit 5d876e5

File tree

3 files changed

+422
-318
lines changed

3 files changed

+422
-318
lines changed

src/main/java/org/duckdb/DuckDBPreparedStatement.java

Lines changed: 87 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public class DuckDBPreparedStatement implements PreparedStatement {
4747
volatile boolean closeOnCompletion = false;
4848

4949
private DuckDBResultSet selectResult = null;
50-
private int updateResult = 0;
50+
private long updateResult = 0;
5151

5252
private boolean returnsChangedRows = false;
5353
private boolean returnsNothing = false;
@@ -188,7 +188,7 @@ private boolean execute(boolean startTransaction) throws SQLException {
188188

189189
if (returnsChangedRows) {
190190
if (selectResult.next()) {
191-
updateResult = selectResult.getInt(1);
191+
updateResult = selectResult.getLong(1);
192192
}
193193
selectResult.close();
194194
}
@@ -208,6 +208,12 @@ public ResultSet executeQuery() throws SQLException {
208208

209209
@Override
210210
public int executeUpdate() throws SQLException {
211+
long res = executeLargeUpdate();
212+
return intFromLong(res);
213+
}
214+
215+
@Override
216+
public long executeLargeUpdate() throws SQLException {
211217
requireNonBatch();
212218
execute();
213219
if (!(returnsChangedRows || returnsNothing)) {
@@ -232,8 +238,14 @@ public ResultSet executeQuery(String sql) throws SQLException {
232238

233239
@Override
234240
public int executeUpdate(String sql) throws SQLException {
241+
long res = executeLargeUpdate(sql);
242+
return intFromLong(res);
243+
}
244+
245+
@Override
246+
public long executeLargeUpdate(String sql) throws SQLException {
235247
prepare(sql);
236-
return executeUpdate();
248+
return executeLargeUpdate();
237249
}
238250

239251
@Override
@@ -377,12 +389,22 @@ public void setMaxFieldSize(int max) throws SQLException {
377389

378390
@Override
379391
public int getMaxRows() throws SQLException {
392+
return (int) getLargeMaxRows();
393+
}
394+
395+
@Override
396+
public void setMaxRows(int max) throws SQLException {
397+
setLargeMaxRows(max);
398+
}
399+
400+
@Override
401+
public long getLargeMaxRows() throws SQLException {
380402
checkOpen();
381403
return 0;
382404
}
383405

384406
@Override
385-
public void setMaxRows(int max) throws SQLException {
407+
public void setLargeMaxRows(long max) throws SQLException {
386408
checkOpen();
387409
}
388410

@@ -450,12 +472,14 @@ public ResultSet getResultSet() throws SQLException {
450472
return to_return;
451473
}
452474

453-
private Integer getUpdateCountInternal() throws SQLException {
475+
private long getUpdateCountInternal() throws SQLException {
454476
if (isClosed()) {
455477
throw new SQLException("Statement was closed");
456478
}
457479
if (stmtRef == null) {
458-
throw new SQLException("Prepare something first");
480+
// It is not required by JDBC spec to return anything in this case,
481+
// but clients can call this method before preparing/executing the query
482+
return -1;
459483
}
460484

461485
if (returnsResultSet || returnsNothing || selectResult.isFinished()) {
@@ -465,11 +489,17 @@ private Integer getUpdateCountInternal() throws SQLException {
465489
}
466490

467491
@Override
468-
public int getUpdateCount() throws SQLException {
492+
public long getLargeUpdateCount() throws SQLException {
469493
// getUpdateCount can only be called once per result
470-
int to_return = getUpdateCountInternal();
494+
long res = getUpdateCountInternal();
471495
updateResult = -1;
472-
return to_return;
496+
return res;
497+
}
498+
499+
@Override
500+
public int getUpdateCount() throws SQLException {
501+
long res = getLargeUpdateCount();
502+
return intFromLong(res);
473503
}
474504

475505
@Override
@@ -534,6 +564,12 @@ public void clearBatch() throws SQLException {
534564

535565
@Override
536566
public int[] executeBatch() throws SQLException {
567+
long[] res = executeLargeBatch();
568+
return intArrayFromLong(res);
569+
}
570+
571+
@Override
572+
public long[] executeLargeBatch() throws SQLException {
537573
checkOpen();
538574
try {
539575
if (this.isPreparedStatement) {
@@ -546,26 +582,26 @@ public int[] executeBatch() throws SQLException {
546582
}
547583
}
548584

549-
private int[] executeBatchedPreparedStatement() throws SQLException {
550-
int[] updateCounts = new int[this.batchedParams.size()];
585+
private long[] executeBatchedPreparedStatement() throws SQLException {
586+
long[] updateCounts = new long[this.batchedParams.size()];
551587

552588
startTransaction();
553589
for (int i = 0; i < this.batchedParams.size(); i++) {
554590
params = this.batchedParams.get(i);
555591
execute(false);
556-
updateCounts[i] = getUpdateCount();
592+
updateCounts[i] = getUpdateCountInternal();
557593
}
558594
return updateCounts;
559595
}
560596

561-
private int[] executeBatchedStatements() throws SQLException {
562-
int[] updateCounts = new int[this.batchedStatements.size()];
597+
private long[] executeBatchedStatements() throws SQLException {
598+
long[] updateCounts = new long[this.batchedStatements.size()];
563599

564600
startTransaction();
565601
for (int i = 0; i < this.batchedStatements.size(); i++) {
566602
prepare(this.batchedStatements.get(i));
567603
execute(false);
568-
updateCounts[i] = getUpdateCount();
604+
updateCounts[i] = getUpdateCountInternal();
569605
}
570606
return updateCounts;
571607
}
@@ -590,22 +626,40 @@ public ResultSet getGeneratedKeys() throws SQLException {
590626

591627
@Override
592628
public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
629+
long res = executeLargeUpdate(sql, autoGeneratedKeys);
630+
return intFromLong(res);
631+
}
632+
633+
@Override
634+
public long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
593635
if (NO_GENERATED_KEYS == autoGeneratedKeys) {
594-
return executeUpdate(sql);
636+
return executeLargeUpdate(sql);
595637
}
596638
throw new SQLFeatureNotSupportedException("executeUpdate(String sql, int autoGeneratedKeys)");
597639
}
598640

599641
@Override
600642
public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
643+
long res = executeLargeUpdate(sql, columnIndexes);
644+
return intFromLong(res);
645+
}
646+
647+
@Override
648+
public long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException {
601649
if (columnIndexes == null || columnIndexes.length == 0) {
602-
return executeUpdate(sql);
650+
return executeLargeUpdate(sql);
603651
}
604652
throw new SQLFeatureNotSupportedException("executeUpdate(String sql, int[] columnIndexes)");
605653
}
606654

607655
@Override
608656
public int executeUpdate(String sql, String[] columnNames) throws SQLException {
657+
long res = executeLargeUpdate(sql, columnNames);
658+
return intFromLong(res);
659+
}
660+
661+
@Override
662+
public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException {
609663
if (columnNames == null || columnNames.length == 0) {
610664
return executeUpdate(sql);
611665
}
@@ -1085,4 +1139,20 @@ private void setCharacterReaderInternal(int parameterIndex, Reader reader, long
10851139
String str = readToString(wrappedReader);
10861140
setObject(parameterIndex, str);
10871141
}
1142+
1143+
private int intFromLong(long val) {
1144+
if (val <= Integer.MAX_VALUE) {
1145+
return (int) val;
1146+
} else {
1147+
return Integer.MAX_VALUE;
1148+
}
1149+
}
1150+
1151+
private int[] intArrayFromLong(long[] arr) {
1152+
int[] res = new int[arr.length];
1153+
for (int i = 0; i < arr.length; i++) {
1154+
res[i] = intFromLong(arr[i]);
1155+
}
1156+
return res;
1157+
}
10881158
}

0 commit comments

Comments
 (0)