Skip to content

Commit a616415

Browse files
committed
Raise SQLException on methods of a closed Connection
Add missed checks on methods of the closed connection. Closes: #72 Affects: #119, #74
1 parent 06755d5 commit a616415

File tree

3 files changed

+228
-26
lines changed

3 files changed

+228
-26
lines changed

src/main/java/org/tarantool/jdbc/SQLConnection.java

Lines changed: 133 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.sql.Array;
1313
import java.sql.Blob;
1414
import java.sql.CallableStatement;
15+
import java.sql.ClientInfoStatus;
1516
import java.sql.Clob;
1617
import java.sql.Connection;
1718
import java.sql.DatabaseMetaData;
@@ -29,6 +30,9 @@
2930
import java.sql.Statement;
3031
import java.sql.Struct;
3132
import java.util.Arrays;
33+
import java.util.Collection;
34+
import java.util.Collections;
35+
import java.util.HashMap;
3236
import java.util.List;
3337
import java.util.Map;
3438
import java.util.Properties;
@@ -40,10 +44,10 @@
4044
import static org.tarantool.jdbc.SQLDriver.PROP_SOCKET_TIMEOUT;
4145
import static org.tarantool.jdbc.SQLDriver.PROP_USER;
4246

43-
@SuppressWarnings("Since15")
4447
public class SQLConnection implements Connection {
4548

4649
private static final int UNSET_HOLDABILITY = 0;
50+
private static final String PING_QUERY = "SELECT 1";
4751

4852
private final TarantoolConnection connection;
4953

@@ -91,6 +95,7 @@ public class SQLConnection implements Connection {
9195
* to honor this timeout for the following read/write operations as well.
9296
*
9397
* @return Connected socket.
98+
*
9499
* @throws SQLException if failed.
95100
*/
96101
protected Socket getConnectedSocket() throws SQLException {
@@ -140,7 +145,9 @@ protected Socket makeSocket() {
140145
* @param user User name.
141146
* @param pass Password.
142147
* @param socket Connected socket.
148+
*
143149
* @return Native tarantool connection.
150+
*
144151
* @throws IOException if failed.
145152
*/
146153
protected TarantoolConnection makeConnection(String user, String pass, Socket socket) throws IOException {
@@ -161,7 +168,7 @@ public PreparedStatement prepareStatement(String sql) throws SQLException {
161168

162169
@Override
163170
public CallableStatement prepareCall(String sql) throws SQLException {
164-
throw new SQLFeatureNotSupportedException();
171+
return prepareCall(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
165172
}
166173

167174
@Override
@@ -171,25 +178,38 @@ public String nativeSQL(String sql) throws SQLException {
171178

172179
@Override
173180
public void setAutoCommit(boolean autoCommit) throws SQLException {
181+
checkNotClosed();
174182
if (autoCommit == false) {
175183
throw new SQLFeatureNotSupportedException();
176184
}
177185
}
178186

179187
@Override
180188
public boolean getAutoCommit() throws SQLException {
189+
checkNotClosed();
181190
return true;
182191
}
183192

184193
@Override
185194
public void commit() throws SQLException {
186-
throw new SQLFeatureNotSupportedException();
195+
checkNotClosed();
196+
if (getAutoCommit()) {
197+
throw new SQLNonTransientException(
198+
"Cannot commit when auto-commit is enabled.",
199+
SQLStates.IVALID_TRANSACTION_STATE.getSqlState()
200+
);
201+
}
187202
}
188203

189204
@Override
190205
public void rollback() throws SQLException {
191-
throw new SQLFeatureNotSupportedException();
192-
206+
checkNotClosed();
207+
if (getAutoCommit()) {
208+
throw new SQLNonTransientException(
209+
"Cannot rollback when auto-commit is enabled.",
210+
SQLStates.IVALID_TRANSACTION_STATE.getSqlState()
211+
);
212+
}
193213
}
194214

195215
@Override
@@ -213,43 +233,50 @@ public DatabaseMetaData getMetaData() throws SQLException {
213233

214234
@Override
215235
public void setReadOnly(boolean readOnly) throws SQLException {
216-
236+
checkNotClosed();
237+
throw new SQLFeatureNotSupportedException();
217238
}
218239

219240
@Override
220241
public boolean isReadOnly() throws SQLException {
242+
checkNotClosed();
221243
return false;
222244
}
223245

224246
@Override
225247
public void setCatalog(String catalog) throws SQLException {
248+
checkNotClosed();
226249
}
227250

228251
@Override
229252
public String getCatalog() throws SQLException {
253+
checkNotClosed();
230254
return null;
231255
}
232256

233257
@Override
234258
public void setTransactionIsolation(int level) throws SQLException {
259+
checkNotClosed();
235260
if (level != Connection.TRANSACTION_NONE) {
236261
throw new SQLFeatureNotSupportedException();
237262
}
238263
}
239264

240265
@Override
241266
public int getTransactionIsolation() throws SQLException {
267+
checkNotClosed();
242268
return Connection.TRANSACTION_NONE;
243269
}
244270

245271
@Override
246272
public SQLWarning getWarnings() throws SQLException {
273+
checkNotClosed();
247274
return null;
248275
}
249276

250277
@Override
251278
public void clearWarnings() throws SQLException {
252-
279+
checkNotClosed();
253280
}
254281

255282
@Override
@@ -265,16 +292,18 @@ public PreparedStatement prepareStatement(String sql, int resultSetType, int res
265292

266293
@Override
267294
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
268-
throw new SQLFeatureNotSupportedException();
295+
return prepareCall(sql, resultSetType, resultSetConcurrency, getHoldability());
269296
}
270297

271298
@Override
272299
public Map<String, Class<?>> getTypeMap() throws SQLException {
300+
checkNotClosed();
273301
throw new SQLFeatureNotSupportedException();
274302
}
275303

276304
@Override
277305
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
306+
checkNotClosed();
278307
throw new SQLFeatureNotSupportedException();
279308
}
280309

@@ -296,21 +325,43 @@ public int getHoldability() throws SQLException {
296325

297326
@Override
298327
public Savepoint setSavepoint() throws SQLException {
328+
checkNotClosed();
329+
if (getAutoCommit()) {
330+
throw new SQLNonTransientException(
331+
"Cannot set a savepoint when auto-commit is enabled.",
332+
SQLStates.IVALID_TRANSACTION_STATE.getSqlState()
333+
);
334+
}
299335
throw new SQLFeatureNotSupportedException();
300336
}
301337

302338
@Override
303339
public Savepoint setSavepoint(String name) throws SQLException {
340+
checkNotClosed();
341+
if (getAutoCommit()) {
342+
throw new SQLNonTransientException(
343+
"Cannot set a savepoint when auto-commit is enabled.",
344+
SQLStates.IVALID_TRANSACTION_STATE.getSqlState()
345+
);
346+
}
304347
throw new SQLFeatureNotSupportedException();
305348
}
306349

307350
@Override
308351
public void rollback(Savepoint savepoint) throws SQLException {
352+
checkNotClosed();
353+
if (getAutoCommit()) {
354+
throw new SQLNonTransientException(
355+
"Cannot roll back to a savepoint when auto-commit is enabled.",
356+
SQLStates.IVALID_TRANSACTION_STATE.getSqlState()
357+
);
358+
}
309359
throw new SQLFeatureNotSupportedException();
310360
}
311361

312362
@Override
313363
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
364+
checkNotClosed();
314365
throw new SQLFeatureNotSupportedException();
315366
}
316367

@@ -336,90 +387,159 @@ public PreparedStatement prepareStatement(String sql,
336387
@Override
337388
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
338389
throws SQLException {
390+
checkNotClosed();
339391
throw new SQLFeatureNotSupportedException();
340392
}
341393

342394
@Override
343395
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
396+
checkNotClosed();
344397
throw new SQLFeatureNotSupportedException();
345398
}
346399

347400
@Override
348401
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
402+
checkNotClosed();
349403
throw new SQLFeatureNotSupportedException();
350404
}
351405

352406
@Override
353407
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
408+
checkNotClosed();
354409
throw new SQLFeatureNotSupportedException();
355410
}
356411

357412
@Override
358413
public Clob createClob() throws SQLException {
414+
checkNotClosed();
359415
throw new SQLFeatureNotSupportedException();
360416
}
361417

362418
@Override
363419
public Blob createBlob() throws SQLException {
420+
checkNotClosed();
364421
throw new SQLFeatureNotSupportedException();
365422
}
366423

367424
@Override
368425
public NClob createNClob() throws SQLException {
426+
checkNotClosed();
369427
throw new SQLFeatureNotSupportedException();
370428
}
371429

372430
@Override
373431
public SQLXML createSQLXML() throws SQLException {
432+
checkNotClosed();
374433
throw new SQLFeatureNotSupportedException();
375434
}
376435

436+
/**
437+
* {@inheritDoc}
438+
*
439+
* @param timeout temporally ignored param
440+
*
441+
* @return connection activity status
442+
*/
377443
@Override
378444
public boolean isValid(int timeout) throws SQLException {
379445
return true;
380446
}
381447

382448
@Override
383449
public void setClientInfo(String name, String value) throws SQLClientInfoException {
384-
throw new SQLClientInfoException();
450+
try {
451+
checkNotClosed();
452+
throwUnknownClientProperties(Collections.singleton(name));
453+
} catch (SQLException cause) {
454+
throwUnknownReasonClientProperties("Connection is closed", Collections.singleton(name), cause);
455+
}
385456
}
386457

387458
@Override
388459
public void setClientInfo(Properties properties) throws SQLClientInfoException {
389-
throw new SQLClientInfoException();
460+
try {
461+
checkNotClosed();
462+
throwUnknownClientProperties(properties.keySet());
463+
} catch (SQLException cause) {
464+
throwUnknownReasonClientProperties("Connection is closed", properties.keySet(), cause);
465+
}
466+
}
467+
468+
/**
469+
* Throws an exception caused by {@code cause} and marks all properties
470+
* as {@link ClientInfoStatus#REASON_UNKNOWN}
471+
*
472+
* @param reason reason mesage
473+
* @param properties client properties
474+
* @param cause original cause
475+
*
476+
* @throws SQLClientInfoException wrapped exception
477+
*/
478+
private void throwUnknownReasonClientProperties(String reason,
479+
Collection<Object> properties,
480+
SQLException cause) throws SQLClientInfoException {
481+
Map<String, ClientInfoStatus> failedProperties = new HashMap<>();
482+
properties.forEach(property -> {
483+
failedProperties.put(property.toString(), ClientInfoStatus.REASON_UNKNOWN);
484+
});
485+
throw new SQLClientInfoException(reason, failedProperties, cause);
486+
}
487+
488+
/**
489+
* Throws exception for unrecognizable properties
490+
*
491+
* @param properties unknown property names
492+
*
493+
* @throws SQLClientInfoException wrapped exception
494+
*/
495+
private void throwUnknownClientProperties(Collection<Object> properties) throws SQLClientInfoException {
496+
Map<String, ClientInfoStatus> failedProperties = new HashMap<>();
497+
properties.forEach(property -> {
498+
failedProperties.put(property.toString(), ClientInfoStatus.REASON_UNKNOWN_PROPERTY);
499+
});
500+
throw new SQLClientInfoException(failedProperties);
390501
}
391502

392503
@Override
393504
public String getClientInfo(String name) throws SQLException {
505+
checkNotClosed();
394506
throw new SQLFeatureNotSupportedException();
395507
}
396508

397509
@Override
398510
public Properties getClientInfo() throws SQLException {
511+
checkNotClosed();
399512
throw new SQLFeatureNotSupportedException();
400513
}
401514

402515
@Override
403516
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
517+
checkNotClosed();
404518
throw new SQLFeatureNotSupportedException();
405519
}
406520

407521
@Override
408522
public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
523+
checkNotClosed();
409524
throw new SQLFeatureNotSupportedException();
410525
}
411526

412527
@Override
413528
public void setSchema(String schema) throws SQLException {
529+
checkNotClosed();
414530
}
415531

416532
@Override
417533
public String getSchema() throws SQLException {
534+
checkNotClosed();
418535
return null;
419536
}
420537

421538
@Override
422539
public void abort(Executor executor) throws SQLException {
540+
if (isClosed()) {
541+
return;
542+
}
423543
throw new SQLFeatureNotSupportedException();
424544
}
425545

@@ -544,8 +664,9 @@ private void handleException(Exception e) {
544664
* Checks whether <code>holdability</code> is supported
545665
*
546666
* @param holdability param to be checked
667+
*
547668
* @throws SQLFeatureNotSupportedException param is not supported
548-
* @throws SQLNonTransientException param has invalid value
669+
* @throws SQLNonTransientException param has invalid value
549670
*/
550671
private void checkHoldabilitySupport(int holdability) throws SQLException {
551672
if (holdability != ResultSet.CLOSE_CURSORS_AT_COMMIT
@@ -562,6 +683,7 @@ private void checkHoldabilitySupport(int holdability) throws SQLException {
562683
*
563684
* @param sql SQL Text.
564685
* @param params Parameters of the SQL statement.
686+
*
565687
* @return Formatted error message.
566688
*/
567689
private static String formatError(String sql, Object... params) {

0 commit comments

Comments
 (0)