1
1
package org .tarantool .jdbc ;
2
2
3
+ import java .io .IOException ;
4
+ import java .net .InetSocketAddress ;
5
+ import java .net .Socket ;
6
+ import java .net .SocketException ;
3
7
import java .sql .Array ;
4
8
import java .sql .Blob ;
5
9
import java .sql .CallableStatement ;
8
12
import java .sql .DatabaseMetaData ;
9
13
import java .sql .NClob ;
10
14
import java .sql .PreparedStatement ;
15
+ import java .sql .ResultSet ;
11
16
import java .sql .SQLClientInfoException ;
12
17
import java .sql .SQLException ;
13
18
import java .sql .SQLFeatureNotSupportedException ;
16
21
import java .sql .Savepoint ;
17
22
import java .sql .Statement ;
18
23
import java .sql .Struct ;
24
+ import java .util .Arrays ;
25
+ import java .util .List ;
19
26
import java .util .Map ;
20
27
import java .util .Properties ;
21
28
import java .util .concurrent .Executor ;
22
29
30
+ import org .tarantool .CommunicationException ;
31
+ import org .tarantool .JDBCBridge ;
23
32
import org .tarantool .TarantoolConnection ;
24
33
34
+ import static org .tarantool .jdbc .SQLDriver .PROP_HOST ;
35
+ import static org .tarantool .jdbc .SQLDriver .PROP_PASSWORD ;
36
+ import static org .tarantool .jdbc .SQLDriver .PROP_PORT ;
37
+ import static org .tarantool .jdbc .SQLDriver .PROP_SOCKET_TIMEOUT ;
38
+ import static org .tarantool .jdbc .SQLDriver .PROP_USER ;
39
+
25
40
@ SuppressWarnings ("Since15" )
26
41
public class SQLConnection implements Connection {
27
- final TarantoolConnection connection ;
42
+ private final TarantoolConnection connection ;
28
43
final String url ;
29
44
final Properties properties ;
30
45
31
- public SQLConnection (TarantoolConnection connection , String url , Properties properties ) {
32
- this .connection = connection ;
46
+ SQLConnection (String url , Properties properties ) throws SQLException {
33
47
this .url = url ;
34
48
this .properties = properties ;
49
+
50
+ String user = properties .getProperty (PROP_USER );
51
+ String pass = properties .getProperty (PROP_PASSWORD );
52
+ Socket socket = null ;
53
+ try {
54
+ socket = getConnectedSocket ();
55
+ this .connection = makeConnection (user , pass , socket );
56
+ } catch (Exception e ) {
57
+ if (socket != null ) {
58
+ try {
59
+ socket .close ();
60
+ } catch (IOException ignored ) {
61
+ // No-op.
62
+ }
63
+ }
64
+ if (e instanceof SQLException )
65
+ throw (SQLException )e ;
66
+ throw new SQLException ("Couldn't initiate connection using " + SQLDriver .diagProperties (properties ), e );
67
+ }
68
+ }
69
+
70
+ protected Socket getConnectedSocket () throws SQLException {
71
+ Socket socket = makeSocket ();
72
+ int timeout = Integer .parseInt (properties .getProperty (PROP_SOCKET_TIMEOUT ));
73
+ String host = properties .getProperty (PROP_HOST );
74
+ int port = Integer .parseInt (properties .getProperty (PROP_PORT ));
75
+ try {
76
+ socket .connect (new InetSocketAddress (host , port ), timeout );
77
+ } catch (IOException e ) {
78
+ throw new SQLException ("Couldn't connect to " + host + ":" + port , e );
79
+ }
80
+ // Setup socket further.
81
+ if (timeout > 0 ) {
82
+ try {
83
+ socket .setSoTimeout (timeout );
84
+ } catch (SocketException e ) {
85
+ try {
86
+ socket .close ();
87
+ } catch (IOException ignored ) {
88
+ // No-op.
89
+ }
90
+ throw new SQLException ("Couldn't set socket timeout. timeout=" + timeout , e );
91
+ }
92
+ }
93
+ return socket ;
94
+ }
95
+
96
+ protected Socket makeSocket () {
97
+ return new Socket ();
98
+ }
99
+
100
+ protected TarantoolConnection makeConnection (String user , String pass , Socket socket ) throws IOException {
101
+ return new TarantoolConnection (user , pass , socket ) {{
102
+ msgPackLite = SQLMsgPackLite .INSTANCE ;
103
+ }};
35
104
}
36
105
37
106
@ Override
38
107
public Statement createStatement () throws SQLException {
39
- return new SQLStatement (connection , this );
108
+ checkNotClosed ();
109
+ return new SQLStatement (this );
40
110
}
41
111
42
112
@ Override
43
113
public PreparedStatement prepareStatement (String sql ) throws SQLException {
44
- return new SQLPreparedStatement (connection , this , sql );
114
+ checkNotClosed ();
115
+ return new SQLPreparedStatement (this , sql );
45
116
}
46
117
47
118
@ Override
@@ -89,6 +160,7 @@ public boolean isClosed() throws SQLException {
89
160
90
161
@ Override
91
162
public DatabaseMetaData getMetaData () throws SQLException {
163
+ checkNotClosed ();
92
164
return new SQLDatabaseMetadata (this );
93
165
}
94
166
@@ -293,15 +365,28 @@ public void abort(Executor executor) throws SQLException {
293
365
294
366
@ Override
295
367
public void setNetworkTimeout (Executor executor , int milliseconds ) throws SQLException {
296
- throw new SQLFeatureNotSupportedException ();
368
+ checkNotClosed ();
369
+
370
+ if (milliseconds < 0 )
371
+ throw new SQLException ("Network timeout cannot be negative." );
372
+
373
+ try {
374
+ connection .setSocketTimeout (milliseconds );
375
+ } catch (SocketException e ) {
376
+ throw new SQLException ("Failed to set socket timeout: timeout=" + milliseconds , e );
377
+ }
297
378
}
298
379
299
380
@ Override
300
381
public int getNetworkTimeout () throws SQLException {
301
- throw new SQLFeatureNotSupportedException ();
382
+ checkNotClosed ();
383
+ try {
384
+ return connection .getSocketTimeout ();
385
+ } catch (SocketException e ) {
386
+ throw new SQLException ("Failed to retrieve socket timeout" , e );
387
+ }
302
388
}
303
389
304
-
305
390
@ Override
306
391
public <T > T unwrap (Class <T > iface ) throws SQLException {
307
392
throw new SQLFeatureNotSupportedException ();
@@ -311,4 +396,84 @@ public <T> T unwrap(Class<T> iface) throws SQLException {
311
396
public boolean isWrapperFor (Class <?> iface ) throws SQLException {
312
397
throw new SQLFeatureNotSupportedException ();
313
398
}
399
+
400
+ protected Object execute (String sql , Object ... args ) throws SQLException {
401
+ checkNotClosed ();
402
+ try {
403
+ return JDBCBridge .execute (connection , sql , args );
404
+ } catch (Exception e ) {
405
+ handleException (e );
406
+ throw new SQLException (formatError (sql , args ), e );
407
+ }
408
+ }
409
+
410
+ protected ResultSet executeQuery (String sql , Object ... args ) throws SQLException {
411
+ checkNotClosed ();
412
+ try {
413
+ return new SQLResultSet (JDBCBridge .query (connection , sql , args ));
414
+ } catch (Exception e ) {
415
+ handleException (e );
416
+ throw new SQLException (formatError (sql , args ), e );
417
+ }
418
+ }
419
+
420
+ protected int executeUpdate (String sql , Object ... args ) throws SQLException {
421
+ checkNotClosed ();
422
+ try {
423
+ return JDBCBridge .update (connection , sql , args );
424
+ } catch (Exception e ) {
425
+ handleException (e );
426
+ throw new SQLException (formatError (sql , args ), e );
427
+ }
428
+ }
429
+
430
+ protected List <?> nativeSelect (Integer space , Integer index , List <?> key , int offset , int limit , int iterator )
431
+ throws SQLException {
432
+ checkNotClosed ();
433
+ try {
434
+ return connection .select (space , index , key , offset , limit , iterator );
435
+ } catch (Exception e ) {
436
+ handleException (e );
437
+ throw new SQLException (e );
438
+ }
439
+ }
440
+
441
+ protected String getServerVersion () {
442
+ return connection .getServerVersion ();
443
+ }
444
+
445
+ /**
446
+ * @throws SQLException If connection is closed.
447
+ */
448
+ protected void checkNotClosed () throws SQLException {
449
+ if (isClosed ())
450
+ throw new SQLException ("Connection is closed." );
451
+ }
452
+
453
+ /**
454
+ * Inspects passed exception and closes the connection if appropriate.
455
+ *
456
+ * @param e Exception to process.
457
+ */
458
+ private void handleException (Exception e ) {
459
+ if (CommunicationException .class .isAssignableFrom (e .getClass ()) ||
460
+ IOException .class .isAssignableFrom (e .getClass ())) {
461
+ try {
462
+ close ();
463
+ } catch (SQLException ignored ) {
464
+ // No-op.
465
+ }
466
+ }
467
+ }
468
+
469
+ /**
470
+ * Provides error message that contains parameters of failed SQL statement.
471
+ *
472
+ * @param sql SQL Text.
473
+ * @param params Parameters of the SQL statement.
474
+ * @return Formatted error message.
475
+ */
476
+ private static String formatError (String sql , Object ... params ) {
477
+ return "Failed to execute SQL: " + sql + ", params: " + Arrays .deepToString (params );
478
+ }
314
479
}
0 commit comments