activerecord-jdbc-alt-adapter 52.4.0-java → 61.0.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.nvimlog +0 -0
  4. data/.travis.yml +63 -39
  5. data/Gemfile +11 -4
  6. data/README.md +55 -35
  7. data/Rakefile +1 -1
  8. data/Rakefile.jdbc +8 -1
  9. data/activerecord-jdbc-adapter.gemspec +6 -9
  10. data/activerecord-jdbc-alt-adapter.gemspec +9 -12
  11. data/lib/arel/visitors/postgresql_jdbc.rb +1 -1
  12. data/lib/arel/visitors/sqlserver.rb +49 -23
  13. data/lib/arjdbc/abstract/connection_management.rb +7 -0
  14. data/lib/arjdbc/abstract/core.rb +17 -23
  15. data/lib/arjdbc/abstract/database_statements.rb +30 -2
  16. data/lib/arjdbc/abstract/statement_cache.rb +2 -5
  17. data/lib/arjdbc/abstract/transaction_support.rb +22 -7
  18. data/lib/arjdbc/db2/column.rb +0 -39
  19. data/lib/arjdbc/derby/adapter.rb +1 -20
  20. data/lib/arjdbc/firebird/adapter.rb +0 -21
  21. data/lib/arjdbc/h2/adapter.rb +0 -15
  22. data/lib/arjdbc/hsqldb/adapter.rb +0 -14
  23. data/lib/arjdbc/informix/adapter.rb +0 -23
  24. data/lib/arjdbc/jdbc/adapter.rb +3 -1
  25. data/lib/arjdbc/jdbc/adapter_require.rb +3 -1
  26. data/lib/arjdbc/jdbc/base_ext.rb +3 -1
  27. data/lib/arjdbc/jdbc/callbacks.rb +2 -0
  28. data/lib/arjdbc/jdbc/column.rb +2 -0
  29. data/lib/arjdbc/jdbc/connection.rb +2 -0
  30. data/lib/arjdbc/jdbc/connection_methods.rb +2 -0
  31. data/lib/arjdbc/jdbc/error.rb +2 -0
  32. data/lib/arjdbc/jdbc/extension.rb +2 -0
  33. data/lib/arjdbc/jdbc/java.rb +3 -1
  34. data/lib/arjdbc/jdbc/railtie.rb +3 -1
  35. data/lib/arjdbc/jdbc/rake_tasks.rb +3 -1
  36. data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +3 -1
  37. data/lib/arjdbc/jdbc/type_cast.rb +2 -0
  38. data/lib/arjdbc/jdbc/type_converter.rb +2 -0
  39. data/lib/arjdbc/mssql.rb +3 -1
  40. data/lib/arjdbc/mssql/adapter.rb +114 -36
  41. data/lib/arjdbc/mssql/column.rb +19 -1
  42. data/lib/arjdbc/mssql/connection_methods.rb +10 -2
  43. data/lib/arjdbc/mssql/database_limits.rb +9 -0
  44. data/lib/arjdbc/mssql/database_statements.rb +44 -6
  45. data/lib/arjdbc/mssql/errors.rb +2 -0
  46. data/lib/arjdbc/mssql/explain_support.rb +3 -1
  47. data/lib/arjdbc/mssql/extensions/attribute_methods.rb +6 -2
  48. data/lib/arjdbc/mssql/extensions/calculations.rb +2 -0
  49. data/lib/arjdbc/mssql/quoting.rb +38 -0
  50. data/lib/arjdbc/mssql/schema_creation.rb +25 -3
  51. data/lib/arjdbc/mssql/schema_definitions.rb +10 -0
  52. data/lib/arjdbc/mssql/schema_dumper.rb +2 -0
  53. data/lib/arjdbc/mssql/schema_statements.rb +92 -22
  54. data/lib/arjdbc/mssql/transaction.rb +2 -0
  55. data/lib/arjdbc/mssql/types.rb +2 -0
  56. data/lib/arjdbc/mssql/types/binary_types.rb +2 -0
  57. data/lib/arjdbc/mssql/types/date_and_time_types.rb +2 -0
  58. data/lib/arjdbc/mssql/types/deprecated_types.rb +2 -0
  59. data/lib/arjdbc/mssql/types/numeric_types.rb +2 -0
  60. data/lib/arjdbc/mssql/types/string_types.rb +2 -0
  61. data/lib/arjdbc/mssql/utils.rb +2 -0
  62. data/lib/arjdbc/mysql/adapter.rb +59 -21
  63. data/lib/arjdbc/mysql/connection_methods.rb +6 -1
  64. data/lib/arjdbc/postgresql/adapter.rb +257 -219
  65. data/lib/arjdbc/postgresql/base/array_decoder.rb +2 -0
  66. data/lib/arjdbc/postgresql/base/array_encoder.rb +4 -2
  67. data/lib/arjdbc/postgresql/base/array_parser.rb +4 -2
  68. data/lib/arjdbc/postgresql/base/pgconn.rb +2 -0
  69. data/lib/arjdbc/postgresql/column.rb +6 -4
  70. data/lib/arjdbc/postgresql/connection_methods.rb +1 -0
  71. data/lib/arjdbc/postgresql/name.rb +2 -0
  72. data/lib/arjdbc/postgresql/oid_types.rb +7 -4
  73. data/lib/arjdbc/sqlite3/adapter.rb +266 -221
  74. data/lib/arjdbc/sqlite3/connection_methods.rb +26 -4
  75. data/lib/arjdbc/tasks/databases.rake +21 -13
  76. data/lib/arjdbc/tasks/mssql_database_tasks.rb +126 -25
  77. data/lib/arjdbc/util/quoted_cache.rb +3 -1
  78. data/lib/arjdbc/util/serialized_attributes.rb +3 -1
  79. data/lib/arjdbc/util/table_copier.rb +3 -1
  80. data/lib/arjdbc/version.rb +3 -1
  81. data/pom.xml +4 -4
  82. data/rakelib/01-tomcat.rake +2 -2
  83. data/rakelib/rails.rake +1 -1
  84. data/src/java/arjdbc/ArJdbcModule.java +5 -5
  85. data/src/java/arjdbc/jdbc/DriverWrapper.java +1 -9
  86. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +549 -691
  87. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +88 -0
  88. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +13 -23
  89. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +125 -53
  90. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +97 -103
  91. data/src/java/arjdbc/util/DateTimeUtils.java +12 -4
  92. metadata +10 -18
@@ -73,7 +73,6 @@ import org.jruby.RubyBoolean;
73
73
  import org.jruby.RubyClass;
74
74
  import org.jruby.RubyException;
75
75
  import org.jruby.RubyFixnum;
76
- import org.jruby.RubyFloat;
77
76
  import org.jruby.RubyHash;
78
77
  import org.jruby.RubyIO;
79
78
  import org.jruby.RubyInteger;
@@ -86,6 +85,8 @@ import org.jruby.RubyTime;
86
85
  import org.jruby.anno.JRubyMethod;
87
86
  import org.jruby.exceptions.RaiseException;
88
87
  import org.jruby.ext.bigdecimal.RubyBigDecimal;
88
+ import org.jruby.ext.date.RubyDate;
89
+ import org.jruby.ext.date.RubyDateTime;
89
90
  import org.jruby.javasupport.JavaEmbedUtils;
90
91
  import org.jruby.javasupport.JavaUtil;
91
92
  import org.jruby.runtime.Block;
@@ -124,6 +125,7 @@ public class RubyJdbcConnection extends RubyObject {
124
125
  private IRubyObject config;
125
126
  private IRubyObject adapter; // the AbstractAdapter instance we belong to
126
127
  private volatile boolean connected = true;
128
+ private RubyClass attributeClass;
127
129
 
128
130
  private boolean lazy = false; // final once set on initialize
129
131
  private boolean jndi; // final once set on initialize
@@ -132,6 +134,7 @@ public class RubyJdbcConnection extends RubyObject {
132
134
 
133
135
  protected RubyJdbcConnection(Ruby runtime, RubyClass metaClass) {
134
136
  super(runtime, metaClass);
137
+ attributeClass = runtime.getModule("ActiveModel").getClass("Attribute");
135
138
  }
136
139
 
137
140
  private static final ObjectAllocator ALLOCATOR = new ObjectAllocator() {
@@ -147,11 +150,6 @@ public class RubyJdbcConnection extends RubyObject {
147
150
  return JdbcConnection;
148
151
  }
149
152
 
150
- @Deprecated
151
- public static RubyClass getJdbcConnectionClass(final Ruby runtime) {
152
- return getConnectionAdapters(runtime).getClass("JdbcConnection");
153
- }
154
-
155
153
  public static RubyClass getJdbcConnection(final Ruby runtime) {
156
154
  return (RubyClass) getConnectionAdapters(runtime).getConstantAt("JdbcConnection");
157
155
  }
@@ -231,34 +229,30 @@ public class RubyJdbcConnection extends RubyObject {
231
229
 
232
230
  @JRubyMethod(name = "transaction_isolation", alias = "get_transaction_isolation")
233
231
  public IRubyObject get_transaction_isolation(final ThreadContext context) {
234
- return withConnection(context, new Callable<IRubyObject>() {
235
- public IRubyObject call(final Connection connection) throws SQLException {
236
- final int level = connection.getTransactionIsolation();
237
- final String isolationSymbol = formatTransactionIsolationLevel(level);
238
- if ( isolationSymbol == null ) return context.nil;
239
- return context.runtime.newSymbol(isolationSymbol);
240
- }
232
+ return withConnection(context, connection -> {
233
+ final int level = connection.getTransactionIsolation();
234
+ final String isolationSymbol = formatTransactionIsolationLevel(level);
235
+ if ( isolationSymbol == null ) return context.nil;
236
+ return context.runtime.newSymbol(isolationSymbol);
241
237
  });
242
238
  }
243
239
 
244
240
  @JRubyMethod(name = "transaction_isolation=", alias = "set_transaction_isolation")
245
241
  public IRubyObject set_transaction_isolation(final ThreadContext context, final IRubyObject isolation) {
246
- return withConnection(context, new Callable<IRubyObject>() {
247
- public IRubyObject call(final Connection connection) throws SQLException {
248
- final int level;
249
- if ( isolation.isNil() ) {
250
- level = connection.getMetaData().getDefaultTransactionIsolation();
251
- }
252
- else {
253
- level = mapTransactionIsolationLevel(isolation);
254
- }
242
+ return withConnection(context, connection -> {
243
+ final int level;
244
+ if ( isolation.isNil() ) {
245
+ level = connection.getMetaData().getDefaultTransactionIsolation();
246
+ }
247
+ else {
248
+ level = mapTransactionIsolationLevel(isolation);
249
+ }
255
250
 
256
- connection.setTransactionIsolation(level);
251
+ connection.setTransactionIsolation(level);
257
252
 
258
- final String isolationSymbol = formatTransactionIsolationLevel(level);
259
- if ( isolationSymbol == null ) return context.nil;
260
- return context.runtime.newSymbol(isolationSymbol);
261
- }
253
+ final String isolationSymbol = formatTransactionIsolationLevel(level);
254
+ if ( isolationSymbol == null ) return context.nil;
255
+ return context.runtime.newSymbol(isolationSymbol);
262
256
  });
263
257
  }
264
258
 
@@ -306,31 +300,25 @@ public class RubyJdbcConnection extends RubyObject {
306
300
  final IRubyObject[] args) throws SQLException {
307
301
  final IRubyObject isolation = args.length > 0 ? args[0] : null;
308
302
 
309
- return withConnection(context, new Callable<IRubyObject>() {
310
- public IRubyObject call(final Connection connection) throws SQLException {
311
- final DatabaseMetaData metaData = connection.getMetaData();
312
- final boolean supported;
313
- if ( isolation != null && ! isolation.isNil() ) {
314
- final int level = mapTransactionIsolationLevel(isolation);
315
- supported = metaData.supportsTransactionIsolationLevel(level);
316
- }
317
- else {
318
- final int level = metaData.getDefaultTransactionIsolation();
319
- supported = level > Connection.TRANSACTION_NONE; // > 0
320
- }
321
- return context.runtime.newBoolean(supported);
303
+ return withConnection(context, (Callable<IRubyObject>) connection -> {
304
+ final DatabaseMetaData metaData = connection.getMetaData();
305
+ final boolean supported;
306
+ if ( isolation != null && ! isolation.isNil() ) {
307
+ final int level = mapTransactionIsolationLevel(isolation);
308
+ supported = metaData.supportsTransactionIsolationLevel(level);
322
309
  }
310
+ else {
311
+ final int level = metaData.getDefaultTransactionIsolation();
312
+ supported = level > Connection.TRANSACTION_NONE; // > 0
313
+ }
314
+ return context.runtime.newBoolean(supported);
323
315
  });
324
316
  }
325
317
 
326
318
  @JRubyMethod(name = {"begin", "transaction"}, required = 1) // optional isolation argument for AR-4.0
327
319
  public IRubyObject begin(final ThreadContext context, final IRubyObject isolation) {
328
320
  try { // handleException == false so we can handle setTXIsolation
329
- return withConnection(context, false, new Callable<IRubyObject>() {
330
- public IRubyObject call(final Connection connection) throws SQLException {
331
- return beginTransaction(context, connection, isolation == context.nil ? null : isolation);
332
- }
333
- });
321
+ return withConnection(context, false, connection -> beginTransaction(context, connection, isolation == context.nil ? null : isolation));
334
322
  } catch (SQLException e) {
335
323
  return handleException(context, e);
336
324
  }
@@ -339,11 +327,7 @@ public class RubyJdbcConnection extends RubyObject {
339
327
  @JRubyMethod(name = {"begin", "transaction"}) // optional isolation argument for AR-4.0
340
328
  public IRubyObject begin(final ThreadContext context) {
341
329
  try { // handleException == false so we can handle setTXIsolation
342
- return withConnection(context, false, new Callable<IRubyObject>() {
343
- public IRubyObject call(final Connection connection) throws SQLException {
344
- return beginTransaction(context, connection, null);
345
- }
346
- });
330
+ return withConnection(context, false, connection -> beginTransaction(context, connection, null));
347
331
  } catch (SQLException e) {
348
332
  return handleException(context, e);
349
333
  }
@@ -373,12 +357,12 @@ public class RubyJdbcConnection extends RubyObject {
373
357
 
374
358
  @JRubyMethod(name = "commit")
375
359
  public IRubyObject commit(final ThreadContext context) {
376
- final Connection connection = getConnection(true);
377
360
  try {
361
+ final Connection connection = getConnectionInternal(true);
378
362
  if ( ! connection.getAutoCommit() ) {
379
363
  try {
380
364
  connection.commit();
381
- resetSavepoints(context); // if any
365
+ resetSavepoints(context, connection); // if any
382
366
  return context.runtime.newBoolean(true);
383
367
  }
384
368
  finally {
@@ -394,13 +378,13 @@ public class RubyJdbcConnection extends RubyObject {
394
378
 
395
379
  @JRubyMethod(name = "rollback")
396
380
  public IRubyObject rollback(final ThreadContext context) {
397
- final Connection connection = getConnection(true);
398
381
  try {
382
+ final Connection connection = getConnectionInternal(true);
399
383
  if ( ! connection.getAutoCommit() ) {
400
384
  try {
401
385
  connection.rollback();
402
- resetSavepoints(context); // if any
403
- return context.runtime.getTrue();
386
+ resetSavepoints(context, connection); // if any
387
+ return context.tru;
404
388
  } finally {
405
389
  connection.setAutoCommit(true);
406
390
  }
@@ -414,11 +398,9 @@ public class RubyJdbcConnection extends RubyObject {
414
398
 
415
399
  @JRubyMethod(name = "supports_savepoints?")
416
400
  public IRubyObject supports_savepoints_p(final ThreadContext context) throws SQLException {
417
- return withConnection(context, new Callable<IRubyObject>() {
418
- public IRubyObject call(final Connection connection) throws SQLException {
419
- final DatabaseMetaData metaData = connection.getMetaData();
420
- return context.runtime.newBoolean( metaData.supportsSavepoints() );
421
- }
401
+ return withConnection(context, (Callable<IRubyObject>) connection -> {
402
+ final DatabaseMetaData metaData = connection.getMetaData();
403
+ return context.runtime.newBoolean( metaData.supportsSavepoints() );
422
404
  });
423
405
  }
424
406
 
@@ -429,8 +411,8 @@ public class RubyJdbcConnection extends RubyObject {
429
411
 
430
412
  @JRubyMethod(name = "create_savepoint", required = 1)
431
413
  public IRubyObject create_savepoint(final ThreadContext context, IRubyObject name) {
432
- final Connection connection = getConnection(true);
433
414
  try {
415
+ final Connection connection = getConnectionInternal(true);
434
416
  connection.setAutoCommit(false);
435
417
 
436
418
  final Savepoint savepoint ;
@@ -458,8 +440,8 @@ public class RubyJdbcConnection extends RubyObject {
458
440
  public IRubyObject rollback_savepoint(final ThreadContext context, final IRubyObject name) {
459
441
  if (name == context.nil) throw context.runtime.newArgumentError("nil savepoint name given");
460
442
 
461
- final Connection connection = getConnection(true);
462
443
  try {
444
+ final Connection connection = getConnectionInternal(true);
463
445
  Savepoint savepoint = getSavepoints(context).get(name);
464
446
  if ( savepoint == null ) {
465
447
  throw context.runtime.newRuntimeError("could not rollback savepoint: '" + name + "' (not set)");
@@ -476,7 +458,6 @@ public class RubyJdbcConnection extends RubyObject {
476
458
  public IRubyObject release_savepoint(final ThreadContext context, final IRubyObject name) {
477
459
  if (name == context.nil) throw context.runtime.newArgumentError("nil savepoint name given");
478
460
 
479
- final Connection connection = getConnection(true);
480
461
  try {
481
462
  Object savepoint = getSavepoints(context).remove(name);
482
463
 
@@ -487,6 +468,7 @@ public class RubyJdbcConnection extends RubyObject {
487
468
  savepoint = ((IRubyObject) savepoint).toJava(Savepoint.class);
488
469
  }
489
470
 
471
+ final Connection connection = getConnectionInternal(true);
490
472
  releaseSavepoint(connection, (Savepoint) savepoint);
491
473
  return context.nil;
492
474
  }
@@ -525,7 +507,7 @@ public class RubyJdbcConnection extends RubyObject {
525
507
  }
526
508
 
527
509
  @SuppressWarnings("unchecked")
528
- private final Map<IRubyObject, Savepoint> getSavepoints(final boolean init) {
510
+ private Map<IRubyObject, Savepoint> getSavepoints(final boolean init) {
529
511
  if ( hasInternalVariable("savepoints") ) {
530
512
  return (Map<IRubyObject, Savepoint>) getInternalVariable("savepoints");
531
513
  }
@@ -537,7 +519,7 @@ public class RubyJdbcConnection extends RubyObject {
537
519
  return null;
538
520
  }
539
521
 
540
- protected boolean resetSavepoints(final ThreadContext context) {
522
+ protected boolean resetSavepoints(final ThreadContext context, final Connection connection) throws SQLException {
541
523
  if ( hasInternalVariable("savepoints") ) {
542
524
  removeInternalVariable("savepoints");
543
525
  return true;
@@ -545,13 +527,6 @@ public class RubyJdbcConnection extends RubyObject {
545
527
  return false;
546
528
  }
547
529
 
548
- @Deprecated // second argument is now mandatory - only kept for compatibility
549
- @JRubyMethod(required = 1)
550
- public final IRubyObject initialize(final ThreadContext context, final IRubyObject config) {
551
- doInitialize(context, config, context.nil);
552
- return this;
553
- }
554
-
555
530
  @JRubyMethod(required = 2)
556
531
  public final IRubyObject initialize(final ThreadContext context, final IRubyObject config, final IRubyObject adapter) {
557
532
  doInitialize(context, config, adapter);
@@ -559,12 +534,17 @@ public class RubyJdbcConnection extends RubyObject {
559
534
  }
560
535
 
561
536
  protected void doInitialize(final ThreadContext context, final IRubyObject config, final IRubyObject adapter) {
562
- this.config = config; this.adapter = adapter;
537
+ this.config = config;
538
+ this.adapter = adapter;
563
539
 
564
540
  this.jndi = setupConnectionFactory(context);
565
541
  this.lazy = jndi; // JNDIs are lazy by default otherwise eager
566
542
  try {
567
- initConnection(context);
543
+ if (adapter == null || adapter == context.nil) {
544
+ warn(context, "adapter not set, please pass adapter on JdbcConnection#initialize(config, adapter)");
545
+ }
546
+
547
+ if (!lazy) setConnection(newConnection());
568
548
  }
569
549
  catch (SQLException e) {
570
550
  String message = e.getMessage();
@@ -575,7 +555,7 @@ public class RubyJdbcConnection extends RubyObject {
575
555
  IRubyObject value = getConfigValue(context, "configure_connection");
576
556
  if ( value == context.nil ) this.configureConnection = true;
577
557
  else {
578
- this.configureConnection = value != context.runtime.getFalse();
558
+ this.configureConnection = value != context.fals;
579
559
  }
580
560
 
581
561
  IRubyObject jdbcFetchSize = getConfigValue(context, "jdbc_fetch_size");
@@ -586,7 +566,6 @@ public class RubyJdbcConnection extends RubyObject {
586
566
 
587
567
  @JRubyMethod(name = "adapter")
588
568
  public IRubyObject adapter(final ThreadContext context) {
589
- final IRubyObject adapter = getAdapter();
590
569
  return adapter == null ? context.nil : adapter;
591
570
  }
592
571
 
@@ -601,43 +580,9 @@ public class RubyJdbcConnection extends RubyObject {
601
580
  return factory;
602
581
  }
603
582
 
604
- /**
605
- * Called during <code>initialize</code> after the connection factory
606
- * has been set to check if we can connect and/or perform any initialization
607
- * necessary.
608
- * <br/>
609
- * NOTE: connection has not been configured at this point,
610
- * nor should we retry - we're creating a brand new JDBC connection
611
- *
612
- * @param context
613
- * @return connection
614
- */
615
- @Deprecated
616
- @JRubyMethod(name = "init_connection")
617
- public synchronized IRubyObject init_connection(final ThreadContext context) {
618
- try {
619
- return initConnection(context);
620
- }
621
- catch (SQLException e) {
622
- return handleException(context, e); // throws
623
- }
624
- }
625
-
626
- private IRubyObject initConnection(final ThreadContext context) throws SQLException {
627
- final IRubyObject adapter = getAdapter(); // self.adapter
628
- if ( adapter == null || adapter == context.nil ) {
629
- warn(context, "adapter not set, please pass adapter on JdbcConnection#initialize(config, adapter)");
630
- }
631
-
632
- if ( ! lazy ) setConnection( newConnection() );
633
-
634
- return context.nil;
635
- }
636
-
637
583
  private void configureConnection() {
638
584
  if ( ! configureConnection ) return; // return false;
639
585
 
640
- final IRubyObject adapter = getAdapter(); // self.adapter
641
586
  if ( adapter != null && ! adapter.isNil() ) {
642
587
  if ( adapter.respondsTo("configure_connection") ) {
643
588
  final ThreadContext context = getRuntime().getCurrentContext();
@@ -659,7 +604,7 @@ public class RubyJdbcConnection extends RubyObject {
659
604
 
660
605
  @JRubyMethod(name = "jdbc_connection", alias = "connection", required = 1)
661
606
  public final IRubyObject connection(final ThreadContext context, final IRubyObject unwrap) {
662
- if ( unwrap == context.nil || unwrap == context.runtime.getFalse() ) {
607
+ if ( unwrap == context.nil || unwrap == context.fals ) {
663
608
  return connection(context);
664
609
  }
665
610
  Connection connection = connectionImpl(context);
@@ -668,11 +613,7 @@ public class RubyJdbcConnection extends RubyObject {
668
613
  return convertJavaToRuby( connection.unwrap(Connection.class) );
669
614
  }
670
615
  }
671
- catch (AbstractMethodError e) {
672
- debugStackTrace(context, e);
673
- warn(context, "driver/pool connection does not support unwrapping: " + e);
674
- }
675
- catch (SQLException e) {
616
+ catch (AbstractMethodError | SQLException e) {
676
617
  debugStackTrace(context, e);
677
618
  warn(context, "driver/pool connection does not support unwrapping: " + e);
678
619
  }
@@ -695,18 +636,25 @@ public class RubyJdbcConnection extends RubyObject {
695
636
 
696
637
  @JRubyMethod(name = "active?", alias = "valid?")
697
638
  public RubyBoolean active_p(final ThreadContext context) {
698
- if ( ! connected ) return context.runtime.getFalse();
699
- if ( isJndi() ) {
639
+ if ( ! connected ) return context.fals;
640
+ if (jndi) {
700
641
  // for JNDI the data-source / pool is supposed to
701
642
  // manage connections for us thus no valid check!
702
643
  boolean active = getConnectionFactory() != null;
703
644
  return context.runtime.newBoolean( active );
704
645
  }
705
- final Connection connection = getConnection();
706
- if ( connection == null ) return context.runtime.getFalse(); // unlikely
646
+ final Connection connection = getConnection(false);
647
+ if ( connection == null ) return context.fals; // unlikely
707
648
  return context.runtime.newBoolean( isConnectionValid(context, connection) );
708
649
  }
709
650
 
651
+ @JRubyMethod(name = "really_valid?")
652
+ public RubyBoolean really_valid_p(final ThreadContext context) {
653
+ final Connection connection = getConnection(true);
654
+ if (connection == null) return context.fals;
655
+ return context.runtime.newBoolean(isConnectionValid(context, connection));
656
+ }
657
+
710
658
  @JRubyMethod(name = "disconnect!")
711
659
  public synchronized IRubyObject disconnect(final ThreadContext context) {
712
660
  setConnection(null); connected = false;
@@ -727,38 +675,43 @@ public class RubyJdbcConnection extends RubyObject {
727
675
 
728
676
  private void connectImpl(final boolean forceConnection) throws SQLException {
729
677
  setConnection( forceConnection ? newConnection() : null );
730
- if ( forceConnection ) configureConnection();
678
+ if (forceConnection) {
679
+ if (getConnectionImpl() == null) throw new SQLException("Didn't get a connection. Wrong URL?");
680
+ configureConnection();
681
+ }
731
682
  }
732
683
 
733
684
  @JRubyMethod(name = "read_only?")
734
685
  public IRubyObject is_read_only(final ThreadContext context) {
735
- final Connection connection = getConnection(false);
736
- if ( connection != null ) {
737
- try {
738
- return context.runtime.newBoolean( connection.isReadOnly() );
686
+ try {
687
+ final Connection connection = getConnectionInternal(false);
688
+ if (connection != null) {
689
+ return context.runtime.newBoolean(connection.isReadOnly());
739
690
  }
740
- catch (SQLException e) { return handleException(context, e); }
691
+ } catch (SQLException e) {
692
+ return handleException(context, e);
741
693
  }
742
694
  return context.nil;
743
695
  }
744
696
 
745
697
  @JRubyMethod(name = "read_only=")
746
698
  public IRubyObject set_read_only(final ThreadContext context, final IRubyObject flag) {
747
- final Connection connection = getConnection(true);
748
699
  try {
700
+ final Connection connection = getConnectionInternal(true);
749
701
  connection.setReadOnly( flag.isTrue() );
750
702
  return context.runtime.newBoolean( connection.isReadOnly() );
703
+ } catch (SQLException e) {
704
+ return handleException(context, e);
751
705
  }
752
- catch (SQLException e) { return handleException(context, e); }
753
706
  }
754
707
 
755
708
  @JRubyMethod(name = { "open?" /* "conn?" */ })
756
709
  public IRubyObject open_p(final ThreadContext context) {
757
- final Connection connection = getConnection(false);
710
+ try {
711
+ final Connection connection = getConnectionInternal(false);
758
712
 
759
- if (connection == null) return context.runtime.getFalse();
713
+ if (connection == null) return context.fals;
760
714
 
761
- try {
762
715
  // NOTE: isClosed method generally cannot be called to determine
763
716
  // whether a connection to a database is valid or invalid ...
764
717
  return context.runtime.newBoolean(!connection.isClosed());
@@ -771,10 +724,10 @@ public class RubyJdbcConnection extends RubyObject {
771
724
  public IRubyObject close(final ThreadContext context) {
772
725
  final Connection connection = getConnection(false);
773
726
 
774
- if (connection == null) return context.runtime.getFalse();
727
+ if (connection == null) return context.fals;
775
728
 
776
729
  try {
777
- if (connection.isClosed()) return context.runtime.getFalse();
730
+ if (connection.isClosed()) return context.fals;
778
731
 
779
732
  setConnection(null); // does connection.close();
780
733
  } catch (Exception e) {
@@ -784,69 +737,65 @@ public class RubyJdbcConnection extends RubyObject {
784
737
 
785
738
  // ActiveRecord expects a closed connection to not try and re-open a connection
786
739
  // whereas JNDI expects that.
787
- if (!isJndi()) disconnect(context);
740
+ if (!jndi) disconnect(context);
788
741
 
789
- return context.runtime.getTrue();
742
+ return context.tru;
790
743
  }
791
744
 
792
745
  @JRubyMethod(name = "database_name")
793
746
  public IRubyObject database_name(final ThreadContext context) {
794
- return withConnection(context, new Callable<IRubyObject>() {
795
- public IRubyObject call(final Connection connection) throws SQLException {
796
- String name = connection.getCatalog();
797
- if ( name == null ) {
798
- name = connection.getMetaData().getUserName();
799
- if ( name == null ) return context.nil;
800
- }
801
- return context.runtime.newString(name);
747
+ return withConnection(context, connection -> {
748
+ String name = connection.getCatalog();
749
+ if ( name == null ) {
750
+ name = connection.getMetaData().getUserName();
751
+ if ( name == null ) return context.nil;
802
752
  }
753
+ return context.runtime.newString(name);
803
754
  });
804
755
  }
805
756
 
806
757
  @JRubyMethod(name = "execute", required = 1)
807
758
  public IRubyObject execute(final ThreadContext context, final IRubyObject sql) {
808
759
  final String query = sqlString(sql);
809
- return withConnection(context, new Callable<IRubyObject>() {
810
- public IRubyObject call(final Connection connection) throws SQLException {
811
- Statement statement = null;
812
- try {
813
- statement = createStatement(context, connection);
814
-
815
- // For DBs that do support multiple statements, lets return the last result set
816
- // to be consistent with AR
817
- boolean hasResultSet = doExecute(statement, query);
818
- int updateCount = statement.getUpdateCount();
760
+ return withConnection(context, connection -> {
761
+ Statement statement = null;
762
+ try {
763
+ statement = createStatement(context, connection);
819
764
 
820
- IRubyObject result = context.nil; // If no results, return nil
821
- ResultSet resultSet;
765
+ // For DBs that do support multiple statements, lets return the last result set
766
+ // to be consistent with AR
767
+ boolean hasResultSet = doExecute(statement, query);
768
+ int updateCount = statement.getUpdateCount();
822
769
 
823
- while (hasResultSet || updateCount != -1) {
770
+ IRubyObject result = context.nil; // If no results, return nil
771
+ ResultSet resultSet;
824
772
 
825
- if (hasResultSet) {
826
- resultSet = statement.getResultSet();
773
+ while (hasResultSet || updateCount != -1) {
827
774
 
828
- // Unfortunately the result set gets closed when getMoreResults()
829
- // is called, so we have to process the result sets as we get them
830
- // this shouldn't be an issue in most cases since we're only getting 1 result set anyways
831
- result = mapExecuteResult(context, connection, resultSet);
832
- resultSet.close();
833
- } else {
834
- result = context.runtime.newFixnum(updateCount);
835
- }
775
+ if (hasResultSet) {
776
+ resultSet = statement.getResultSet();
836
777
 
837
- // Check to see if there is another result set
838
- hasResultSet = statement.getMoreResults();
839
- updateCount = statement.getUpdateCount();
778
+ // Unfortunately the result set gets closed when getMoreResults()
779
+ // is called, so we have to process the result sets as we get them
780
+ // this shouldn't be an issue in most cases since we're only getting 1 result set anyways
781
+ result = mapExecuteResult(context, connection, resultSet);
782
+ resultSet.close();
783
+ } else {
784
+ result = context.runtime.newFixnum(updateCount);
840
785
  }
841
786
 
842
- return result;
843
-
844
- } catch (final SQLException e) {
845
- debugErrorSQL(context, query);
846
- throw e;
847
- } finally {
848
- close(statement);
787
+ // Check to see if there is another result set
788
+ hasResultSet = statement.getMoreResults();
789
+ updateCount = statement.getUpdateCount();
849
790
  }
791
+
792
+ return result;
793
+
794
+ } catch (final SQLException e) {
795
+ debugErrorSQL(context, query);
796
+ throw e;
797
+ } finally {
798
+ close(statement);
850
799
  }
851
800
  });
852
801
  }
@@ -885,66 +834,100 @@ public class RubyJdbcConnection extends RubyObject {
885
834
  return mapQueryResult(context, connection, resultSet);
886
835
  }
887
836
 
837
+ private static String[] createStatementPk(IRubyObject pk) {
838
+ String[] statementPk;
839
+ if (pk instanceof RubyArray) {
840
+ RubyArray ary = (RubyArray) pk;
841
+ int size = ary.size();
842
+ statementPk = new String[size];
843
+ for (int i = 0; i < size; i++) {
844
+ statementPk[i] = sqlString(ary.eltInternal(i));
845
+ }
846
+ } else {
847
+ statementPk = new String[] { sqlString(pk) };
848
+ }
849
+ return statementPk;
850
+ }
851
+
888
852
  /**
889
853
  * Executes an INSERT SQL statement
890
854
  * @param context
891
855
  * @param sql
856
+ * @param pk Rails PK
892
857
  * @return ActiveRecord::Result
893
858
  * @throws SQLException
894
859
  */
895
- @JRubyMethod(name = "execute_insert", required = 1)
896
- public IRubyObject execute_insert(final ThreadContext context, final IRubyObject sql) {
897
- return withConnection(context, new Callable<IRubyObject>() {
898
- public IRubyObject call(final Connection connection) throws SQLException {
899
- Statement statement = null;
900
- final String query = sqlString(sql);
901
- try {
860
+ @JRubyMethod(name = "execute_insert_pk", required = 2)
861
+ public IRubyObject execute_insert_pk(final ThreadContext context, final IRubyObject sql, final IRubyObject pk) {
862
+ return withConnection(context, connection -> {
863
+ Statement statement = null;
864
+ final String query = sqlString(sql);
865
+ try {
902
866
 
903
- statement = createStatement(context, connection);
904
- statement.executeUpdate(query, Statement.RETURN_GENERATED_KEYS);
905
- return mapGeneratedKeys(context, connection, statement);
867
+ statement = createStatement(context, connection);
906
868
 
907
- } catch (final SQLException e) {
908
- debugErrorSQL(context, query);
909
- throw e;
910
- } finally {
911
- close(statement);
869
+ if (pk == context.nil || pk == context.fals || !supportsGeneratedKeys(connection)) {
870
+ statement.executeUpdate(query, Statement.RETURN_GENERATED_KEYS);
871
+ } else {
872
+ statement.executeUpdate(query, createStatementPk(pk));
912
873
  }
874
+
875
+ return mapGeneratedKeys(context, connection, statement);
876
+ } catch (final SQLException e) {
877
+ debugErrorSQL(context, query);
878
+ throw e;
879
+ } finally {
880
+ close(statement);
913
881
  }
914
882
  });
915
883
  }
916
884
 
885
+ @Deprecated
886
+ @JRubyMethod(name = "execute_insert", required = 1)
887
+ public IRubyObject execute_insert(final ThreadContext context, final IRubyObject sql) {
888
+ return execute_insert_pk(context, sql, context.nil);
889
+ }
890
+
917
891
  /**
918
892
  * Executes an INSERT SQL statement using a prepared statement
919
893
  * @param context
920
894
  * @param sql
921
895
  * @param binds RubyArray of values to be bound to the query
896
+ * @param pk Rails PK
922
897
  * @return ActiveRecord::Result
923
898
  * @throws SQLException
924
899
  */
925
- @JRubyMethod(name = "execute_insert", required = 2)
926
- public IRubyObject execute_insert(final ThreadContext context, final IRubyObject sql, final IRubyObject binds) {
927
- return withConnection(context, new Callable<IRubyObject>() {
928
- public IRubyObject call(final Connection connection) throws SQLException {
929
- PreparedStatement statement = null;
930
- final String query = sqlString(sql);
931
- try {
932
-
900
+ @JRubyMethod(name = "execute_insert_pk", required = 3)
901
+ public IRubyObject execute_insert_pk(final ThreadContext context, final IRubyObject sql, final IRubyObject binds,
902
+ final IRubyObject pk) {
903
+ return withConnection(context, connection -> {
904
+ PreparedStatement statement = null;
905
+ final String query = sqlString(sql);
906
+ try {
907
+ if (pk == context.nil || pk == context.fals || !supportsGeneratedKeys(connection)) {
933
908
  statement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
934
- setStatementParameters(context, connection, statement, (RubyArray) binds);
935
- statement.executeUpdate();
936
- return mapGeneratedKeys(context, connection, statement);
937
-
938
- } catch (final SQLException e) {
939
- debugErrorSQL(context, query);
940
- throw e;
941
- } finally {
942
- close(statement);
909
+ } else {
910
+ statement = connection.prepareStatement(query, createStatementPk(pk));
943
911
  }
912
+
913
+ setStatementParameters(context, connection, statement, (RubyArray) binds);
914
+ statement.executeUpdate();
915
+ return mapGeneratedKeys(context, connection, statement);
916
+ } catch (final SQLException e) {
917
+ debugErrorSQL(context, query);
918
+ throw e;
919
+ } finally {
920
+ close(statement);
944
921
  }
945
922
  });
946
923
  }
947
924
 
925
+ @Deprecated
926
+ @JRubyMethod(name = "execute_insert", required = 2)
927
+ public IRubyObject execute_insert(final ThreadContext context, final IRubyObject binds, final IRubyObject sql) {
928
+ return execute_insert_pk(context, sql, binds, context.nil);
929
+ }
930
+
948
931
  /**
949
932
  * Executes an UPDATE (DELETE) SQL statement
950
933
  * @param context
@@ -954,22 +937,20 @@ public class RubyJdbcConnection extends RubyObject {
954
937
  */
955
938
  @JRubyMethod(name = {"execute_update", "execute_delete"}, required = 1)
956
939
  public IRubyObject execute_update(final ThreadContext context, final IRubyObject sql) {
957
- return withConnection(context, new Callable<IRubyObject>() {
958
- public IRubyObject call(final Connection connection) throws SQLException {
959
- Statement statement = null;
960
- final String query = sqlString(sql);
940
+ return withConnection(context, (Callable<IRubyObject>) connection -> {
941
+ Statement statement = null;
942
+ final String query = sqlString(sql);
961
943
 
962
- try {
963
- statement = createStatement(context, connection);
944
+ try {
945
+ statement = createStatement(context, connection);
964
946
 
965
- final int rowCount = statement.executeUpdate(query);
966
- return context.runtime.newFixnum(rowCount);
967
- } catch (final SQLException e) {
968
- debugErrorSQL(context, query);
969
- throw e;
970
- } finally {
971
- close(statement);
972
- }
947
+ final int rowCount = statement.executeUpdate(query);
948
+ return context.runtime.newFixnum(rowCount);
949
+ } catch (final SQLException e) {
950
+ debugErrorSQL(context, query);
951
+ throw e;
952
+ } finally {
953
+ close(statement);
973
954
  }
974
955
  });
975
956
  }
@@ -985,21 +966,19 @@ public class RubyJdbcConnection extends RubyObject {
985
966
  */
986
967
  @JRubyMethod(name = {"execute_prepared_update", "execute_prepared_delete"}, required = 2)
987
968
  public IRubyObject execute_prepared_update(final ThreadContext context, final IRubyObject sql, final IRubyObject binds) {
988
- return withConnection(context, new Callable<IRubyObject>() {
989
- public IRubyObject call(final Connection connection) throws SQLException {
990
- PreparedStatement statement = null;
991
- final String query = sqlString(sql);
992
- try {
993
- statement = connection.prepareStatement(query);
994
- setStatementParameters(context, connection, statement, (RubyArray) binds);
995
- final int rowCount = statement.executeUpdate();
996
- return context.runtime.newFixnum(rowCount);
997
- } catch (final SQLException e) {
998
- debugErrorSQL(context, query);
999
- throw e;
1000
- } finally {
1001
- close(statement);
1002
- }
969
+ return withConnection(context, (Callable<IRubyObject>) connection -> {
970
+ PreparedStatement statement = null;
971
+ final String query = sqlString(sql);
972
+ try {
973
+ statement = connection.prepareStatement(query);
974
+ setStatementParameters(context, connection, statement, (RubyArray) binds);
975
+ final int rowCount = statement.executeUpdate();
976
+ return context.runtime.newFixnum(rowCount);
977
+ } catch (final SQLException e) {
978
+ debugErrorSQL(context, query);
979
+ throw e;
980
+ } finally {
981
+ close(statement);
1003
982
  }
1004
983
  });
1005
984
  }
@@ -1028,12 +1007,12 @@ public class RubyJdbcConnection extends RubyObject {
1028
1007
  binds = null;
1029
1008
  } else { // (sql, binds)
1030
1009
  maxRows = 0;
1031
- binds = (RubyArray) TypeConverter.checkArrayType(args[1]);
1010
+ binds = (RubyArray) TypeConverter.checkArrayType(context, args[1]);
1032
1011
  }
1033
1012
  break;
1034
1013
  case 3: // (sql, max_rows, binds)
1035
1014
  maxRows = RubyNumeric.fix2int(args[1]);
1036
- binds = (RubyArray) TypeConverter.checkArrayType(args[2]);
1015
+ binds = (RubyArray) TypeConverter.checkArrayType(context, args[2]);
1037
1016
  break;
1038
1017
  default: // (sql) 1-arg
1039
1018
  maxRows = 0;
@@ -1046,50 +1025,48 @@ public class RubyJdbcConnection extends RubyObject {
1046
1025
 
1047
1026
  private IRubyObject doExecuteQueryRaw(final ThreadContext context,
1048
1027
  final String query, final int maxRows, final Block block, final RubyArray binds) {
1049
- return withConnection(context, new Callable<IRubyObject>() {
1050
- public IRubyObject call(final Connection connection) throws SQLException {
1051
- Statement statement = null; boolean hasResult;
1052
- try {
1053
- if ( binds == null || binds.isEmpty()) { // plain statement
1054
- statement = createStatement(context, connection);
1055
- statement.setMaxRows(maxRows); // zero means there is no limit
1056
- hasResult = statement.execute(query);
1057
- }
1058
- else {
1059
- final PreparedStatement prepStatement;
1060
- statement = prepStatement = connection.prepareStatement(query);
1061
- if (fetchSize != 0) statement.setFetchSize(fetchSize);
1062
- statement.setMaxRows(maxRows); // zero means there is no limit
1063
- setStatementParameters(context, connection, prepStatement, binds);
1064
- hasResult = prepStatement.execute();
1065
- }
1028
+ return withConnection(context, connection -> {
1029
+ Statement statement = null; boolean hasResult;
1030
+ try {
1031
+ if ( binds == null || binds.isEmpty()) { // plain statement
1032
+ statement = createStatement(context, connection);
1033
+ statement.setMaxRows(maxRows); // zero means there is no limit
1034
+ hasResult = statement.execute(query);
1035
+ }
1036
+ else {
1037
+ final PreparedStatement prepStatement;
1038
+ statement = prepStatement = connection.prepareStatement(query);
1039
+ if (fetchSize != 0) statement.setFetchSize(fetchSize);
1040
+ statement.setMaxRows(maxRows); // zero means there is no limit
1041
+ setStatementParameters(context, connection, prepStatement, binds);
1042
+ hasResult = prepStatement.execute();
1043
+ }
1066
1044
 
1067
- if (block.isGiven()) {
1068
- if (hasResult) {
1069
- // yield(id1, name1) ... row 1 result data
1070
- // yield(id2, name2) ... row 2 result data
1071
- return yieldResultRows(context, connection, statement.getResultSet(), block);
1072
- }
1073
- return context.nil;
1074
- }
1045
+ if (block.isGiven()) {
1075
1046
  if (hasResult) {
1076
- return mapToRawResult(context, connection, statement.getResultSet(), false);
1047
+ // yield(id1, name1) ... row 1 result data
1048
+ // yield(id2, name2) ... row 2 result data
1049
+ return yieldResultRows(context, connection, statement.getResultSet(), block);
1077
1050
  }
1078
- return context.runtime.newEmptyArray();
1079
- }
1080
- catch (final SQLException e) {
1081
- debugErrorSQL(context, query);
1082
- throw e;
1051
+ return context.nil;
1083
1052
  }
1084
- finally {
1085
- close(statement);
1053
+ if (hasResult) {
1054
+ return mapToRawResult(context, connection, statement.getResultSet(), false);
1086
1055
  }
1056
+ return context.runtime.newEmptyArray();
1057
+ }
1058
+ catch (final SQLException e) {
1059
+ debugErrorSQL(context, query);
1060
+ throw e;
1061
+ }
1062
+ finally {
1063
+ close(statement);
1087
1064
  }
1088
1065
  });
1089
1066
  }
1090
1067
 
1091
1068
  protected static String sqlString(final IRubyObject sql) {
1092
- return sql instanceof RubyString ? ((RubyString) sql).decodeString() : sql.convertToString().decodeString();
1069
+ return sql.convertToString().decodeString();
1093
1070
  }
1094
1071
 
1095
1072
  /**
@@ -1102,26 +1079,46 @@ public class RubyJdbcConnection extends RubyObject {
1102
1079
  */
1103
1080
  @JRubyMethod(required = 1)
1104
1081
  public IRubyObject execute_query(final ThreadContext context, final IRubyObject sql) {
1105
- return withConnection(context, new Callable<IRubyObject>() {
1106
- public IRubyObject call(final Connection connection) throws SQLException {
1107
- Statement statement = null;
1108
- final String query = sqlString(sql);
1109
- try {
1110
- statement = createStatement(context, connection);
1082
+ return withConnection(context, connection -> {
1083
+ Statement statement = null;
1084
+ final String query = sqlString(sql);
1085
+ try {
1086
+ statement = createStatement(context, connection);
1111
1087
 
1112
- // At least until AR 5.1 #exec_query still gets called for things that don't return results in some cases :(
1113
- if (statement.execute(query)) {
1114
- return mapQueryResult(context, connection, statement.getResultSet());
1115
- }
1088
+ // At least until AR 5.1 #exec_query still gets called for things that don't return results in some cases :(
1089
+ if (statement.execute(query)) {
1090
+ return mapQueryResult(context, connection, statement.getResultSet());
1091
+ }
1116
1092
 
1117
- return context.nil;
1093
+ return newEmptyResult(context);
1118
1094
 
1119
- } catch (final SQLException e) {
1120
- debugErrorSQL(context, query);
1121
- throw e;
1122
- } finally {
1123
- close(statement);
1124
- }
1095
+ } catch (final SQLException e) {
1096
+ debugErrorSQL(context, query);
1097
+ throw e;
1098
+ } finally {
1099
+ close(statement);
1100
+ }
1101
+ });
1102
+ }
1103
+
1104
+ @JRubyMethod(required = 1)
1105
+ public IRubyObject get_first_value(final ThreadContext context, final IRubyObject sql) {
1106
+ return withConnection(context, connection -> {
1107
+ Statement statement = null;
1108
+ final String query = sqlString(sql);
1109
+ try {
1110
+ statement = createStatement(context, connection);
1111
+ statement.execute(query);
1112
+ ResultSet rs = statement.getResultSet();
1113
+ if (rs == null || !rs.next()) return context.nil;
1114
+
1115
+ return jdbcToRuby(context, context.getRuntime(), 1, rs.getMetaData().getColumnType(1), rs);
1116
+
1117
+ } catch (final SQLException e) {
1118
+ debugErrorSQL(context, query);
1119
+ throw e;
1120
+ } finally {
1121
+ close(statement);
1125
1122
  }
1126
1123
  });
1127
1124
  }
@@ -1134,13 +1131,11 @@ public class RubyJdbcConnection extends RubyObject {
1134
1131
  */
1135
1132
  @JRubyMethod(required = 1)
1136
1133
  public IRubyObject prepare_statement(final ThreadContext context, final IRubyObject sql) {
1137
- return withConnection(context, new Callable<IRubyObject>() {
1138
- public IRubyObject call(Connection connection) throws SQLException {
1139
- final String query = sql.convertToString().getUnicodeValue();
1140
- PreparedStatement statement = connection.prepareStatement(query);
1141
- if (fetchSize != 0) statement.setFetchSize(fetchSize);
1142
- return JavaUtil.convertJavaToRuby(context.runtime, statement);
1143
- }
1134
+ return withConnection(context, connection -> {
1135
+ final String query = sql.convertToString().getUnicodeValue();
1136
+ PreparedStatement statement = connection.prepareStatement(query);
1137
+ if (fetchSize != 0) statement.setFetchSize(fetchSize);
1138
+ return JavaUtil.convertJavaToRuby(context.runtime, statement);
1144
1139
  });
1145
1140
  }
1146
1141
 
@@ -1163,40 +1158,40 @@ public class RubyJdbcConnection extends RubyObject {
1163
1158
  @JRubyMethod(required = 3)
1164
1159
  public IRubyObject execute_prepared_query(final ThreadContext context, final IRubyObject sql,
1165
1160
  final IRubyObject binds, final IRubyObject cachedStatement) {
1166
- return withConnection(context, new Callable<IRubyObject>() {
1167
- public IRubyObject call(final Connection connection) throws SQLException {
1168
- final boolean cached = !(cachedStatement == null || cachedStatement.isNil());
1169
- final String query = sql.convertToString().getUnicodeValue();
1170
- PreparedStatement statement = null;
1161
+ return withConnection(context, connection -> {
1162
+ final boolean cached = !(cachedStatement == null || cachedStatement.isNil());
1163
+ String query = null;
1164
+ PreparedStatement statement = null;
1171
1165
 
1172
- try {
1173
- if (cached) {
1174
- statement = (PreparedStatement) JavaEmbedUtils.rubyToJava(cachedStatement);
1175
- } else {
1176
- statement = connection.prepareStatement(query);
1177
- if (fetchSize != 0) statement.setFetchSize(fetchSize);
1178
- }
1166
+ try {
1167
+ if (cached) {
1168
+ statement = (PreparedStatement) JavaEmbedUtils.rubyToJava(cachedStatement);
1169
+ } else {
1170
+ query = sql.convertToString().getUnicodeValue();
1171
+ statement = connection.prepareStatement(query);
1172
+ if (fetchSize != 0) statement.setFetchSize(fetchSize);
1173
+ }
1179
1174
 
1180
- setStatementParameters(context, connection, statement, (RubyArray) binds);
1175
+ setStatementParameters(context, connection, statement, (RubyArray) binds);
1181
1176
 
1182
- if (statement.execute()) {
1183
- ResultSet resultSet = statement.getResultSet();
1184
- IRubyObject results = mapQueryResult(context, connection, resultSet);
1185
- resultSet.close();
1177
+ if (statement.execute()) {
1178
+ ResultSet resultSet = statement.getResultSet();
1179
+ IRubyObject results = mapQueryResult(context, connection, resultSet);
1180
+ resultSet.close();
1186
1181
 
1187
- return results;
1188
- } else {
1189
- return context.nil;
1190
- }
1191
- } catch (final SQLException e) {
1192
- debugErrorSQL(context, query);
1193
- throw e;
1194
- } finally {
1195
- if ( cached ) {
1196
- statement.clearParameters();
1197
- } else {
1198
- close(statement);
1199
- }
1182
+ return results;
1183
+ } else {
1184
+ return newEmptyResult(context);
1185
+ }
1186
+ } catch (final SQLException e) {
1187
+ if (query == null) query = sql.convertToString().getUnicodeValue();
1188
+ debugErrorSQL(context, query);
1189
+ throw e;
1190
+ } finally {
1191
+ if ( cached ) {
1192
+ statement.clearParameters();
1193
+ } else {
1194
+ close(statement);
1200
1195
  }
1201
1196
  }
1202
1197
  });
@@ -1208,35 +1203,6 @@ public class RubyJdbcConnection extends RubyObject {
1208
1203
  return mapToResult(context, connection, resultSet, columns);
1209
1204
  }
1210
1205
 
1211
- /**
1212
- * @deprecated please do not use this method
1213
- */
1214
- @Deprecated // only used by Oracle adapter - also it's really a bad idea
1215
- @JRubyMethod(name = "execute_id_insert", required = 2)
1216
- public IRubyObject execute_id_insert(final ThreadContext context, final IRubyObject sql, final IRubyObject id) {
1217
- final Ruby runtime = context.runtime;
1218
-
1219
- callMethod("warn", RubyString.newUnicodeString(runtime, "DEPRECATED: execute_id_insert(sql, id) will be removed"));
1220
-
1221
- return withConnection(context, new Callable<IRubyObject>() {
1222
- public IRubyObject call(final Connection connection) throws SQLException {
1223
- PreparedStatement statement = null;
1224
- final String insertSQL = sql.convertToString().getUnicodeValue();
1225
- try {
1226
- statement = connection.prepareStatement(insertSQL);
1227
- statement.setLong(1, RubyNumeric.fix2long(id));
1228
- statement.executeUpdate();
1229
- }
1230
- catch (final SQLException e) {
1231
- debugErrorSQL(context, insertSQL);
1232
- throw e;
1233
- }
1234
- finally { close(statement); }
1235
- return id;
1236
- }
1237
- });
1238
- }
1239
-
1240
1206
  @JRubyMethod(name = "supported_data_types")
1241
1207
  public IRubyObject supported_data_types(final ThreadContext context) throws SQLException {
1242
1208
  final Connection connection = getConnection(true);
@@ -1260,12 +1226,10 @@ public class RubyJdbcConnection extends RubyObject {
1260
1226
  protected static final int PRIMARY_KEYS_COLUMN_NAME = 4;
1261
1227
 
1262
1228
  private List<RubyString> primaryKeys(final ThreadContext context, final String tableName) {
1263
- return withConnection(context, new Callable<List<RubyString>>() {
1264
- public List<RubyString> call(final Connection connection) throws SQLException {
1265
- final String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
1266
- final TableName table = extractTableName(connection, null, null, _tableName);
1267
- return primaryKeys(context, connection, table);
1268
- }
1229
+ return withConnection(context, connection -> {
1230
+ final String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
1231
+ final TableName table = extractTableName(connection, null, null, _tableName);
1232
+ return primaryKeys(context, connection, table);
1269
1233
  });
1270
1234
  }
1271
1235
 
@@ -1273,7 +1237,7 @@ public class RubyJdbcConnection extends RubyObject {
1273
1237
  final Connection connection, final TableName table) throws SQLException {
1274
1238
  final DatabaseMetaData metaData = connection.getMetaData();
1275
1239
  ResultSet resultSet = null;
1276
- final List<RubyString> keyNames = new ArrayList<RubyString>();
1240
+ final List<RubyString> keyNames = new ArrayList<>();
1277
1241
  try {
1278
1242
  resultSet = metaData.getPrimaryKeys(table.catalog, table.schema, table.name);
1279
1243
  final Ruby runtime = context.runtime;
@@ -1287,26 +1251,6 @@ public class RubyJdbcConnection extends RubyObject {
1287
1251
  return keyNames;
1288
1252
  }
1289
1253
 
1290
- @Deprecated //@JRubyMethod(name = "tables")
1291
- public IRubyObject tables(ThreadContext context) {
1292
- return tables(context, null, null, null, TABLE_TYPE);
1293
- }
1294
-
1295
- @Deprecated //@JRubyMethod(name = "tables")
1296
- public IRubyObject tables(ThreadContext context, IRubyObject catalog) {
1297
- return tables(context, toStringOrNull(catalog), null, null, TABLE_TYPE);
1298
- }
1299
-
1300
- @Deprecated //@JRubyMethod(name = "tables")
1301
- public IRubyObject tables(ThreadContext context, IRubyObject catalog, IRubyObject schemaPattern) {
1302
- return tables(context, toStringOrNull(catalog), toStringOrNull(schemaPattern), null, TABLE_TYPE);
1303
- }
1304
-
1305
- @Deprecated //@JRubyMethod(name = "tables")
1306
- public IRubyObject tables(ThreadContext context, IRubyObject catalog, IRubyObject schemaPattern, IRubyObject tablePattern) {
1307
- return tables(context, toStringOrNull(catalog), toStringOrNull(schemaPattern), toStringOrNull(tablePattern), TABLE_TYPE);
1308
- }
1309
-
1310
1254
  @JRubyMethod(name = "tables", required = 0, optional = 4)
1311
1255
  public IRubyObject tables(final ThreadContext context, final IRubyObject[] args) {
1312
1256
  switch ( args.length ) {
@@ -1324,11 +1268,7 @@ public class RubyJdbcConnection extends RubyObject {
1324
1268
 
1325
1269
  protected IRubyObject tables(final ThreadContext context,
1326
1270
  final String catalog, final String schemaPattern, final String tablePattern, final String[] types) {
1327
- return withConnection(context, new Callable<IRubyObject>() {
1328
- public IRubyObject call(final Connection connection) throws SQLException {
1329
- return matchTables(context, connection, catalog, schemaPattern, tablePattern, types, false);
1330
- }
1331
- });
1271
+ return withConnection(context, connection -> matchTables(context, connection, catalog, schemaPattern, tablePattern, types, false));
1332
1272
  }
1333
1273
 
1334
1274
  protected String[] getTableTypes() {
@@ -1358,40 +1298,36 @@ public class RubyJdbcConnection extends RubyObject {
1358
1298
 
1359
1299
  protected IRubyObject tableExists(final ThreadContext context,
1360
1300
  final String defaultSchema, final String tableName) {
1361
- return withConnection(context, new Callable<RubyBoolean>() {
1362
- public RubyBoolean call(final Connection connection) throws SQLException {
1363
- final TableName components = extractTableName(connection, defaultSchema, tableName);
1364
- return context.runtime.newBoolean( tableExists(context, connection, components) );
1365
- }
1301
+ return withConnection(context, connection -> {
1302
+ final TableName components = extractTableName(connection, defaultSchema, tableName);
1303
+ return context.runtime.newBoolean( tableExists(context, connection, components) );
1366
1304
  });
1367
1305
  }
1368
1306
 
1369
1307
  @JRubyMethod(name = {"columns", "columns_internal"}, required = 1, optional = 2)
1370
1308
  public RubyArray columns_internal(final ThreadContext context, final IRubyObject[] args)
1371
1309
  throws SQLException {
1372
- return withConnection(context, new Callable<RubyArray>() {
1373
- public RubyArray call(final Connection connection) throws SQLException {
1374
- ResultSet columns = null;
1375
- try {
1376
- final String tableName = args[0].toString();
1377
- // optionals (NOTE: catalog argumnet was never used before 1.3.0) :
1378
- final String catalog = args.length > 1 ? toStringOrNull(args[1]) : null;
1379
- final String defaultSchema = args.length > 2 ? toStringOrNull(args[2]) : null;
1380
-
1381
- final TableName components;
1382
- components = extractTableName(connection, catalog, defaultSchema, tableName);
1310
+ return withConnection(context, connection -> {
1311
+ ResultSet columns = null;
1312
+ try {
1313
+ final String tableName = args[0].toString();
1314
+ // optionals (NOTE: catalog argumnet was never used before 1.3.0) :
1315
+ final String catalog = args.length > 1 ? toStringOrNull(args[1]) : null;
1316
+ final String defaultSchema = args.length > 2 ? toStringOrNull(args[2]) : null;
1383
1317
 
1384
- if ( ! tableExists(context, connection, components) ) {
1385
- throw new SQLException("table: " + tableName + " does not exist");
1386
- }
1318
+ final TableName components;
1319
+ components = extractTableName(connection, catalog, defaultSchema, tableName);
1387
1320
 
1388
- final DatabaseMetaData metaData = connection.getMetaData();
1389
- columns = metaData.getColumns(components.catalog, components.schema, components.name, null);
1390
- return mapColumnsResult(context, metaData, components, columns);
1391
- }
1392
- finally {
1393
- close(columns);
1321
+ if ( ! tableExists(context, connection, components) ) {
1322
+ throw new SQLException("table: " + tableName + " does not exist");
1394
1323
  }
1324
+
1325
+ final DatabaseMetaData metaData = connection.getMetaData();
1326
+ columns = metaData.getColumns(components.catalog, components.schema, components.name, null);
1327
+ return mapColumnsResult(context, metaData, components, columns);
1328
+ }
1329
+ finally {
1330
+ close(columns);
1395
1331
  }
1396
1332
  });
1397
1333
  }
@@ -1421,70 +1357,68 @@ public class RubyJdbcConnection extends RubyObject {
1421
1357
  * should filter the return from this method instead.
1422
1358
  */
1423
1359
  protected IRubyObject indexes(final ThreadContext context, final String tableName, final String name, final String schemaName) {
1424
- return withConnection(context, new Callable<IRubyObject>() {
1425
- public IRubyObject call(final Connection connection) throws SQLException {
1426
- final Ruby runtime = context.runtime;
1427
- final RubyClass IndexDefinition = getIndexDefinition(context);
1428
-
1429
- String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
1430
- String _schemaName = caseConvertIdentifierForJdbc(connection, schemaName);
1431
- final TableName table = extractTableName(connection, null, _schemaName, _tableName);
1360
+ return withConnection(context, (Callable<IRubyObject>) connection -> {
1361
+ final Ruby runtime = context.runtime;
1362
+ final RubyClass IndexDefinition = getIndexDefinition(context);
1432
1363
 
1433
- final List<RubyString> primaryKeys = primaryKeys(context, connection, table);
1364
+ String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
1365
+ String _schemaName = caseConvertIdentifierForJdbc(connection, schemaName);
1366
+ final TableName table = extractTableName(connection, null, _schemaName, _tableName);
1434
1367
 
1435
- ResultSet indexInfoSet = null;
1436
- final RubyArray indexes = RubyArray.newArray(runtime, 8);
1437
- try {
1438
- final DatabaseMetaData metaData = connection.getMetaData();
1439
- indexInfoSet = metaData.getIndexInfo(table.catalog, table.schema, table.name, false, true);
1440
- String currentIndex = null;
1441
- RubyArray currentColumns = null;
1368
+ final List<RubyString> primaryKeys = primaryKeys(context, connection, table);
1442
1369
 
1443
- while ( indexInfoSet.next() ) {
1444
- String indexName = indexInfoSet.getString(INDEX_INFO_NAME);
1445
- if ( indexName == null ) continue;
1370
+ ResultSet indexInfoSet = null;
1371
+ final RubyArray indexes = RubyArray.newArray(runtime, 8);
1372
+ try {
1373
+ final DatabaseMetaData metaData = connection.getMetaData();
1374
+ indexInfoSet = metaData.getIndexInfo(table.catalog, table.schema, table.name, false, true);
1375
+ String currentIndex = null;
1446
1376
 
1447
- indexName = caseConvertIdentifierForRails(metaData, indexName);
1377
+ while ( indexInfoSet.next() ) {
1378
+ String indexName = indexInfoSet.getString(INDEX_INFO_NAME);
1379
+ if ( indexName == null ) continue;
1380
+ RubyArray currentColumns = null;
1448
1381
 
1449
- final String columnName = indexInfoSet.getString(INDEX_INFO_COLUMN_NAME);
1450
- final RubyString rubyColumnName = cachedString(
1451
- context, caseConvertIdentifierForRails(metaData, columnName)
1452
- );
1453
- if ( primaryKeys.contains(rubyColumnName) ) continue;
1382
+ indexName = caseConvertIdentifierForRails(metaData, indexName);
1454
1383
 
1455
- // We are working on a new index
1456
- if ( ! indexName.equals(currentIndex) ) {
1457
- currentIndex = indexName;
1384
+ final String columnName = indexInfoSet.getString(INDEX_INFO_COLUMN_NAME);
1385
+ final RubyString rubyColumnName = cachedString(
1386
+ context, caseConvertIdentifierForRails(metaData, columnName)
1387
+ );
1388
+ if ( primaryKeys.contains(rubyColumnName) ) continue;
1458
1389
 
1459
- String indexTableName = indexInfoSet.getString(INDEX_INFO_TABLE_NAME);
1460
- indexTableName = caseConvertIdentifierForRails(metaData, indexTableName);
1390
+ // We are working on a new index
1391
+ if ( ! indexName.equals(currentIndex) ) {
1392
+ currentIndex = indexName;
1461
1393
 
1462
- final boolean nonUnique = indexInfoSet.getBoolean(INDEX_INFO_NON_UNIQUE);
1394
+ String indexTableName = indexInfoSet.getString(INDEX_INFO_TABLE_NAME);
1395
+ indexTableName = caseConvertIdentifierForRails(metaData, indexTableName);
1463
1396
 
1464
- IRubyObject[] args = new IRubyObject[] {
1465
- cachedString(context, indexTableName), // table_name
1466
- cachedString(context, indexName), // index_name
1467
- nonUnique ? runtime.getFalse() : runtime.getTrue(), // unique
1468
- currentColumns = RubyArray.newArray(runtime, 4) // [] column names
1469
- // orders, (since AR 3.2) where, type, using (AR 4.0)
1470
- };
1397
+ final boolean nonUnique = indexInfoSet.getBoolean(INDEX_INFO_NON_UNIQUE);
1471
1398
 
1472
- indexes.append( IndexDefinition.newInstance(context, args, Block.NULL_BLOCK) ); // IndexDefinition.new
1473
- }
1399
+ IRubyObject[] args = new IRubyObject[] {
1400
+ cachedString(context, indexTableName), // table_name
1401
+ cachedString(context, indexName), // index_name
1402
+ nonUnique ? context.fals : context.tru, // unique
1403
+ currentColumns = RubyArray.newArray(runtime, 4) // [] column names
1404
+ // orders, (since AR 3.2) where, type, using (AR 4.0)
1405
+ };
1474
1406
 
1475
- // one or more columns can be associated with an index
1476
- if ( currentColumns != null ) currentColumns.append(rubyColumnName);
1407
+ indexes.append( IndexDefinition.newInstance(context, args, Block.NULL_BLOCK) ); // IndexDefinition.new
1477
1408
  }
1478
1409
 
1479
- return indexes;
1410
+ // one or more columns can be associated with an index
1411
+ if ( currentColumns != null ) currentColumns.append(rubyColumnName);
1412
+ }
1480
1413
 
1481
- } finally { close(indexInfoSet); }
1482
- }
1414
+ return indexes;
1415
+
1416
+ } finally { close(indexInfoSet); }
1483
1417
  });
1484
1418
  }
1485
1419
 
1486
1420
  protected RubyClass getIndexDefinition(final ThreadContext context) {
1487
- final RubyClass adapterClass = getAdapter().getMetaClass();
1421
+ final RubyClass adapterClass = adapter.getMetaClass();
1488
1422
  IRubyObject IDef = adapterClass.getConstantAt("IndexDefinition");
1489
1423
  return IDef != null ? (RubyClass) IDef : getIndexDefinition(context.runtime);
1490
1424
  }
@@ -1495,57 +1429,55 @@ public class RubyJdbcConnection extends RubyObject {
1495
1429
  }
1496
1430
 
1497
1431
  protected IRubyObject foreignKeys(final ThreadContext context, final String tableName, final String schemaName, final String catalog) {
1498
- return withConnection(context, new Callable<IRubyObject>() {
1499
- public IRubyObject call(final Connection connection) throws SQLException {
1500
- final Ruby runtime = context.runtime;
1501
- final RubyClass FKDefinition = getForeignKeyDefinition(context);
1432
+ return withConnection(context, (Callable<IRubyObject>) connection -> {
1433
+ final Ruby runtime = context.runtime;
1434
+ final RubyClass FKDefinition = getForeignKeyDefinition(context);
1502
1435
 
1503
- String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
1504
- String _schemaName = caseConvertIdentifierForJdbc(connection, schemaName);
1505
- final TableName table = extractTableName(connection, catalog, _schemaName, _tableName);
1436
+ String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
1437
+ String _schemaName = caseConvertIdentifierForJdbc(connection, schemaName);
1438
+ final TableName table = extractTableName(connection, catalog, _schemaName, _tableName);
1506
1439
 
1507
- ResultSet fkInfoSet = null;
1508
- final List<IRubyObject> fKeys = new ArrayList<IRubyObject>(8);
1509
- try {
1510
- final DatabaseMetaData metaData = connection.getMetaData();
1511
- fkInfoSet = metaData.getImportedKeys(table.catalog, table.schema, table.name);
1440
+ ResultSet fkInfoSet = null;
1441
+ final List<IRubyObject> fKeys = new ArrayList<>(8);
1442
+ try {
1443
+ final DatabaseMetaData metaData = connection.getMetaData();
1444
+ fkInfoSet = metaData.getImportedKeys(table.catalog, table.schema, table.name);
1512
1445
 
1513
- while ( fkInfoSet.next() ) {
1514
- final RubyHash options = RubyHash.newHash(runtime);
1446
+ while ( fkInfoSet.next() ) {
1447
+ final RubyHash options = RubyHash.newHash(runtime);
1515
1448
 
1516
- String fkName = fkInfoSet.getString("FK_NAME");
1517
- if (fkName != null) {
1518
- fkName = caseConvertIdentifierForRails(metaData, fkName);
1519
- options.put(runtime.newSymbol("name"), fkName);
1520
- }
1449
+ String fkName = fkInfoSet.getString("FK_NAME");
1450
+ if (fkName != null) {
1451
+ fkName = caseConvertIdentifierForRails(metaData, fkName);
1452
+ options.put(runtime.newSymbol("name"), fkName);
1453
+ }
1521
1454
 
1522
- String columnName = fkInfoSet.getString("FKCOLUMN_NAME");
1523
- options.put(runtime.newSymbol("column"), caseConvertIdentifierForRails(metaData, columnName));
1455
+ String columnName = fkInfoSet.getString("FKCOLUMN_NAME");
1456
+ options.put(runtime.newSymbol("column"), caseConvertIdentifierForRails(metaData, columnName));
1524
1457
 
1525
- columnName = fkInfoSet.getString("PKCOLUMN_NAME");
1526
- options.put(runtime.newSymbol("primary_key"), caseConvertIdentifierForRails(metaData, columnName));
1458
+ columnName = fkInfoSet.getString("PKCOLUMN_NAME");
1459
+ options.put(runtime.newSymbol("primary_key"), caseConvertIdentifierForRails(metaData, columnName));
1527
1460
 
1528
- String fkTableName = fkInfoSet.getString("FKTABLE_NAME");
1529
- fkTableName = caseConvertIdentifierForRails(metaData, fkTableName);
1461
+ String fkTableName = fkInfoSet.getString("FKTABLE_NAME");
1462
+ fkTableName = caseConvertIdentifierForRails(metaData, fkTableName);
1530
1463
 
1531
- String pkTableName = fkInfoSet.getString("PKTABLE_NAME");
1532
- pkTableName = caseConvertIdentifierForRails(metaData, pkTableName);
1464
+ String pkTableName = fkInfoSet.getString("PKTABLE_NAME");
1465
+ pkTableName = caseConvertIdentifierForRails(metaData, pkTableName);
1533
1466
 
1534
- final String onDelete = extractForeignKeyRule( fkInfoSet.getInt("DELETE_RULE") );
1535
- if ( onDelete != null ) options.op_aset(context, runtime.newSymbol("on_delete"), runtime.newSymbol(onDelete));
1467
+ final String onDelete = extractForeignKeyRule( fkInfoSet.getInt("DELETE_RULE") );
1468
+ if ( onDelete != null ) options.op_aset(context, runtime.newSymbol("on_delete"), runtime.newSymbol(onDelete));
1536
1469
 
1537
- final String onUpdate = extractForeignKeyRule( fkInfoSet.getInt("UPDATE_RULE") );
1538
- if ( onUpdate != null ) options.op_aset(context, runtime.newSymbol("on_update"), runtime.newSymbol(onUpdate));
1470
+ final String onUpdate = extractForeignKeyRule( fkInfoSet.getInt("UPDATE_RULE") );
1471
+ if ( onUpdate != null ) options.op_aset(context, runtime.newSymbol("on_update"), runtime.newSymbol(onUpdate));
1539
1472
 
1540
- IRubyObject from_table = cachedString(context, fkTableName);
1541
- IRubyObject to_table = cachedString(context, pkTableName);
1542
- fKeys.add( FKDefinition.newInstance(context, from_table, to_table, options, Block.NULL_BLOCK) ); // ForeignKeyDefinition.new
1543
- }
1473
+ IRubyObject from_table = cachedString(context, fkTableName);
1474
+ IRubyObject to_table = cachedString(context, pkTableName);
1475
+ fKeys.add( FKDefinition.newInstance(context, from_table, to_table, options, Block.NULL_BLOCK) ); // ForeignKeyDefinition.new
1476
+ }
1544
1477
 
1545
- return runtime.newArray(fKeys);
1478
+ return runtime.newArray(fKeys);
1546
1479
 
1547
- } finally { close(fkInfoSet); }
1548
- }
1480
+ } finally { close(fkInfoSet); }
1549
1481
  });
1550
1482
  }
1551
1483
 
@@ -1560,7 +1492,7 @@ public class RubyJdbcConnection extends RubyObject {
1560
1492
  }
1561
1493
 
1562
1494
  protected RubyClass getForeignKeyDefinition(final ThreadContext context) {
1563
- final RubyClass adapterClass = getAdapter().getMetaClass();
1495
+ final RubyClass adapterClass = adapter.getMetaClass();
1564
1496
  IRubyObject FKDef = adapterClass.getConstantAt("ForeignKeyDefinition");
1565
1497
  return FKDef != null ? (RubyClass) FKDef : getForeignKeyDefinition(context.runtime);
1566
1498
  }
@@ -1568,42 +1500,34 @@ public class RubyJdbcConnection extends RubyObject {
1568
1500
 
1569
1501
  @JRubyMethod(name = "supports_foreign_keys?")
1570
1502
  public IRubyObject supports_foreign_keys_p(final ThreadContext context) throws SQLException {
1571
- return withConnection(context, new Callable<IRubyObject>() {
1572
- public IRubyObject call(final Connection connection) throws SQLException {
1573
- final DatabaseMetaData metaData = connection.getMetaData();
1574
- return context.runtime.newBoolean( metaData.supportsIntegrityEnhancementFacility() );
1575
- }
1503
+ return withConnection(context, (Callable<IRubyObject>) connection -> {
1504
+ final DatabaseMetaData metaData = connection.getMetaData();
1505
+ return context.runtime.newBoolean( metaData.supportsIntegrityEnhancementFacility() );
1576
1506
  });
1577
1507
  }
1578
1508
 
1579
1509
  @JRubyMethod(name = "supports_views?")
1580
1510
  public IRubyObject supports_views_p(final ThreadContext context) throws SQLException {
1581
- return withConnection(context, new Callable<IRubyObject>() {
1582
- public IRubyObject call(final Connection connection) throws SQLException {
1583
- final DatabaseMetaData metaData = connection.getMetaData();
1584
- final ResultSet tableTypes = metaData.getTableTypes();
1585
- try {
1586
- while ( tableTypes.next() ) {
1587
- if ( "VIEW".equalsIgnoreCase( tableTypes.getString(1) ) ) {
1588
- return context.runtime.newBoolean( true );
1589
- }
1511
+ return withConnection(context, (Callable<IRubyObject>) connection -> {
1512
+ final DatabaseMetaData metaData = connection.getMetaData();
1513
+ final ResultSet tableTypes = metaData.getTableTypes();
1514
+ try {
1515
+ while ( tableTypes.next() ) {
1516
+ if ( "VIEW".equalsIgnoreCase( tableTypes.getString(1) ) ) {
1517
+ return context.runtime.newBoolean( true );
1590
1518
  }
1591
1519
  }
1592
- finally {
1593
- close(tableTypes);
1594
- }
1595
- return context.runtime.newBoolean( false );
1596
1520
  }
1521
+ finally {
1522
+ close(tableTypes);
1523
+ }
1524
+ return context.runtime.newBoolean( false );
1597
1525
  });
1598
1526
  }
1599
1527
 
1600
1528
  @JRubyMethod(name = "with_jdbc_connection", alias = "with_connection_retry_guard", frame = true)
1601
1529
  public IRubyObject with_jdbc_connection(final ThreadContext context, final Block block) {
1602
- return withConnection(context, new Callable<IRubyObject>() {
1603
- public IRubyObject call(final Connection connection) throws SQLException {
1604
- return block.call(context, convertJavaToRuby(connection));
1605
- }
1606
- });
1530
+ return withConnection(context, connection -> block.call(context, convertJavaToRuby(connection)));
1607
1531
  }
1608
1532
 
1609
1533
  /*
@@ -1664,24 +1588,22 @@ public class RubyJdbcConnection extends RubyObject {
1664
1588
  // TODO: Fix this, the columns don't have the info needed to handle this anymore
1665
1589
  // currently commented out so that it will compile
1666
1590
 
1667
- return withConnection(context, new Callable<Integer>() {
1668
- public Integer call(final Connection connection) throws SQLException {
1669
- PreparedStatement statement = null;
1670
- try {
1671
- statement = connection.prepareStatement(sql);
1672
- /*
1673
- if ( binary ) { // blob
1674
- setBlobParameter(context, connection, statement, 1, value, column, Types.BLOB);
1675
- }
1676
- else { // clob
1677
- setClobParameter(context, connection, statement, 1, value, column, Types.CLOB);
1678
- }
1679
- setStatementParameter(context, context.runtime, connection, statement, 2, idValue, idColumn);
1680
- */
1681
- return statement.executeUpdate();
1591
+ return withConnection(context, connection -> {
1592
+ PreparedStatement statement = null;
1593
+ try {
1594
+ statement = connection.prepareStatement(sql);
1595
+ /*
1596
+ if ( binary ) { // blob
1597
+ setBlobParameter(context, connection, statement, 1, value, column, Types.BLOB);
1598
+ }
1599
+ else { // clob
1600
+ setClobParameter(context, connection, statement, 1, value, column, Types.CLOB);
1682
1601
  }
1683
- finally { close(statement); }
1602
+ setStatementParameter(context, context.runtime, connection, statement, 2, idValue, idColumn);
1603
+ */
1604
+ return statement.executeUpdate();
1684
1605
  }
1606
+ finally { close(statement); }
1685
1607
  });
1686
1608
  }
1687
1609
 
@@ -1737,7 +1659,7 @@ public class RubyJdbcConnection extends RubyObject {
1737
1659
  final IRubyObject self, final IRubyObject config, final Block block) {
1738
1660
  final IRubyObject ds_or_name = rawDataSourceOrName(context, config);
1739
1661
 
1740
- if ( ds_or_name == null ) return context.runtime.getFalse();
1662
+ if ( ds_or_name == null ) return context.fals;
1741
1663
 
1742
1664
  final javax.sql.DataSource dataSource;
1743
1665
  final Object dsOrName = ds_or_name.toJava(Object.class);
@@ -1793,7 +1715,7 @@ public class RubyJdbcConnection extends RubyObject {
1793
1715
  }
1794
1716
  }
1795
1717
 
1796
- if ( configValue == null || configValue == context.nil || configValue == runtime.getFalse() ) {
1718
+ if ( configValue == null || configValue == context.nil || configValue == context.fals ) {
1797
1719
  return null;
1798
1720
  }
1799
1721
  return configValue;
@@ -1816,13 +1738,6 @@ public class RubyJdbcConnection extends RubyObject {
1816
1738
  }
1817
1739
  }
1818
1740
 
1819
- @Deprecated
1820
- @JRubyMethod(name = "setup_jdbc_factory", visibility = Visibility.PROTECTED)
1821
- public IRubyObject set_driver_factory(final ThreadContext context) {
1822
- setDriverFactory(context);
1823
- return get_connection_factory(context.runtime);
1824
- }
1825
-
1826
1741
  private ConnectionFactory setDriverFactory(final ThreadContext context) {
1827
1742
 
1828
1743
  final IRubyObject url = getConfigValue(context, "url");
@@ -1922,12 +1837,6 @@ public class RubyJdbcConnection extends RubyObject {
1922
1837
  return props;
1923
1838
  }
1924
1839
 
1925
- @JRubyMethod(name = "setup_jndi_factory", visibility = Visibility.PROTECTED)
1926
- public IRubyObject set_data_source_factory(final ThreadContext context) {
1927
- setDataSourceFactory(context);
1928
- return get_connection_factory(context.runtime);
1929
- }
1930
-
1931
1840
  private ConnectionFactory setDataSourceFactory(final ThreadContext context) {
1932
1841
  final javax.sql.DataSource dataSource; final String lookupName;
1933
1842
  IRubyObject value = getConfigValue(context, "data_source");
@@ -1949,28 +1858,10 @@ public class RubyJdbcConnection extends RubyObject {
1949
1858
  private static volatile boolean defaultConfigJndi;
1950
1859
  private static transient ConnectionFactory defaultConnectionFactory;
1951
1860
 
1952
- /**
1953
- * Sets the connection factory from the available configuration.
1954
- * @param context
1955
- * @see #initialize
1956
- */
1957
- @Deprecated
1958
- @JRubyMethod(name = "setup_connection_factory", visibility = Visibility.PROTECTED)
1959
- public IRubyObject setup_connection_factory(final ThreadContext context) {
1960
- setupConnectionFactory(context);
1961
- return get_connection_factory(context.runtime);
1962
- }
1963
-
1964
- private IRubyObject get_connection_factory(final Ruby runtime) {
1965
- return JavaUtil.convertJavaToRuby(runtime, connectionFactory);
1966
- }
1967
-
1968
1861
  /**
1969
1862
  * @return whether the connection factory is JNDI based
1970
1863
  */
1971
1864
  private boolean setupConnectionFactory(final ThreadContext context) {
1972
- final IRubyObject config = getConfig();
1973
-
1974
1865
  if ( defaultConfig == null ) {
1975
1866
  synchronized(RubyJdbcConnection.class) {
1976
1867
  if ( defaultConfig == null ) {
@@ -2002,18 +1893,17 @@ public class RubyJdbcConnection extends RubyObject {
2002
1893
 
2003
1894
  @JRubyMethod(name = "jndi?", alias = "jndi_connection?")
2004
1895
  public RubyBoolean jndi_p(final ThreadContext context) {
2005
- return context.runtime.newBoolean( isJndi() );
1896
+ return context.runtime.newBoolean(jndi);
2006
1897
  }
2007
1898
 
2008
1899
  protected boolean isJndi() { return this.jndi; }
2009
1900
 
2010
1901
  @JRubyMethod(name = "config")
2011
- public IRubyObject config() { return getConfig(); }
1902
+ public IRubyObject config() { return config; }
2012
1903
 
2013
1904
  public IRubyObject getConfig() { return this.config; }
2014
1905
 
2015
1906
  protected final IRubyObject getConfigValue(final ThreadContext context, final String key) {
2016
- final IRubyObject config = getConfig();
2017
1907
  final RubySymbol keySym = context.runtime.newSymbol(key);
2018
1908
  if ( config instanceof RubyHash ) {
2019
1909
  final IRubyObject value = ((RubyHash) config).fastARef(keySym);
@@ -2024,7 +1914,6 @@ public class RubyJdbcConnection extends RubyObject {
2024
1914
 
2025
1915
  protected final IRubyObject setConfigValue(final ThreadContext context,
2026
1916
  final String key, final IRubyObject value) {
2027
- final IRubyObject config = getConfig();
2028
1917
  final RubySymbol keySym = context.runtime.newSymbol(key);
2029
1918
  if ( config instanceof RubyHash ) {
2030
1919
  return ((RubyHash) config).op_aset(context, keySym, value);
@@ -2034,7 +1923,6 @@ public class RubyJdbcConnection extends RubyObject {
2034
1923
 
2035
1924
  protected final IRubyObject setConfigValueIfNotSet(final ThreadContext context,
2036
1925
  final String key, final IRubyObject value) {
2037
- final IRubyObject config = getConfig();
2038
1926
  final RubySymbol keySym = context.runtime.newSymbol(key);
2039
1927
  if ( config instanceof RubyHash ) {
2040
1928
  final IRubyObject setValue = ((RubyHash) config).fastARef(keySym);
@@ -2054,7 +1942,7 @@ public class RubyJdbcConnection extends RubyObject {
2054
1942
  protected final IRubyObject getAdapter() { return this.adapter; }
2055
1943
 
2056
1944
  protected RubyClass getJdbcColumnClass(final ThreadContext context) {
2057
- return (RubyClass) getAdapter().callMethod(context, "jdbc_column_class");
1945
+ return (RubyClass) adapter.callMethod(context, "jdbc_column_class");
2058
1946
  }
2059
1947
 
2060
1948
  protected ConnectionFactory getConnectionFactory() throws RaiseException {
@@ -2266,7 +2154,7 @@ public class RubyJdbcConnection extends RubyObject {
2266
2154
  @JRubyMethod(name = "raw_date_time?", meta = true)
2267
2155
  public static IRubyObject useRawDateTime(final ThreadContext context, final IRubyObject self) {
2268
2156
  if ( rawDateTime == null ) return context.nil;
2269
- return context.runtime.newBoolean( rawDateTime.booleanValue() );
2157
+ return context.runtime.newBoolean(rawDateTime);
2270
2158
  }
2271
2159
 
2272
2160
  @JRubyMethod(name = "raw_date_time=", meta = true)
@@ -2280,17 +2168,6 @@ public class RubyJdbcConnection extends RubyObject {
2280
2168
  return value;
2281
2169
  }
2282
2170
 
2283
- /**
2284
- * @return AR::Type-casted value
2285
- * @since 1.3.18
2286
- */
2287
- @Deprecated
2288
- protected static IRubyObject typeCastFromDatabase(final ThreadContext context,
2289
- final IRubyObject adapter, final RubySymbol typeName, final RubyString value) {
2290
- final IRubyObject type = adapter.callMethod(context, "lookup_cast_type", typeName);
2291
- return type.callMethod(context, "deserialize", value);
2292
- }
2293
-
2294
2171
  protected IRubyObject dateToRuby(final ThreadContext context,
2295
2172
  final Ruby runtime, final ResultSet resultSet, final int column)
2296
2173
  throws SQLException {
@@ -2301,11 +2178,11 @@ public class RubyJdbcConnection extends RubyObject {
2301
2178
  return resultSet.wasNull() ? context.nil : RubyString.newEmptyString(runtime);
2302
2179
  }
2303
2180
 
2304
- if ( rawDateTime != null && rawDateTime.booleanValue() ) {
2181
+ if ( rawDateTime != null && rawDateTime) {
2305
2182
  return RubyString.newString(runtime, DateTimeUtils.dateToString(value));
2306
2183
  }
2307
2184
 
2308
- return DateTimeUtils.newDateAsTime(context, value, null).callMethod(context, "to_date");
2185
+ return DateTimeUtils.newDateAsTime(context, value, DateTimeZone.UTC).callMethod(context, "to_date");
2309
2186
  }
2310
2187
 
2311
2188
  protected IRubyObject timeToRuby(final ThreadContext context,
@@ -2317,7 +2194,7 @@ public class RubyJdbcConnection extends RubyObject {
2317
2194
  return resultSet.wasNull() ? context.nil : RubyString.newEmptyString(runtime);
2318
2195
  }
2319
2196
 
2320
- if ( rawDateTime != null && rawDateTime.booleanValue() ) {
2197
+ if ( rawDateTime != null && rawDateTime) {
2321
2198
  return RubyString.newString(runtime, DateTimeUtils.timeToString(value));
2322
2199
  }
2323
2200
 
@@ -2333,7 +2210,7 @@ public class RubyJdbcConnection extends RubyObject {
2333
2210
  return resultSet.wasNull() ? context.nil : RubyString.newEmptyString(runtime);
2334
2211
  }
2335
2212
 
2336
- if ( rawDateTime != null && rawDateTime.booleanValue() ) {
2213
+ if ( rawDateTime != null && rawDateTime) {
2337
2214
  return RubyString.newString(runtime, DateTimeUtils.timestampToString(value));
2338
2215
  }
2339
2216
 
@@ -2345,19 +2222,6 @@ public class RubyJdbcConnection extends RubyObject {
2345
2222
  return DateTimeUtils.newTime(context, value, getDefaultTimeZone(context));
2346
2223
  }
2347
2224
 
2348
- @Deprecated
2349
- protected static RubyString timestampToRubyString(final Ruby runtime, String value) {
2350
- // Timestamp's format: yyyy-mm-dd hh:mm:ss.fffffffff
2351
- String suffix; // assumes java.sql.Timestamp internals :
2352
- if ( value.endsWith( suffix = " 00:00:00.0" ) ) {
2353
- value = value.substring( 0, value.length() - suffix.length() );
2354
- }
2355
- else if ( value.endsWith( suffix = ".0" ) ) {
2356
- value = value.substring( 0, value.length() - suffix.length() );
2357
- }
2358
- return RubyString.newUnicodeString(runtime, value);
2359
- }
2360
-
2361
2225
  protected static Boolean rawBoolean;
2362
2226
  static {
2363
2227
  final String booleanRaw = SafePropertyAccessor.getProperty("arjdbc.boolean.raw");
@@ -2369,7 +2233,7 @@ public class RubyJdbcConnection extends RubyObject {
2369
2233
  @JRubyMethod(name = "raw_boolean?", meta = true)
2370
2234
  public static IRubyObject useRawBoolean(final ThreadContext context, final IRubyObject self) {
2371
2235
  if ( rawBoolean == null ) return context.nil;
2372
- return context.runtime.newBoolean( rawBoolean.booleanValue() );
2236
+ return context.runtime.newBoolean(rawBoolean);
2373
2237
  }
2374
2238
 
2375
2239
  @JRubyMethod(name = "raw_boolean=", meta = true)
@@ -2401,13 +2265,13 @@ public class RubyJdbcConnection extends RubyObject {
2401
2265
  protected IRubyObject booleanToRuby(final ThreadContext context,
2402
2266
  final Ruby runtime, final ResultSet resultSet, final int column)
2403
2267
  throws SQLException {
2404
- if ( rawBoolean != null && rawBoolean.booleanValue() ) {
2268
+ if ( rawBoolean != null && rawBoolean) {
2405
2269
  final String value = resultSet.getString(column);
2406
2270
  if ( value == null /* && resultSet.wasNull() */ ) return context.nil;
2407
2271
  return RubyString.newUnicodeString(runtime, value);
2408
2272
  }
2409
2273
  final boolean value = resultSet.getBoolean(column);
2410
- if ( value == false && resultSet.wasNull() ) return context.nil;
2274
+ if (!value && resultSet.wasNull()) return context.nil;
2411
2275
  return runtime.newBoolean(value);
2412
2276
  }
2413
2277
 
@@ -2555,9 +2419,16 @@ public class RubyJdbcConnection extends RubyObject {
2555
2419
  final Connection connection, final PreparedStatement statement,
2556
2420
  final int index, IRubyObject attribute) throws SQLException {
2557
2421
 
2558
- //debugMessage(context, attribute);
2559
- final int type = jdbcTypeForAttribute(context, attribute);
2560
- IRubyObject value = valueForDatabase(context, attribute);
2422
+ final IRubyObject value;
2423
+ final int type;
2424
+
2425
+ if (attributeClass.isInstance(attribute)) {
2426
+ type = jdbcTypeForAttribute(context, attribute);
2427
+ value = valueForDatabase(context, attribute);
2428
+ } else {
2429
+ type = jdbcTypeForPrimitiveAttribute(context, attribute);
2430
+ value = attribute;
2431
+ }
2561
2432
 
2562
2433
  // All the set methods were calling this first so save a method call in the nil case
2563
2434
  if ( value == context.nil ) {
@@ -2625,7 +2496,7 @@ public class RubyJdbcConnection extends RubyObject {
2625
2496
  }
2626
2497
  }
2627
2498
 
2628
- protected static final Map<String, Integer> JDBC_TYPE_FOR = new HashMap<String, Integer>(32, 1);
2499
+ protected static final Map<String, Integer> JDBC_TYPE_FOR = new HashMap<>(32, 1);
2629
2500
  static {
2630
2501
  JDBC_TYPE_FOR.put("string", Types.VARCHAR);
2631
2502
  JDBC_TYPE_FOR.put("text", Types.CLOB);
@@ -2667,12 +2538,40 @@ public class RubyJdbcConnection extends RubyObject {
2667
2538
  final String internedType = internedTypeFor(context, attribute);
2668
2539
  final Integer sqlType = jdbcTypeFor(internedType);
2669
2540
  if ( sqlType != null ) {
2670
- return sqlType.intValue();
2541
+ return sqlType;
2671
2542
  }
2672
2543
 
2673
2544
  return Types.OTHER; // -1 as well as 0 are used in Types
2674
2545
  }
2675
2546
 
2547
+ protected String internedTypeForPrimitive(final ThreadContext context, final IRubyObject value) throws SQLException {
2548
+ if (value instanceof RubyString) {
2549
+ return "string";
2550
+ }
2551
+ if (value instanceof RubyInteger) {
2552
+ return "integer";
2553
+ }
2554
+ if (value instanceof RubyNumeric) {
2555
+ return "float";
2556
+ }
2557
+ if (value instanceof RubyTime || value instanceof RubyDateTime) {
2558
+ return "timestamp";
2559
+ }
2560
+ if (value instanceof RubyDate) {
2561
+ return "date";
2562
+ }
2563
+ if (value instanceof RubyBoolean) {
2564
+ return "boolean";
2565
+ }
2566
+ return "string";
2567
+ }
2568
+
2569
+ protected Integer jdbcTypeForPrimitiveAttribute(final ThreadContext context,
2570
+ final IRubyObject attribute) throws SQLException {
2571
+ final String internedType = internedTypeForPrimitive(context, attribute);
2572
+ return jdbcTypeFor(internedType);
2573
+ }
2574
+
2676
2575
  protected Integer jdbcTypeFor(final String type) {
2677
2576
  return JDBC_TYPE_FOR.get(type);
2678
2577
  }
@@ -2684,7 +2583,9 @@ public class RubyJdbcConnection extends RubyObject {
2684
2583
  }
2685
2584
 
2686
2585
  protected static IRubyObject attributeSQLType(final ThreadContext context, final IRubyObject attribute) {
2687
- return attributeType(context, attribute).callMethod(context, "type");
2586
+ final IRubyObject type = attributeType(context, attribute);
2587
+ if (type != null) return type.callMethod(context, "type");
2588
+ return context.nil;
2688
2589
  }
2689
2590
 
2690
2591
  private final CachingCallSite value_site = new FunctionalCachingCallSite("value"); // AR::Attribute#value
@@ -2699,23 +2600,7 @@ public class RubyJdbcConnection extends RubyObject {
2699
2600
 
2700
2601
  final IRubyObject value = value_site.call(context, attribute, attribute);
2701
2602
 
2702
- if (value instanceof RubyInteger) {
2703
- return "integer";
2704
- }
2705
-
2706
- if (value instanceof RubyNumeric) {
2707
- return "float";
2708
- }
2709
-
2710
- if (value instanceof RubyTime) {
2711
- return "timestamp";
2712
- }
2713
-
2714
- if (value instanceof RubyBoolean) {
2715
- return "boolean";
2716
- }
2717
-
2718
- return "string";
2603
+ return internedTypeForPrimitive(context, value);
2719
2604
  }
2720
2605
 
2721
2606
  // to be overriden in child class for database specific types
@@ -2854,11 +2739,6 @@ public class RubyJdbcConnection extends RubyObject {
2854
2739
  statement.setTimestamp(index, timestamp, getCalendar(dateTime.getZone()));
2855
2740
  }
2856
2741
 
2857
- @Deprecated
2858
- protected static Timestamp convertToTimestamp(final RubyFloat value) {
2859
- return DateTimeUtils.convertToTimestamp(value);
2860
- }
2861
-
2862
2742
  protected static Calendar getCalendar(final DateTimeZone zone) { // final java.util.Date hint
2863
2743
  if (DateTimeZone.UTC == zone) return getCalendarUTC();
2864
2744
  if (DateTimeZone.getDefault() == zone) return new GregorianCalendar();
@@ -2904,9 +2784,14 @@ public class RubyJdbcConnection extends RubyObject {
2904
2784
  value = value.callMethod(context, "to_date");
2905
2785
  }
2906
2786
 
2907
- // NOTE: Here we rely in ActiveRecord (ActiveSupport) to get
2908
- // the date as a string in the database format.
2909
- statement.setDate(index, Date.valueOf(value.callMethod(context, "to_s", context.runtime.newSymbol("db")).toString()));
2787
+ if (value instanceof RubyDate) {
2788
+ RubyDate rubyDate = (RubyDate) value;
2789
+ statement.setDate(index, rubyDate.toJava(Date.class));
2790
+ return;
2791
+ }
2792
+
2793
+ // NOTE: assuming Date#to_s does right ...
2794
+ statement.setDate(index, Date.valueOf(value.toString()));
2910
2795
  }
2911
2796
 
2912
2797
  protected void setBooleanParameter(final ThreadContext context,
@@ -2943,7 +2828,7 @@ public class RubyJdbcConnection extends RubyObject {
2943
2828
  // For some reason the driver doesn't like "character varying" as a type
2944
2829
  if ( type.eql(context.runtime.newSymbol("string")) ) return "varchar";
2945
2830
 
2946
- final RubyHash nativeTypes = (RubyHash) getAdapter().callMethod(context, "native_database_types");
2831
+ final RubyHash nativeTypes = (RubyHash) adapter.callMethod(context, "native_database_types");
2947
2832
  // e.g. `integer: { name: 'integer' }`
2948
2833
  final RubyHash typeInfo = (RubyHash) nativeTypes.op_aref(context, type);
2949
2834
 
@@ -3004,16 +2889,7 @@ public class RubyJdbcConnection extends RubyObject {
3004
2889
  }
3005
2890
 
3006
2891
  /**
3007
- * Always returns a connection (might cause a reconnect if there's none).
3008
- * @return connection
3009
- * @throws <code>ActiveRecord::ConnectionNotEstablished</code>, <code>ActiveRecord::JDBCError</code>
3010
- */
3011
- protected Connection getConnection() throws RaiseException {
3012
- return getConnection(false);
3013
- }
3014
-
3015
- /**
3016
- * @see #getConnection()
2892
+ * Returns a connection (might cause a reconnect if there's none).
3017
2893
  * @param required set to true if a connection is required to exists (e.g. on commit)
3018
2894
  * @return connection
3019
2895
  * @throws <code>ActiveRecord::ConnectionNotEstablished</code> if disconnected
@@ -3028,17 +2904,15 @@ public class RubyJdbcConnection extends RubyObject {
3028
2904
  }
3029
2905
  }
3030
2906
 
3031
- private Connection getConnectionInternal(final boolean required) throws SQLException {
2907
+ protected Connection getConnectionInternal(final boolean required) throws SQLException {
3032
2908
  Connection connection = getConnectionImpl();
3033
- if ( connection == null ) {
3034
- if ( required ) {
3035
- if ( ! connected ) handleNotConnected(); // raise ConnectionNotEstablished
3036
- synchronized (this) {
2909
+ if (connection == null && required) {
2910
+ if (!connected) handleNotConnected(); // raise ConnectionNotEstablished
2911
+ synchronized (this) {
2912
+ connection = getConnectionImpl();
2913
+ if ( connection == null ) {
2914
+ connectImpl(true); // throws SQLException
3037
2915
  connection = getConnectionImpl();
3038
- if ( connection == null ) {
3039
- connectImpl( true ); // throws SQLException
3040
- connection = getConnectionImpl();
3041
- }
3042
2916
  }
3043
2917
  }
3044
2918
  }
@@ -3169,7 +3043,7 @@ public class RubyJdbcConnection extends RubyObject {
3169
3043
  try {
3170
3044
  tablesSet = metaData.getTables(catalog, _schemaPattern, _tablePattern, types);
3171
3045
  if ( checkExistsOnly ) { // only check if given table exists
3172
- return tablesSet.next() ? context.runtime.getTrue() : null;
3046
+ return tablesSet.next() ? context.tru : null;
3173
3047
  }
3174
3048
  else {
3175
3049
  return mapTables(context, connection, catalog, _schemaPattern, _tablePattern, tablesSet);
@@ -3178,15 +3052,6 @@ public class RubyJdbcConnection extends RubyObject {
3178
3052
  finally { close(tablesSet); }
3179
3053
  }
3180
3054
 
3181
- @Deprecated
3182
- protected IRubyObject matchTables(final Ruby runtime,
3183
- final Connection connection,
3184
- final String catalog, final String schemaPattern,
3185
- final String tablePattern, final String[] types,
3186
- final boolean checkExistsOnly) throws SQLException {
3187
- return matchTables(runtime.getCurrentContext(), connection, catalog, schemaPattern, tablePattern, types, checkExistsOnly);
3188
- }
3189
-
3190
3055
  // NOTE java.sql.DatabaseMetaData.getTables :
3191
3056
  protected final static int TABLES_TABLE_CAT = 1;
3192
3057
  protected final static int TABLES_TABLE_SCHEM = 2;
@@ -3275,7 +3140,7 @@ public class RubyJdbcConnection extends RubyObject {
3275
3140
  final String tabName = results.getString(TABLE_NAME);
3276
3141
  final RubyString tableName = cachedString(context, caseConvertIdentifierForRails(metaData, tabName));
3277
3142
 
3278
- final IRubyObject type_metadata = getAdapter().callMethod(context, "fetch_type_metadata", sqlType);
3143
+ final IRubyObject type_metadata = adapter.callMethod(context, "fetch_type_metadata", sqlType);
3279
3144
 
3280
3145
  // (name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment: nil)
3281
3146
  final IRubyObject[] args = new IRubyObject[] {
@@ -3291,7 +3156,7 @@ public class RubyJdbcConnection extends RubyObject {
3291
3156
  ResultSet primaryKeys = null;
3292
3157
  try {
3293
3158
  primaryKeys = metaData.getPrimaryKeys(components.catalog, components.schema, components.name);
3294
- final List<String> primaryKeyNames = new ArrayList<String>(4);
3159
+ final List<String> primaryKeyNames = new ArrayList<>(4);
3295
3160
  while ( primaryKeys.next() ) {
3296
3161
  primaryKeyNames.add( primaryKeys.getString(COLUMN_NAME) );
3297
3162
  }
@@ -3340,7 +3205,7 @@ public class RubyJdbcConnection extends RubyObject {
3340
3205
  // not have and auto-generated ID column :
3341
3206
  boolean next = genKeys.next() && genKeys.getMetaData().getColumnCount() > 0;
3342
3207
  // singleResult == null - guess if only single key returned
3343
- if ( singleResult == null || singleResult.booleanValue() ) {
3208
+ if ( singleResult == null || singleResult) {
3344
3209
  if ( next ) {
3345
3210
  firstKey = mapGeneratedKey(runtime, genKeys);
3346
3211
  if ( singleResult != null || ! genKeys.next() ) {
@@ -3373,7 +3238,7 @@ public class RubyJdbcConnection extends RubyObject {
3373
3238
  if (supportsGeneratedKeys == null) {
3374
3239
  supportsGeneratedKeys = this.supportsGeneratedKeys = connection.getMetaData().supportsGetGeneratedKeys();
3375
3240
  }
3376
- return supportsGeneratedKeys.booleanValue();
3241
+ return supportsGeneratedKeys;
3377
3242
  }
3378
3243
 
3379
3244
  /**
@@ -3405,8 +3270,8 @@ public class RubyJdbcConnection extends RubyObject {
3405
3270
  final ColumnData[] columns = extractColumns(context, connection, resultSet, false);
3406
3271
 
3407
3272
  final Ruby runtime = context.runtime;
3408
- final IRubyObject[] blockArgs = new IRubyObject[columns.length];
3409
3273
  while ( resultSet.next() ) {
3274
+ final IRubyObject[] blockArgs = new IRubyObject[columns.length];
3410
3275
  for ( int i = 0; i < columns.length; i++ ) {
3411
3276
  final ColumnData column = columns[i];
3412
3277
  blockArgs[i] = jdbcToRuby(context, runtime, column.index, column.type, resultSet);
@@ -3432,16 +3297,6 @@ public class RubyJdbcConnection extends RubyObject {
3432
3297
  return setupColumns(context, connection, resultSet.getMetaData(), downCase);
3433
3298
  }
3434
3299
 
3435
- /**
3436
- * @deprecated use {@link #extractColumns(ThreadContext, Connection, ResultSet, boolean)}
3437
- */
3438
- @Deprecated
3439
- protected ColumnData[] extractColumns(final Ruby runtime,
3440
- final Connection connection, final ResultSet resultSet,
3441
- final boolean downCase) throws SQLException {
3442
- return extractColumns(runtime.getCurrentContext(), connection, resultSet, downCase);
3443
- }
3444
-
3445
3300
  protected <T> T withConnection(final ThreadContext context, final Callable<T> block)
3446
3301
  throws RaiseException {
3447
3302
  try {
@@ -3547,13 +3402,12 @@ public class RubyJdbcConnection extends RubyObject {
3547
3402
  }
3548
3403
 
3549
3404
  protected boolean isTransient(final Exception exception) {
3550
- if ( exception instanceof SQLTransientException ) return true;
3551
- return false;
3405
+ return exception instanceof SQLTransientException;
3552
3406
  }
3553
3407
 
3554
3408
  protected boolean isRecoverable(final Exception exception) {
3555
- if ( exception instanceof SQLRecoverableException) return true;
3556
- return false; // exception instanceof SQLException; // pre JDBC 4.0 drivers?
3409
+ return exception instanceof SQLRecoverableException;
3410
+ // exception instanceof SQLException; // pre JDBC 4.0 drivers?
3557
3411
  }
3558
3412
 
3559
3413
  private static Throwable getCause(Throwable exception) {
@@ -3711,6 +3565,11 @@ public class RubyJdbcConnection extends RubyObject {
3711
3565
  return Result.newInstance(context, columnsToArray(context, columns), rows, Block.NULL_BLOCK); // Result.new
3712
3566
  }
3713
3567
 
3568
+ protected static IRubyObject newEmptyResult(final ThreadContext context) {
3569
+ final RubyClass Result = getResult(context.runtime);
3570
+ return Result.newInstance(context, RubyArray.newEmptyArray(context.runtime), RubyArray.newEmptyArray(context.runtime), Block.NULL_BLOCK); // Result.new
3571
+ }
3572
+
3714
3573
  private static RubyArray columnsToArray(ThreadContext context, ColumnData[] columns) {
3715
3574
  final IRubyObject[] cols = new IRubyObject[columns.length];
3716
3575
 
@@ -3963,7 +3822,7 @@ public class RubyJdbcConnection extends RubyObject {
3963
3822
  public static void debugStackTrace(final ThreadContext context, final Throwable e) {
3964
3823
  if ( debug || ( context != null && context.runtime.isDebug() ) ) {
3965
3824
  final PrintStream out = context != null ? context.runtime.getOut() : System.out;
3966
- if ( debugStackTrace == null || debugStackTrace.booleanValue() ) {
3825
+ if ( debugStackTrace == null || debugStackTrace) {
3967
3826
  e.printStackTrace(out);
3968
3827
  }
3969
3828
  else {
@@ -3979,8 +3838,7 @@ public class RubyJdbcConnection extends RubyObject {
3979
3838
  private static boolean driverUsedLogged;
3980
3839
 
3981
3840
  private void logDriverUsed(final Connection connection) {
3982
- if ( isDebug() ) {
3983
- if ( driverUsedLogged ) return;
3841
+ if (debug && !driverUsedLogged) {
3984
3842
  driverUsedLogged = true;
3985
3843
  try {
3986
3844
  final DatabaseMetaData meta = connection.getMetaData();