Skip to content

Commit 762ce2f

Browse files
committed
Support Statement.closeOnCompletion.
Check a statement after all its dependent result set are closed. Extract TarantoolStatement as tarantool specific extension interface to be used for internal purposes (incompatible vendor API). Closes: #180
1 parent 9f877a5 commit 762ce2f

9 files changed

+212
-34
lines changed

Diff for: src/main/java/org/tarantool/jdbc/SQLDatabaseMetadata.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -1126,8 +1126,8 @@ private SQLNullResultSet sqlNullResultSet(List<String> columnNames, List<List<Ob
11261126
return new SQLNullResultSet(SQLResultHolder.ofQuery(meta, rows), createMetadataStatement());
11271127
}
11281128

1129-
private SQLStatement createMetadataStatement() throws SQLException {
1130-
return connection.createStatement().unwrap(SQLStatement.class);
1129+
private TarantoolStatement createMetadataStatement() throws SQLException {
1130+
return connection.createStatement().unwrap(TarantoolStatement.class);
11311131
}
11321132

11331133
private static <T> T ensureType(Class<T> cls, Object v) throws Exception {
@@ -1152,7 +1152,7 @@ private SQLNullResultSet emptyResultSet(List<String> colNames) throws SQLExcepti
11521152

11531153
protected class SQLNullResultSet extends SQLResultSet {
11541154

1155-
public SQLNullResultSet(SQLResultHolder holder, SQLStatement ownerStatement) throws SQLException {
1155+
public SQLNullResultSet(SQLResultHolder holder, TarantoolStatement ownerStatement) throws SQLException {
11561156
super(holder, ownerStatement);
11571157
}
11581158

Diff for: src/main/java/org/tarantool/jdbc/SQLResultSet.java

+14-6
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@
3838

3939
public class SQLResultSet implements ResultSet {
4040

41-
private final CursorIterator<List<Object>> iterator;
42-
private final SQLResultSetMetaData metaData;
41+
private CursorIterator<List<Object>> iterator;
42+
private SQLResultSetMetaData metaData;
4343

4444
private Map<String, Integer> columnByNameLookups;
4545
private boolean lastColumnWasNull;
4646

47-
private final Statement statement;
47+
private final TarantoolStatement statement;
4848
private final int maxRows;
4949

5050
private AtomicBoolean isClosed = new AtomicBoolean(false);
@@ -53,7 +53,7 @@ public class SQLResultSet implements ResultSet {
5353
private final int concurrencyLevel;
5454
private final int holdability;
5555

56-
public SQLResultSet(SQLResultHolder holder, SQLStatement ownerStatement) throws SQLException {
56+
public SQLResultSet(SQLResultHolder holder, TarantoolStatement ownerStatement) throws SQLException {
5757
metaData = new SQLResultSetMetaData(holder.getSqlMetadata());
5858
statement = ownerStatement;
5959
scrollType = statement.getResultSetType();
@@ -108,7 +108,13 @@ protected Number getNullableNumber(int columnIndex) throws SQLException {
108108
@Override
109109
public void close() throws SQLException {
110110
if (isClosed.compareAndSet(false, true)) {
111-
iterator.close();
111+
try {
112+
iterator.close();
113+
iterator = null;
114+
metaData = null;
115+
} finally {
116+
statement.checkCompletion();
117+
}
112118
}
113119
}
114120

@@ -393,11 +399,13 @@ public String getCursorName() throws SQLException {
393399

394400
@Override
395401
public ResultSetMetaData getMetaData() throws SQLException {
402+
checkNotClosed();
396403
return metaData;
397404
}
398405

399406
@Override
400407
public int findColumn(String columnLabel) throws SQLException {
408+
checkNotClosed();
401409
return findColumnIndex(columnLabel);
402410
}
403411

@@ -1122,7 +1130,7 @@ public <T> T unwrap(Class<T> type) throws SQLException {
11221130
if (isWrapperFor(type)) {
11231131
return type.cast(this);
11241132
}
1125-
throw new SQLNonTransientException("ResultSet does not wrap " + type.getName());
1133+
throw new SQLNonTransientException("SQLResultSet does not wrap " + type.getName());
11261134
}
11271135

11281136
@Override

Diff for: src/main/java/org/tarantool/jdbc/SQLStatement.java

+34-17
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
* types of cursors.
2222
* Supports only {@link ResultSet#HOLD_CURSORS_OVER_COMMIT} holdability type.
2323
*/
24-
public class SQLStatement implements Statement {
24+
public class SQLStatement implements TarantoolStatement {
2525

2626
protected final SQLConnection connection;
2727

@@ -31,6 +31,8 @@ public class SQLStatement implements Statement {
3131
protected SQLResultSet resultSet;
3232
protected int updateCount;
3333

34+
private boolean isCloseOnCompletion;
35+
3436
private final int resultSetType;
3537
private final int resultSetConcurrency;
3638
private final int resultSetHoldability;
@@ -310,23 +312,44 @@ public boolean isPoolable() throws SQLException {
310312
throw new SQLFeatureNotSupportedException();
311313
}
312314

315+
/**
316+
* {@inheritDoc}
317+
* <p>
318+
* <strong>Impl Note:</strong> this method doesn't affect
319+
* execution methods which close the last result set implicitly.
320+
* It is applied only when {@link ResultSet#close()} is invoked
321+
* explicitly by the app.
322+
*
323+
* @throws SQLException if this method is called on a closed
324+
* {@code Statement}
325+
*/
313326
@Override
314327
public void closeOnCompletion() throws SQLException {
315-
328+
checkNotClosed();
329+
isCloseOnCompletion = true;
316330
}
317331

318332
@Override
319333
public boolean isCloseOnCompletion() throws SQLException {
320334
checkNotClosed();
321-
return false;
335+
return isCloseOnCompletion;
336+
}
337+
338+
@Override
339+
public void checkCompletion() throws SQLException {
340+
if (isCloseOnCompletion &&
341+
resultSet != null &&
342+
resultSet.isClosed()) {
343+
close();
344+
}
322345
}
323346

324347
@Override
325348
public <T> T unwrap(Class<T> type) throws SQLException {
326349
if (isWrapperFor(type)) {
327350
return type.cast(this);
328351
}
329-
throw new SQLNonTransientException("Statement does not wrap " + type.getName());
352+
throw new SQLNonTransientException("SQLStatement does not wrap " + type.getName());
330353
}
331354

332355
@Override
@@ -338,15 +361,18 @@ public boolean isWrapperFor(Class<?> type) throws SQLException {
338361
* Clears the results of the most recent execution.
339362
*/
340363
protected void discardLastResults() throws SQLException {
364+
final SQLResultSet lastResultSet = resultSet;
365+
341366
clearWarnings();
342367
updateCount = -1;
343-
if (resultSet != null) {
368+
resultSet = null;
369+
370+
if (lastResultSet != null) {
344371
try {
345-
resultSet.close();
372+
lastResultSet.close();
346373
} catch (Exception ignored) {
347374
// No-op.
348375
}
349-
resultSet = null;
350376
}
351377
}
352378

@@ -375,16 +401,7 @@ protected boolean executeInternal(String sql, Object... params) throws SQLExcept
375401
return holder.isQueryResult();
376402
}
377403

378-
/**
379-
* Returns {@link ResultSet} which will be initialized by <code>data</code>.
380-
*
381-
* @param data predefined result to be wrapped by {@link ResultSet}
382-
*
383-
* @return wrapped result
384-
*
385-
* @throws SQLException if a database access error occurs or
386-
* this method is called on a closed <code>Statement</code>
387-
*/
404+
@Override
388405
public ResultSet executeMetadata(SQLResultHolder data) throws SQLException {
389406
checkNotClosed();
390407
return createResultSet(data);
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package org.tarantool.jdbc;
2+
3+
import java.sql.ResultSet;
4+
import java.sql.SQLException;
5+
import java.sql.Statement;
6+
7+
/**
8+
* Tarantool specific statement extensions.
9+
*/
10+
public interface TarantoolStatement extends Statement {
11+
12+
/**
13+
* Checks for statement completion and closes itself,
14+
* according to {@link Statement#closeOnCompletion()}.
15+
*/
16+
void checkCompletion() throws SQLException;
17+
18+
/**
19+
* Returns {@link ResultSet} which will be initialized by <code>data</code>.
20+
*
21+
* @param data predefined result to be wrapped by {@link ResultSet}
22+
*
23+
* @return wrapped result
24+
*
25+
* @throws SQLException if a database access error occurs or
26+
* this method is called on a closed <code>Statement</code>
27+
*/
28+
ResultSet executeMetadata(SQLResultHolder data) throws SQLException;
29+
30+
}

Diff for: src/test/java/org/tarantool/TarantoolConnectionSQLOpsIT.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ public void setup() {
2222

2323
@AfterEach
2424
public void tearDown() {
25-
connection.close();
25+
if (connection != null) {
26+
connection.close();
27+
}
2628
}
2729

2830
@Override

Diff for: src/test/java/org/tarantool/jdbc/JdbcConnectionTimeoutIT.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
import static org.junit.jupiter.api.Assertions.assertFalse;
44
import static org.junit.jupiter.api.Assertions.assertThrows;
55
import static org.junit.jupiter.api.Assertions.assertTrue;
6+
import static org.tarantool.TestAssumptions.assumeMinimalServerVersion;
67
import static org.tarantool.TestUtils.makeInstanceEnv;
78

9+
import org.tarantool.ServerVersion;
810
import org.tarantool.TarantoolClientConfig;
11+
import org.tarantool.TarantoolConsole;
912
import org.tarantool.TarantoolControl;
1013
import org.tarantool.protocol.TarantoolPacket;
1114

@@ -25,6 +28,7 @@
2528
public class JdbcConnectionTimeoutIT {
2629

2730
protected static final String LUA_FILE = "jdk-testing.lua";
31+
private static final String HOST = "localhost";
2832
protected static final int LISTEN = 3301;
2933
protected static final int ADMIN = 3313;
3034
private static final String INSTANCE_NAME = "jdk-testing";
@@ -47,6 +51,7 @@ public static void tearDownEnv() {
4751

4852
@BeforeEach
4953
void setUp() throws SQLException {
54+
assumeMinimalServerVersion(TarantoolConsole.open(HOST, ADMIN), ServerVersion.V_2_1);
5055
connection = new SQLConnection("", new Properties()) {
5156
@Override
5257
protected SQLTarantoolClientImpl makeSqlClient(String address, TarantoolClientConfig config) {
@@ -66,7 +71,9 @@ protected void completeSql(TarantoolOp<?> operation, TarantoolPacket pack) {
6671

6772
@AfterEach
6873
void tearDown() throws SQLException {
69-
connection.close();
74+
if (connection != null) {
75+
connection.close();
76+
}
7077
}
7178

7279
@Test

Diff for: src/test/java/org/tarantool/jdbc/JdbcResultSetIT.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,12 @@ public void testResultSetMetadataAfterClose() throws SQLException {
167167
assertNotNull(resultSet);
168168
ResultSetMetaData metaData = resultSet.getMetaData();
169169
assertNotNull(metaData);
170+
171+
int expectedColumnSize = 2;
172+
assertEquals(expectedColumnSize, metaData.getColumnCount());
173+
170174
resultSet.close();
171-
assertEquals(metaData, resultSet.getMetaData());
175+
assertEquals(expectedColumnSize, metaData.getColumnCount());
172176
}
173177

174178
@Test

0 commit comments

Comments
 (0)