12
12
import java .sql .Array ;
13
13
import java .sql .Blob ;
14
14
import java .sql .CallableStatement ;
15
+ import java .sql .ClientInfoStatus ;
15
16
import java .sql .Clob ;
16
17
import java .sql .Connection ;
17
18
import java .sql .DatabaseMetaData ;
29
30
import java .sql .Statement ;
30
31
import java .sql .Struct ;
31
32
import java .util .Arrays ;
33
+ import java .util .Collection ;
34
+ import java .util .Collections ;
35
+ import java .util .HashMap ;
32
36
import java .util .List ;
33
37
import java .util .Map ;
34
38
import java .util .Properties ;
40
44
import static org .tarantool .jdbc .SQLDriver .PROP_SOCKET_TIMEOUT ;
41
45
import static org .tarantool .jdbc .SQLDriver .PROP_USER ;
42
46
43
- @ SuppressWarnings ("Since15" )
44
47
public class SQLConnection implements Connection {
45
48
46
49
private static final int UNSET_HOLDABILITY = 0 ;
50
+ private static final String PING_QUERY = "SELECT 1" ;
47
51
48
52
private final TarantoolConnection connection ;
49
53
@@ -91,6 +95,7 @@ public class SQLConnection implements Connection {
91
95
* to honor this timeout for the following read/write operations as well.
92
96
*
93
97
* @return Connected socket.
98
+ *
94
99
* @throws SQLException if failed.
95
100
*/
96
101
protected Socket getConnectedSocket () throws SQLException {
@@ -140,7 +145,9 @@ protected Socket makeSocket() {
140
145
* @param user User name.
141
146
* @param pass Password.
142
147
* @param socket Connected socket.
148
+ *
143
149
* @return Native tarantool connection.
150
+ *
144
151
* @throws IOException if failed.
145
152
*/
146
153
protected TarantoolConnection makeConnection (String user , String pass , Socket socket ) throws IOException {
@@ -161,7 +168,7 @@ public PreparedStatement prepareStatement(String sql) throws SQLException {
161
168
162
169
@ Override
163
170
public CallableStatement prepareCall (String sql ) throws SQLException {
164
- throw new SQLFeatureNotSupportedException ( );
171
+ return prepareCall ( sql , ResultSet . TYPE_FORWARD_ONLY , ResultSet . CONCUR_READ_ONLY );
165
172
}
166
173
167
174
@ Override
@@ -171,25 +178,38 @@ public String nativeSQL(String sql) throws SQLException {
171
178
172
179
@ Override
173
180
public void setAutoCommit (boolean autoCommit ) throws SQLException {
181
+ checkNotClosed ();
174
182
if (autoCommit == false ) {
175
183
throw new SQLFeatureNotSupportedException ();
176
184
}
177
185
}
178
186
179
187
@ Override
180
188
public boolean getAutoCommit () throws SQLException {
189
+ checkNotClosed ();
181
190
return true ;
182
191
}
183
192
184
193
@ Override
185
194
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
+ }
187
202
}
188
203
189
204
@ Override
190
205
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
+ }
193
213
}
194
214
195
215
@ Override
@@ -213,43 +233,50 @@ public DatabaseMetaData getMetaData() throws SQLException {
213
233
214
234
@ Override
215
235
public void setReadOnly (boolean readOnly ) throws SQLException {
216
-
236
+ checkNotClosed ();
237
+ throw new SQLFeatureNotSupportedException ();
217
238
}
218
239
219
240
@ Override
220
241
public boolean isReadOnly () throws SQLException {
242
+ checkNotClosed ();
221
243
return false ;
222
244
}
223
245
224
246
@ Override
225
247
public void setCatalog (String catalog ) throws SQLException {
248
+ checkNotClosed ();
226
249
}
227
250
228
251
@ Override
229
252
public String getCatalog () throws SQLException {
253
+ checkNotClosed ();
230
254
return null ;
231
255
}
232
256
233
257
@ Override
234
258
public void setTransactionIsolation (int level ) throws SQLException {
259
+ checkNotClosed ();
235
260
if (level != Connection .TRANSACTION_NONE ) {
236
261
throw new SQLFeatureNotSupportedException ();
237
262
}
238
263
}
239
264
240
265
@ Override
241
266
public int getTransactionIsolation () throws SQLException {
267
+ checkNotClosed ();
242
268
return Connection .TRANSACTION_NONE ;
243
269
}
244
270
245
271
@ Override
246
272
public SQLWarning getWarnings () throws SQLException {
273
+ checkNotClosed ();
247
274
return null ;
248
275
}
249
276
250
277
@ Override
251
278
public void clearWarnings () throws SQLException {
252
-
279
+ checkNotClosed ();
253
280
}
254
281
255
282
@ Override
@@ -265,16 +292,18 @@ public PreparedStatement prepareStatement(String sql, int resultSetType, int res
265
292
266
293
@ Override
267
294
public CallableStatement prepareCall (String sql , int resultSetType , int resultSetConcurrency ) throws SQLException {
268
- throw new SQLFeatureNotSupportedException ( );
295
+ return prepareCall ( sql , resultSetType , resultSetConcurrency , getHoldability () );
269
296
}
270
297
271
298
@ Override
272
299
public Map <String , Class <?>> getTypeMap () throws SQLException {
300
+ checkNotClosed ();
273
301
throw new SQLFeatureNotSupportedException ();
274
302
}
275
303
276
304
@ Override
277
305
public void setTypeMap (Map <String , Class <?>> map ) throws SQLException {
306
+ checkNotClosed ();
278
307
throw new SQLFeatureNotSupportedException ();
279
308
}
280
309
@@ -296,21 +325,43 @@ public int getHoldability() throws SQLException {
296
325
297
326
@ Override
298
327
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
+ }
299
335
throw new SQLFeatureNotSupportedException ();
300
336
}
301
337
302
338
@ Override
303
339
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
+ }
304
347
throw new SQLFeatureNotSupportedException ();
305
348
}
306
349
307
350
@ Override
308
351
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
+ }
309
359
throw new SQLFeatureNotSupportedException ();
310
360
}
311
361
312
362
@ Override
313
363
public void releaseSavepoint (Savepoint savepoint ) throws SQLException {
364
+ checkNotClosed ();
314
365
throw new SQLFeatureNotSupportedException ();
315
366
}
316
367
@@ -336,90 +387,159 @@ public PreparedStatement prepareStatement(String sql,
336
387
@ Override
337
388
public CallableStatement prepareCall (String sql , int resultSetType , int resultSetConcurrency , int resultSetHoldability )
338
389
throws SQLException {
390
+ checkNotClosed ();
339
391
throw new SQLFeatureNotSupportedException ();
340
392
}
341
393
342
394
@ Override
343
395
public PreparedStatement prepareStatement (String sql , int autoGeneratedKeys ) throws SQLException {
396
+ checkNotClosed ();
344
397
throw new SQLFeatureNotSupportedException ();
345
398
}
346
399
347
400
@ Override
348
401
public PreparedStatement prepareStatement (String sql , int [] columnIndexes ) throws SQLException {
402
+ checkNotClosed ();
349
403
throw new SQLFeatureNotSupportedException ();
350
404
}
351
405
352
406
@ Override
353
407
public PreparedStatement prepareStatement (String sql , String [] columnNames ) throws SQLException {
408
+ checkNotClosed ();
354
409
throw new SQLFeatureNotSupportedException ();
355
410
}
356
411
357
412
@ Override
358
413
public Clob createClob () throws SQLException {
414
+ checkNotClosed ();
359
415
throw new SQLFeatureNotSupportedException ();
360
416
}
361
417
362
418
@ Override
363
419
public Blob createBlob () throws SQLException {
420
+ checkNotClosed ();
364
421
throw new SQLFeatureNotSupportedException ();
365
422
}
366
423
367
424
@ Override
368
425
public NClob createNClob () throws SQLException {
426
+ checkNotClosed ();
369
427
throw new SQLFeatureNotSupportedException ();
370
428
}
371
429
372
430
@ Override
373
431
public SQLXML createSQLXML () throws SQLException {
432
+ checkNotClosed ();
374
433
throw new SQLFeatureNotSupportedException ();
375
434
}
376
435
436
+ /**
437
+ * {@inheritDoc}
438
+ *
439
+ * @param timeout temporally ignored param
440
+ *
441
+ * @return connection activity status
442
+ */
377
443
@ Override
378
444
public boolean isValid (int timeout ) throws SQLException {
379
445
return true ;
380
446
}
381
447
382
448
@ Override
383
449
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
+ }
385
456
}
386
457
387
458
@ Override
388
459
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 );
390
501
}
391
502
392
503
@ Override
393
504
public String getClientInfo (String name ) throws SQLException {
505
+ checkNotClosed ();
394
506
throw new SQLFeatureNotSupportedException ();
395
507
}
396
508
397
509
@ Override
398
510
public Properties getClientInfo () throws SQLException {
511
+ checkNotClosed ();
399
512
throw new SQLFeatureNotSupportedException ();
400
513
}
401
514
402
515
@ Override
403
516
public Array createArrayOf (String typeName , Object [] elements ) throws SQLException {
517
+ checkNotClosed ();
404
518
throw new SQLFeatureNotSupportedException ();
405
519
}
406
520
407
521
@ Override
408
522
public Struct createStruct (String typeName , Object [] attributes ) throws SQLException {
523
+ checkNotClosed ();
409
524
throw new SQLFeatureNotSupportedException ();
410
525
}
411
526
412
527
@ Override
413
528
public void setSchema (String schema ) throws SQLException {
529
+ checkNotClosed ();
414
530
}
415
531
416
532
@ Override
417
533
public String getSchema () throws SQLException {
534
+ checkNotClosed ();
418
535
return null ;
419
536
}
420
537
421
538
@ Override
422
539
public void abort (Executor executor ) throws SQLException {
540
+ if (isClosed ()) {
541
+ return ;
542
+ }
423
543
throw new SQLFeatureNotSupportedException ();
424
544
}
425
545
@@ -544,8 +664,9 @@ private void handleException(Exception e) {
544
664
* Checks whether <code>holdability</code> is supported
545
665
*
546
666
* @param holdability param to be checked
667
+ *
547
668
* @throws SQLFeatureNotSupportedException param is not supported
548
- * @throws SQLNonTransientException param has invalid value
669
+ * @throws SQLNonTransientException param has invalid value
549
670
*/
550
671
private void checkHoldabilitySupport (int holdability ) throws SQLException {
551
672
if (holdability != ResultSet .CLOSE_CURSORS_AT_COMMIT
@@ -562,6 +683,7 @@ private void checkHoldabilitySupport(int holdability) throws SQLException {
562
683
*
563
684
* @param sql SQL Text.
564
685
* @param params Parameters of the SQL statement.
686
+ *
565
687
* @return Formatted error message.
566
688
*/
567
689
private static String formatError (String sql , Object ... params ) {
0 commit comments