Skip to content

Commit 00232b7

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 00232b7

File tree

3 files changed

+227
-26
lines changed

3 files changed

+227
-26
lines changed

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

Lines changed: 132 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,7 +44,6 @@
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;
@@ -91,6 +94,7 @@ public class SQLConnection implements Connection {
9194
* to honor this timeout for the following read/write operations as well.
9295
*
9396
* @return Connected socket.
97+
*
9498
* @throws SQLException if failed.
9599
*/
96100
protected Socket getConnectedSocket() throws SQLException {
@@ -140,7 +144,9 @@ protected Socket makeSocket() {
140144
* @param user User name.
141145
* @param pass Password.
142146
* @param socket Connected socket.
147+
*
143148
* @return Native tarantool connection.
149+
*
144150
* @throws IOException if failed.
145151
*/
146152
protected TarantoolConnection makeConnection(String user, String pass, Socket socket) throws IOException {
@@ -161,7 +167,7 @@ public PreparedStatement prepareStatement(String sql) throws SQLException {
161167

162168
@Override
163169
public CallableStatement prepareCall(String sql) throws SQLException {
164-
throw new SQLFeatureNotSupportedException();
170+
return prepareCall(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
165171
}
166172

167173
@Override
@@ -171,25 +177,38 @@ public String nativeSQL(String sql) throws SQLException {
171177

172178
@Override
173179
public void setAutoCommit(boolean autoCommit) throws SQLException {
180+
checkNotClosed();
174181
if (autoCommit == false) {
175182
throw new SQLFeatureNotSupportedException();
176183
}
177184
}
178185

179186
@Override
180187
public boolean getAutoCommit() throws SQLException {
188+
checkNotClosed();
181189
return true;
182190
}
183191

184192
@Override
185193
public void commit() throws SQLException {
186-
throw new SQLFeatureNotSupportedException();
194+
checkNotClosed();
195+
if (getAutoCommit()) {
196+
throw new SQLNonTransientException(
197+
"Cannot commit when auto-commit is enabled.",
198+
SQLStates.IVALID_TRANSACTION_STATE.getSqlState()
199+
);
200+
}
187201
}
188202

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

195214
@Override
@@ -213,43 +232,50 @@ public DatabaseMetaData getMetaData() throws SQLException {
213232

214233
@Override
215234
public void setReadOnly(boolean readOnly) throws SQLException {
216-
235+
checkNotClosed();
236+
throw new SQLFeatureNotSupportedException();
217237
}
218238

219239
@Override
220240
public boolean isReadOnly() throws SQLException {
241+
checkNotClosed();
221242
return false;
222243
}
223244

224245
@Override
225246
public void setCatalog(String catalog) throws SQLException {
247+
checkNotClosed();
226248
}
227249

228250
@Override
229251
public String getCatalog() throws SQLException {
252+
checkNotClosed();
230253
return null;
231254
}
232255

233256
@Override
234257
public void setTransactionIsolation(int level) throws SQLException {
258+
checkNotClosed();
235259
if (level != Connection.TRANSACTION_NONE) {
236260
throw new SQLFeatureNotSupportedException();
237261
}
238262
}
239263

240264
@Override
241265
public int getTransactionIsolation() throws SQLException {
266+
checkNotClosed();
242267
return Connection.TRANSACTION_NONE;
243268
}
244269

245270
@Override
246271
public SQLWarning getWarnings() throws SQLException {
272+
checkNotClosed();
247273
return null;
248274
}
249275

250276
@Override
251277
public void clearWarnings() throws SQLException {
252-
278+
checkNotClosed();
253279
}
254280

255281
@Override
@@ -265,16 +291,18 @@ public PreparedStatement prepareStatement(String sql, int resultSetType, int res
265291

266292
@Override
267293
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
268-
throw new SQLFeatureNotSupportedException();
294+
return prepareCall(sql, resultSetType, resultSetConcurrency, getHoldability());
269295
}
270296

271297
@Override
272298
public Map<String, Class<?>> getTypeMap() throws SQLException {
299+
checkNotClosed();
273300
throw new SQLFeatureNotSupportedException();
274301
}
275302

276303
@Override
277304
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
305+
checkNotClosed();
278306
throw new SQLFeatureNotSupportedException();
279307
}
280308

@@ -296,21 +324,43 @@ public int getHoldability() throws SQLException {
296324

297325
@Override
298326
public Savepoint setSavepoint() throws SQLException {
327+
checkNotClosed();
328+
if (getAutoCommit()) {
329+
throw new SQLNonTransientException(
330+
"Cannot set a savepoint when auto-commit is enabled.",
331+
SQLStates.IVALID_TRANSACTION_STATE.getSqlState()
332+
);
333+
}
299334
throw new SQLFeatureNotSupportedException();
300335
}
301336

302337
@Override
303338
public Savepoint setSavepoint(String name) throws SQLException {
339+
checkNotClosed();
340+
if (getAutoCommit()) {
341+
throw new SQLNonTransientException(
342+
"Cannot set a savepoint when auto-commit is enabled.",
343+
SQLStates.IVALID_TRANSACTION_STATE.getSqlState()
344+
);
345+
}
304346
throw new SQLFeatureNotSupportedException();
305347
}
306348

307349
@Override
308350
public void rollback(Savepoint savepoint) throws SQLException {
351+
checkNotClosed();
352+
if (getAutoCommit()) {
353+
throw new SQLNonTransientException(
354+
"Cannot roll back to a savepoint when auto-commit is enabled.",
355+
SQLStates.IVALID_TRANSACTION_STATE.getSqlState()
356+
);
357+
}
309358
throw new SQLFeatureNotSupportedException();
310359
}
311360

312361
@Override
313362
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
363+
checkNotClosed();
314364
throw new SQLFeatureNotSupportedException();
315365
}
316366

@@ -336,90 +386,159 @@ public PreparedStatement prepareStatement(String sql,
336386
@Override
337387
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
338388
throws SQLException {
389+
checkNotClosed();
339390
throw new SQLFeatureNotSupportedException();
340391
}
341392

342393
@Override
343394
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
395+
checkNotClosed();
344396
throw new SQLFeatureNotSupportedException();
345397
}
346398

347399
@Override
348400
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
401+
checkNotClosed();
349402
throw new SQLFeatureNotSupportedException();
350403
}
351404

352405
@Override
353406
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
407+
checkNotClosed();
354408
throw new SQLFeatureNotSupportedException();
355409
}
356410

357411
@Override
358412
public Clob createClob() throws SQLException {
413+
checkNotClosed();
359414
throw new SQLFeatureNotSupportedException();
360415
}
361416

362417
@Override
363418
public Blob createBlob() throws SQLException {
419+
checkNotClosed();
364420
throw new SQLFeatureNotSupportedException();
365421
}
366422

367423
@Override
368424
public NClob createNClob() throws SQLException {
425+
checkNotClosed();
369426
throw new SQLFeatureNotSupportedException();
370427
}
371428

372429
@Override
373430
public SQLXML createSQLXML() throws SQLException {
431+
checkNotClosed();
374432
throw new SQLFeatureNotSupportedException();
375433
}
376434

435+
/**
436+
* {@inheritDoc}
437+
*
438+
* @param timeout temporally ignored param
439+
*
440+
* @return connection activity status
441+
*/
377442
@Override
378443
public boolean isValid(int timeout) throws SQLException {
379444
return true;
380445
}
381446

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

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

392502
@Override
393503
public String getClientInfo(String name) throws SQLException {
504+
checkNotClosed();
394505
throw new SQLFeatureNotSupportedException();
395506
}
396507

397508
@Override
398509
public Properties getClientInfo() throws SQLException {
510+
checkNotClosed();
399511
throw new SQLFeatureNotSupportedException();
400512
}
401513

402514
@Override
403515
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
516+
checkNotClosed();
404517
throw new SQLFeatureNotSupportedException();
405518
}
406519

407520
@Override
408521
public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
522+
checkNotClosed();
409523
throw new SQLFeatureNotSupportedException();
410524
}
411525

412526
@Override
413527
public void setSchema(String schema) throws SQLException {
528+
checkNotClosed();
414529
}
415530

416531
@Override
417532
public String getSchema() throws SQLException {
533+
checkNotClosed();
418534
return null;
419535
}
420536

421537
@Override
422538
public void abort(Executor executor) throws SQLException {
539+
if (isClosed()) {
540+
return;
541+
}
423542
throw new SQLFeatureNotSupportedException();
424543
}
425544

@@ -544,8 +663,9 @@ private void handleException(Exception e) {
544663
* Checks whether <code>holdability</code> is supported
545664
*
546665
* @param holdability param to be checked
666+
*
547667
* @throws SQLFeatureNotSupportedException param is not supported
548-
* @throws SQLNonTransientException param has invalid value
668+
* @throws SQLNonTransientException param has invalid value
549669
*/
550670
private void checkHoldabilitySupport(int holdability) throws SQLException {
551671
if (holdability != ResultSet.CLOSE_CURSORS_AT_COMMIT
@@ -562,6 +682,7 @@ private void checkHoldabilitySupport(int holdability) throws SQLException {
562682
*
563683
* @param sql SQL Text.
564684
* @param params Parameters of the SQL statement.
685+
*
565686
* @return Formatted error message.
566687
*/
567688
private static String formatError(String sql, Object... params) {

0 commit comments

Comments
 (0)