activerecord-jdbc-alt-adapter 52.2.3-java → 60.1.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/.travis.yml +80 -52
  4. data/Gemfile +10 -3
  5. data/README.md +55 -37
  6. data/Rakefile +31 -5
  7. data/Rakefile.jdbc +8 -1
  8. data/activerecord-jdbc-adapter.gemspec +6 -9
  9. data/activerecord-jdbc-alt-adapter.gemspec +6 -9
  10. data/lib/arel/visitors/sqlserver.rb +33 -23
  11. data/lib/arjdbc/abstract/connection_management.rb +7 -0
  12. data/lib/arjdbc/abstract/core.rb +17 -24
  13. data/lib/arjdbc/abstract/database_statements.rb +31 -20
  14. data/lib/arjdbc/abstract/statement_cache.rb +2 -5
  15. data/lib/arjdbc/abstract/transaction_support.rb +5 -3
  16. data/lib/arjdbc/db2/column.rb +0 -39
  17. data/lib/arjdbc/derby/adapter.rb +1 -20
  18. data/lib/arjdbc/firebird/adapter.rb +0 -21
  19. data/lib/arjdbc/h2/adapter.rb +0 -15
  20. data/lib/arjdbc/hsqldb/adapter.rb +0 -14
  21. data/lib/arjdbc/informix/adapter.rb +0 -23
  22. data/lib/arjdbc/jdbc.rb +0 -4
  23. data/lib/arjdbc/jdbc/adapter.rb +3 -1
  24. data/lib/arjdbc/jdbc/adapter_require.rb +3 -1
  25. data/lib/arjdbc/jdbc/base_ext.rb +3 -1
  26. data/lib/arjdbc/jdbc/callbacks.rb +2 -0
  27. data/lib/arjdbc/jdbc/column.rb +3 -5
  28. data/lib/arjdbc/jdbc/connection.rb +2 -0
  29. data/lib/arjdbc/jdbc/connection_methods.rb +2 -0
  30. data/lib/arjdbc/jdbc/error.rb +2 -0
  31. data/lib/arjdbc/jdbc/extension.rb +2 -0
  32. data/lib/arjdbc/jdbc/java.rb +3 -1
  33. data/lib/arjdbc/jdbc/railtie.rb +3 -1
  34. data/lib/arjdbc/jdbc/rake_tasks.rb +3 -1
  35. data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +3 -1
  36. data/lib/arjdbc/jdbc/type_cast.rb +2 -0
  37. data/lib/arjdbc/jdbc/type_converter.rb +2 -0
  38. data/lib/arjdbc/mssql.rb +3 -1
  39. data/lib/arjdbc/mssql/adapter.rb +112 -46
  40. data/lib/arjdbc/mssql/column.rb +5 -1
  41. data/lib/arjdbc/mssql/connection_methods.rb +13 -2
  42. data/lib/arjdbc/mssql/database_limits.rb +2 -0
  43. data/lib/arjdbc/mssql/database_statements.rb +44 -6
  44. data/lib/arjdbc/mssql/errors.rb +2 -0
  45. data/lib/arjdbc/mssql/explain_support.rb +3 -1
  46. data/lib/arjdbc/mssql/extensions/attribute_methods.rb +5 -1
  47. data/lib/arjdbc/mssql/extensions/calculations.rb +2 -0
  48. data/lib/arjdbc/mssql/quoting.rb +38 -0
  49. data/lib/arjdbc/mssql/schema_creation.rb +24 -2
  50. data/lib/arjdbc/mssql/schema_definitions.rb +10 -0
  51. data/lib/arjdbc/mssql/schema_dumper.rb +2 -0
  52. data/lib/arjdbc/mssql/schema_statements.rb +63 -21
  53. data/lib/arjdbc/mssql/transaction.rb +2 -0
  54. data/lib/arjdbc/mssql/types.rb +2 -0
  55. data/lib/arjdbc/mssql/types/binary_types.rb +2 -0
  56. data/lib/arjdbc/mssql/types/date_and_time_types.rb +2 -0
  57. data/lib/arjdbc/mssql/types/deprecated_types.rb +2 -0
  58. data/lib/arjdbc/mssql/types/numeric_types.rb +2 -0
  59. data/lib/arjdbc/mssql/types/string_types.rb +2 -0
  60. data/lib/arjdbc/mssql/utils.rb +2 -0
  61. data/lib/arjdbc/mysql/adapter.rb +47 -18
  62. data/lib/arjdbc/mysql/connection_methods.rb +13 -7
  63. data/lib/arjdbc/postgresql/adapter.rb +240 -214
  64. data/lib/arjdbc/postgresql/base/array_decoder.rb +2 -0
  65. data/lib/arjdbc/postgresql/base/array_encoder.rb +4 -2
  66. data/lib/arjdbc/postgresql/base/array_parser.rb +4 -2
  67. data/lib/arjdbc/postgresql/base/pgconn.rb +2 -0
  68. data/lib/arjdbc/postgresql/column.rb +11 -6
  69. data/lib/arjdbc/postgresql/connection_methods.rb +3 -1
  70. data/lib/arjdbc/postgresql/name.rb +2 -0
  71. data/lib/arjdbc/postgresql/oid_types.rb +3 -1
  72. data/lib/arjdbc/sqlite3/adapter.rb +188 -180
  73. data/lib/arjdbc/sqlite3/connection_methods.rb +16 -4
  74. data/lib/arjdbc/tasks/databases.rake +13 -10
  75. data/lib/arjdbc/tasks/mssql_database_tasks.rb +49 -5
  76. data/lib/arjdbc/util/quoted_cache.rb +3 -1
  77. data/lib/arjdbc/util/serialized_attributes.rb +3 -1
  78. data/lib/arjdbc/util/table_copier.rb +3 -1
  79. data/lib/arjdbc/version.rb +1 -1
  80. data/pom.xml +4 -4
  81. data/rakelib/01-tomcat.rake +2 -2
  82. data/rakelib/02-test.rake +0 -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 +468 -637
  87. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +319 -38
  88. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +13 -23
  89. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +44 -31
  90. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +94 -99
  91. data/src/java/arjdbc/util/DateTimeUtils.java +34 -12
  92. metadata +7 -17
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  ArJdbc::ConnectionMethods.module_eval do
3
3
  def sqlite3_connection(config)
4
+ config = config.deep_dup
4
5
  config[:adapter_spec] ||= ::ArJdbc::SQLite3
5
6
  config[:adapter_class] = ActiveRecord::ConnectionAdapters::SQLite3Adapter unless config.key?(:adapter_class)
6
7
 
@@ -22,17 +23,27 @@ ArJdbc::ConnectionMethods.module_eval do
22
23
  raise
23
24
  end
24
25
  end
25
-
26
+
27
+ config[:properties] ||= {}
28
+
26
29
  database = config[:database] # NOTE: "jdbc:sqlite::memory:" syntax is supported
27
30
  config[:url] ||= "jdbc:sqlite:#{database == ':memory:' ? '' : database}"
28
31
  config[:connection_alive_sql] ||= 'SELECT 1'
29
32
 
33
+ if config[:readonly]
34
+ # See
35
+ # * http://sqlite.org/c3ref/open.html
36
+ # * http://sqlite.org/c3ref/c_open_autoproxy.html
37
+ # => 0x01 = readonly, 0x40 = uri (default in JDBC)
38
+ config[:properties][:open_mode] = 0x01 | 0x40
39
+ end
40
+
30
41
  timeout = config[:timeout]
31
42
  if timeout && timeout.to_s !~ /\A\d+\Z/
32
43
  raise TypeError.new "Timeout must be nil or a number (got: #{timeout})."
33
44
  end
34
45
 
35
- options = ( config[:properties] ||= {} )
46
+ options = config[:properties]
36
47
  options['busy_timeout'] ||= timeout unless timeout.nil?
37
48
 
38
49
  jdbc_connection(config)
@@ -50,8 +61,9 @@ ArJdbc::ConnectionMethods.module_eval do
50
61
  def parse_sqlite3_config!(config)
51
62
  database = ( config[:database] ||= config[:dbfile] )
52
63
  if ':memory:' != database
53
- config[:database] = File.expand_path(database, Rails.root) if defined?(Rails.root)
54
- dirname = File.dirname(database)
64
+ # make sure to have an absolute path. Ruby and Java don't agree on working directory
65
+ config[:database] = File.expand_path(database, defined?(Rails.root) ? Rails.root : nil)
66
+ dirname = File.dirname(config[:database])
55
67
  Dir.mkdir(dirname) unless File.directory?(dirname)
56
68
  end
57
69
  end
@@ -5,25 +5,28 @@ module ActiveRecord::Tasks
5
5
  DatabaseTasks.module_eval do
6
6
 
7
7
  # @override patched to adapt jdbc configuration
8
- def each_current_configuration(environment)
8
+ def each_current_configuration(environment, spec_name = nil)
9
9
  environments = [environment]
10
10
  environments << 'test' if environment == 'development'
11
11
 
12
- configurations = ActiveRecord::Base.configurations.values_at(*environments)
13
- configurations.compact.each do |config|
14
- yield adapt_jdbc_config(config) unless config['database'].blank?
12
+ environments.each do |env|
13
+ ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
14
+ next if spec_name && spec_name != db_config.spec_name
15
+
16
+ yield adapt_jdbc_config(db_config.config), db_config.spec_name, env unless db_config.config['database'].blank?
17
+ end
15
18
  end
16
19
  end
17
20
 
18
21
  # @override patched to adapt jdbc configuration
19
22
  def each_local_configuration
20
- ActiveRecord::Base.configurations.each_value do |config|
21
- next unless config['database']
23
+ ActiveRecord::Base.configurations.configs_for.each do |db_config|
24
+ next unless db_config.config['database']
22
25
 
23
- if local_database?(config)
24
- yield adapt_jdbc_config(config)
26
+ if local_database?(db_config.config)
27
+ yield adapt_jdbc_config(db_config.config)
25
28
  else
26
- $stderr.puts "This task only modifies local databases. #{config['database']} is on a remote host."
29
+ $stderr.puts "This task only modifies local databases. #{db_config.config['database']} is on a remote host."
27
30
  end
28
31
  end
29
32
  end
@@ -45,4 +48,4 @@ module ActiveRecord::Tasks
45
48
 
46
49
  end if const_defined?(:MySQLDatabaseTasks)
47
50
 
48
- end
51
+ end
@@ -1,17 +1,37 @@
1
+ require 'active_record/tasks/database_tasks'
2
+
1
3
  require 'arjdbc/tasks/jdbc_database_tasks'
2
4
 
3
5
  module ArJdbc
4
6
  module Tasks
5
7
  class MSSQLDatabaseTasks < JdbcDatabaseTasks
8
+ delegate :clear_active_connections!, to: ActiveRecord::Base
9
+
10
+ def create
11
+ establish_master_connection
12
+ connection.create_database(configuration['database'])
13
+ establish_connection configuration
14
+ rescue ActiveRecord::StatementInvalid => error
15
+ case error.message
16
+ when /database .* already exists/i
17
+ raise ActiveRecord::Tasks::DatabaseAlreadyExists
18
+ else
19
+ raise
20
+ end
21
+ end
22
+
23
+ def drop
24
+ establish_master_connection
25
+ connection.drop_database configuration['database']
26
+ end
6
27
 
7
28
  def purge
8
- test = deep_dup(configuration)
9
- test_database = resolve_database(test)
10
- test['database'] = 'master'
11
- establish_connection(test)
12
- connection.recreate_database(test_database)
29
+ clear_active_connections!
30
+ drop
31
+ create
13
32
  end
14
33
 
34
+
15
35
  def structure_dump(filename)
16
36
  config = config_from_url_if_needed
17
37
  `smoscript -s #{config['host']} -d #{config['database']} -u #{config['username']} -p #{config['password']} -f #{filename} -A -U`
@@ -24,6 +44,10 @@ module ArJdbc
24
44
 
25
45
  private
26
46
 
47
+ def establish_master_connection
48
+ establish_connection configuration.merge('database' => 'master')
49
+ end
50
+
27
51
  def config_from_url_if_needed
28
52
  config = self.config
29
53
  if config['url'] && ! config.key?('database')
@@ -42,5 +66,25 @@ module ArJdbc
42
66
  end
43
67
 
44
68
  end
69
+
70
+ module DatabaseTasksMSSQL
71
+ extend ActiveSupport::Concern
72
+
73
+ module ClassMethods
74
+
75
+ def check_protected_environments!
76
+ super
77
+ rescue ActiveRecord::JDBCError => error
78
+ case error.message
79
+ when /cannot open database .* requested by the login/i
80
+ else
81
+ raise
82
+ end
83
+ end
84
+
85
+ end
86
+ end
87
+
88
+ ActiveRecord::Tasks::DatabaseTasks.send :include, DatabaseTasksMSSQL
45
89
  end
46
90
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ArJdbc
2
4
  module Util
3
5
  # Caches table and column name (quoted) outcomes.
@@ -57,4 +59,4 @@ module ArJdbc
57
59
 
58
60
  end
59
61
  end
60
- end
62
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ArJdbc
2
4
  module Util
3
5
  # Gets included into `ActiveRecord::Base` to support sending LOB values
@@ -95,4 +97,4 @@ module ArJdbc
95
97
  end
96
98
  # @private only due backwards compatibility
97
99
  SerializedAttributesHelper = Util::SerializedAttributes
98
- end
100
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ArJdbc
2
4
  module Util
3
5
  module TableCopier
@@ -107,4 +109,4 @@ module ArJdbc
107
109
  end
108
110
  # @private @deprecated backwards compatibility
109
111
  MissingFunctionalityHelper = Util::TableCopier
110
- end
112
+ end
@@ -1,3 +1,3 @@
1
1
  module ArJdbc
2
- VERSION = '52.2.3'
2
+ VERSION = '60.1.0'
3
3
  end
data/pom.xml CHANGED
@@ -12,7 +12,7 @@
12
12
  <url>http://github.com/jruby/activerecord-jdbc-adapter/wiki</url>
13
13
 
14
14
  <properties>
15
- <jruby.version>9.1.6.0</jruby.version>
15
+ <jruby.version>9.2.6.0</jruby.version>
16
16
  </properties>
17
17
 
18
18
  <issueManagement>
@@ -75,7 +75,7 @@
75
75
  <dependency>
76
76
  <groupId>org.postgresql</groupId>
77
77
  <artifactId>postgresql</artifactId>
78
- <version>42.1.4.jre7</version>
78
+ <version>42.1.4</version>
79
79
  </dependency>
80
80
  </dependencies>
81
81
 
@@ -103,8 +103,8 @@
103
103
  <artifactId>maven-compiler-plugin</artifactId>
104
104
  <version>2.5.1</version>
105
105
  <configuration>
106
- <source>1.7</source>
107
- <target>1.7</target>
106
+ <source>1.8</source>
107
+ <target>1.8</target>
108
108
  </configuration>
109
109
  </plugin>
110
110
  </plugins>
@@ -1,6 +1,6 @@
1
1
  namespace :'tomcat-jndi' do # contains a FS JNDI impl (for tests)
2
2
 
3
- TOMCAT_MAVEN_REPO = 'http://repo2.maven.org/maven2/org/apache/tomcat'
3
+ TOMCAT_MAVEN_REPO = 'https://repo1.maven.org/maven2/org/apache/tomcat'
4
4
  TOMCAT_VERSION = '7.0.54'
5
5
 
6
6
  DOWNLOAD_DIR = File.expand_path('../test/jars', File.dirname(__FILE__))
@@ -48,4 +48,4 @@ namespace :'tomcat-jndi' do # contains a FS JNDI impl (for tests)
48
48
  rm jar_path if File.exist?(jar_path)
49
49
  end
50
50
 
51
- end
51
+ end
@@ -76,8 +76,6 @@ end
76
76
  test_task_for adapter, :desc => "Run tests against #{adapter} (ensure driver is on class-path)"
77
77
  end
78
78
 
79
- #test_task_for :MSSQL, :name => 'test_sqlserver', :driver => nil, :database_name => 'MS-SQL using SQLJDBC'
80
-
81
79
  test_task_for :AS400, :desc => "Run tests against AS400 (DB2) (ensure driver is on class-path)",
82
80
  :files => FileList["test/db2*_test.rb"] + FileList["test/db/db2/*_test.rb"]
83
81
 
@@ -57,7 +57,7 @@ namespace :rails do
57
57
  ruby_opts_string += " -C \"#{ar_path}\""
58
58
  ruby_opts_string += " -rbundler/setup"
59
59
  ruby_opts_string += " -rminitest -rminitest/excludes" unless ENV['NO_EXCLUDES'].eql?('true')
60
- file_list = ENV["TEST"] ? FileList[ ENV["TEST"] ] : test_files_finder.call
60
+ file_list = ENV["TEST"] ? FileList[ ENV["TEST"].split(',') ] : test_files_finder.call
61
61
  file_list_string = file_list.map { |fn| "\"#{fn}\"" }.join(' ')
62
62
  # test_loader_code = "-e \"ARGV.each{|f| require f}\"" # :direct
63
63
  option_list = ( ENV["TESTOPTS"] || ENV["TESTOPT"] || ENV["TEST_OPTS"] || '' )
@@ -151,7 +151,7 @@ public class ArJdbcModule {
151
151
  throw newNativeException(runtime, e);
152
152
  }
153
153
 
154
- return runtime.getTrue();
154
+ return context.tru;
155
155
  }
156
156
 
157
157
  /**
@@ -191,7 +191,7 @@ public class ArJdbcModule {
191
191
  }
192
192
 
193
193
  // NOTE: probably useless - only to be useful for the pooled runtime mode when jar at WEB-INF/lib
194
- static final Map<Ruby, Map<String, Boolean>> loadedDrivers = new WeakHashMap<Ruby, Map<String, Boolean>>(8);
194
+ static final Map<Ruby, Map<String, Boolean>> loadedDrivers = new WeakHashMap<>(8);
195
195
 
196
196
  private static IRubyObject loadDriver(final ThreadContext context, final IRubyObject self,
197
197
  final String constName) {
@@ -202,7 +202,7 @@ public class ArJdbcModule {
202
202
  synchronized (ArJdbcModule.class) {
203
203
  loadedMap = loadedDrivers.get(runtime);
204
204
  if ( loadedMap == null ) {
205
- loadedMap = new HashMap<String, Boolean>(4);
205
+ loadedMap = new HashMap<>(4);
206
206
  loadedDrivers.put(runtime, loadedMap);
207
207
  }
208
208
  }
@@ -210,8 +210,8 @@ public class ArJdbcModule {
210
210
 
211
211
  final Boolean driverLoaded = loadedMap.get(constName);
212
212
  if ( driverLoaded != null ) {
213
- if ( driverLoaded.booleanValue() ) return runtime.getFalse();
214
- return runtime.getNil();
213
+ if (driverLoaded) return context.fals;
214
+ return context.nil;
215
215
  }
216
216
 
217
217
  try { // require 'jdbc/mysql'
@@ -60,15 +60,7 @@ public class DriverWrapper {
60
60
 
61
61
  private Driver allocateDriver(final Class<? extends Driver> driverClass)
62
62
  throws InstantiationException, IllegalAccessException {
63
- try {
64
- return driverClass.newInstance();
65
- }
66
- catch (InstantiationException e) {
67
- throw e;
68
- }
69
- catch (IllegalAccessException e) {
70
- throw e;
71
- }
63
+ return driverClass.newInstance();
72
64
  }
73
65
 
74
66
  protected static Class<? extends Driver> loadDriver(final Ruby runtime, final String name)
@@ -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,7 @@ 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
89
  import org.jruby.javasupport.JavaEmbedUtils;
90
90
  import org.jruby.javasupport.JavaUtil;
91
91
  import org.jruby.runtime.Block;
@@ -147,11 +147,6 @@ public class RubyJdbcConnection extends RubyObject {
147
147
  return JdbcConnection;
148
148
  }
149
149
 
150
- @Deprecated
151
- public static RubyClass getJdbcConnectionClass(final Ruby runtime) {
152
- return getConnectionAdapters(runtime).getClass("JdbcConnection");
153
- }
154
-
155
150
  public static RubyClass getJdbcConnection(final Ruby runtime) {
156
151
  return (RubyClass) getConnectionAdapters(runtime).getConstantAt("JdbcConnection");
157
152
  }
@@ -231,34 +226,30 @@ public class RubyJdbcConnection extends RubyObject {
231
226
 
232
227
  @JRubyMethod(name = "transaction_isolation", alias = "get_transaction_isolation")
233
228
  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
- }
229
+ return withConnection(context, connection -> {
230
+ final int level = connection.getTransactionIsolation();
231
+ final String isolationSymbol = formatTransactionIsolationLevel(level);
232
+ if ( isolationSymbol == null ) return context.nil;
233
+ return context.runtime.newSymbol(isolationSymbol);
241
234
  });
242
235
  }
243
236
 
244
237
  @JRubyMethod(name = "transaction_isolation=", alias = "set_transaction_isolation")
245
238
  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
- }
239
+ return withConnection(context, connection -> {
240
+ final int level;
241
+ if ( isolation.isNil() ) {
242
+ level = connection.getMetaData().getDefaultTransactionIsolation();
243
+ }
244
+ else {
245
+ level = mapTransactionIsolationLevel(isolation);
246
+ }
255
247
 
256
- connection.setTransactionIsolation(level);
248
+ connection.setTransactionIsolation(level);
257
249
 
258
- final String isolationSymbol = formatTransactionIsolationLevel(level);
259
- if ( isolationSymbol == null ) return context.nil;
260
- return context.runtime.newSymbol(isolationSymbol);
261
- }
250
+ final String isolationSymbol = formatTransactionIsolationLevel(level);
251
+ if ( isolationSymbol == null ) return context.nil;
252
+ return context.runtime.newSymbol(isolationSymbol);
262
253
  });
263
254
  }
264
255
 
@@ -306,31 +297,25 @@ public class RubyJdbcConnection extends RubyObject {
306
297
  final IRubyObject[] args) throws SQLException {
307
298
  final IRubyObject isolation = args.length > 0 ? args[0] : null;
308
299
 
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);
300
+ return withConnection(context, (Callable<IRubyObject>) connection -> {
301
+ final DatabaseMetaData metaData = connection.getMetaData();
302
+ final boolean supported;
303
+ if ( isolation != null && ! isolation.isNil() ) {
304
+ final int level = mapTransactionIsolationLevel(isolation);
305
+ supported = metaData.supportsTransactionIsolationLevel(level);
322
306
  }
307
+ else {
308
+ final int level = metaData.getDefaultTransactionIsolation();
309
+ supported = level > Connection.TRANSACTION_NONE; // > 0
310
+ }
311
+ return context.runtime.newBoolean(supported);
323
312
  });
324
313
  }
325
314
 
326
315
  @JRubyMethod(name = {"begin", "transaction"}, required = 1) // optional isolation argument for AR-4.0
327
316
  public IRubyObject begin(final ThreadContext context, final IRubyObject isolation) {
328
317
  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
- });
318
+ return withConnection(context, false, connection -> beginTransaction(context, connection, isolation == context.nil ? null : isolation));
334
319
  } catch (SQLException e) {
335
320
  return handleException(context, e);
336
321
  }
@@ -339,11 +324,7 @@ public class RubyJdbcConnection extends RubyObject {
339
324
  @JRubyMethod(name = {"begin", "transaction"}) // optional isolation argument for AR-4.0
340
325
  public IRubyObject begin(final ThreadContext context) {
341
326
  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
- });
327
+ return withConnection(context, false, connection -> beginTransaction(context, connection, null));
347
328
  } catch (SQLException e) {
348
329
  return handleException(context, e);
349
330
  }
@@ -373,8 +354,8 @@ public class RubyJdbcConnection extends RubyObject {
373
354
 
374
355
  @JRubyMethod(name = "commit")
375
356
  public IRubyObject commit(final ThreadContext context) {
376
- final Connection connection = getConnection(true);
377
357
  try {
358
+ final Connection connection = getConnectionInternal(true);
378
359
  if ( ! connection.getAutoCommit() ) {
379
360
  try {
380
361
  connection.commit();
@@ -394,13 +375,13 @@ public class RubyJdbcConnection extends RubyObject {
394
375
 
395
376
  @JRubyMethod(name = "rollback")
396
377
  public IRubyObject rollback(final ThreadContext context) {
397
- final Connection connection = getConnection(true);
398
378
  try {
379
+ final Connection connection = getConnectionInternal(true);
399
380
  if ( ! connection.getAutoCommit() ) {
400
381
  try {
401
382
  connection.rollback();
402
383
  resetSavepoints(context); // if any
403
- return context.runtime.getTrue();
384
+ return context.tru;
404
385
  } finally {
405
386
  connection.setAutoCommit(true);
406
387
  }
@@ -414,11 +395,9 @@ public class RubyJdbcConnection extends RubyObject {
414
395
 
415
396
  @JRubyMethod(name = "supports_savepoints?")
416
397
  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
- }
398
+ return withConnection(context, (Callable<IRubyObject>) connection -> {
399
+ final DatabaseMetaData metaData = connection.getMetaData();
400
+ return context.runtime.newBoolean( metaData.supportsSavepoints() );
422
401
  });
423
402
  }
424
403
 
@@ -429,8 +408,8 @@ public class RubyJdbcConnection extends RubyObject {
429
408
 
430
409
  @JRubyMethod(name = "create_savepoint", required = 1)
431
410
  public IRubyObject create_savepoint(final ThreadContext context, IRubyObject name) {
432
- final Connection connection = getConnection(true);
433
411
  try {
412
+ final Connection connection = getConnectionInternal(true);
434
413
  connection.setAutoCommit(false);
435
414
 
436
415
  final Savepoint savepoint ;
@@ -458,8 +437,8 @@ public class RubyJdbcConnection extends RubyObject {
458
437
  public IRubyObject rollback_savepoint(final ThreadContext context, final IRubyObject name) {
459
438
  if (name == context.nil) throw context.runtime.newArgumentError("nil savepoint name given");
460
439
 
461
- final Connection connection = getConnection(true);
462
440
  try {
441
+ final Connection connection = getConnectionInternal(true);
463
442
  Savepoint savepoint = getSavepoints(context).get(name);
464
443
  if ( savepoint == null ) {
465
444
  throw context.runtime.newRuntimeError("could not rollback savepoint: '" + name + "' (not set)");
@@ -476,7 +455,6 @@ public class RubyJdbcConnection extends RubyObject {
476
455
  public IRubyObject release_savepoint(final ThreadContext context, final IRubyObject name) {
477
456
  if (name == context.nil) throw context.runtime.newArgumentError("nil savepoint name given");
478
457
 
479
- final Connection connection = getConnection(true);
480
458
  try {
481
459
  Object savepoint = getSavepoints(context).remove(name);
482
460
 
@@ -487,7 +465,8 @@ public class RubyJdbcConnection extends RubyObject {
487
465
  savepoint = ((IRubyObject) savepoint).toJava(Savepoint.class);
488
466
  }
489
467
 
490
- connection.releaseSavepoint((Savepoint) savepoint);
468
+ final Connection connection = getConnectionInternal(true);
469
+ releaseSavepoint(connection, (Savepoint) savepoint);
491
470
  return context.nil;
492
471
  }
493
472
  catch (SQLException e) {
@@ -495,6 +474,11 @@ public class RubyJdbcConnection extends RubyObject {
495
474
  }
496
475
  }
497
476
 
477
+ // MSSQL doesn't support releasing savepoints so we make it possible to override the actual release action
478
+ protected void releaseSavepoint(final Connection connection, final Savepoint savepoint) throws SQLException {
479
+ connection.releaseSavepoint(savepoint);
480
+ }
481
+
498
482
  protected static RuntimeException newSavepointNotSetError(final ThreadContext context, final IRubyObject name, final String op) {
499
483
  RubyClass StatementInvalid = ActiveRecord(context).getClass("StatementInvalid");
500
484
  return context.runtime.newRaiseException(StatementInvalid, "could not " + op + " savepoint: '" + name + "' (not set)");
@@ -520,7 +504,7 @@ public class RubyJdbcConnection extends RubyObject {
520
504
  }
521
505
 
522
506
  @SuppressWarnings("unchecked")
523
- private final Map<IRubyObject, Savepoint> getSavepoints(final boolean init) {
507
+ private Map<IRubyObject, Savepoint> getSavepoints(final boolean init) {
524
508
  if ( hasInternalVariable("savepoints") ) {
525
509
  return (Map<IRubyObject, Savepoint>) getInternalVariable("savepoints");
526
510
  }
@@ -540,13 +524,6 @@ public class RubyJdbcConnection extends RubyObject {
540
524
  return false;
541
525
  }
542
526
 
543
- @Deprecated // second argument is now mandatory - only kept for compatibility
544
- @JRubyMethod(required = 1)
545
- public final IRubyObject initialize(final ThreadContext context, final IRubyObject config) {
546
- doInitialize(context, config, context.nil);
547
- return this;
548
- }
549
-
550
527
  @JRubyMethod(required = 2)
551
528
  public final IRubyObject initialize(final ThreadContext context, final IRubyObject config, final IRubyObject adapter) {
552
529
  doInitialize(context, config, adapter);
@@ -554,12 +531,17 @@ public class RubyJdbcConnection extends RubyObject {
554
531
  }
555
532
 
556
533
  protected void doInitialize(final ThreadContext context, final IRubyObject config, final IRubyObject adapter) {
557
- this.config = config; this.adapter = adapter;
534
+ this.config = config;
535
+ this.adapter = adapter;
558
536
 
559
537
  this.jndi = setupConnectionFactory(context);
560
538
  this.lazy = jndi; // JNDIs are lazy by default otherwise eager
561
539
  try {
562
- initConnection(context);
540
+ if (adapter == null || adapter == context.nil) {
541
+ warn(context, "adapter not set, please pass adapter on JdbcConnection#initialize(config, adapter)");
542
+ }
543
+
544
+ if (!lazy) setConnection(newConnection());
563
545
  }
564
546
  catch (SQLException e) {
565
547
  String message = e.getMessage();
@@ -570,7 +552,7 @@ public class RubyJdbcConnection extends RubyObject {
570
552
  IRubyObject value = getConfigValue(context, "configure_connection");
571
553
  if ( value == context.nil ) this.configureConnection = true;
572
554
  else {
573
- this.configureConnection = value != context.runtime.getFalse();
555
+ this.configureConnection = value != context.fals;
574
556
  }
575
557
 
576
558
  IRubyObject jdbcFetchSize = getConfigValue(context, "jdbc_fetch_size");
@@ -581,7 +563,6 @@ public class RubyJdbcConnection extends RubyObject {
581
563
 
582
564
  @JRubyMethod(name = "adapter")
583
565
  public IRubyObject adapter(final ThreadContext context) {
584
- final IRubyObject adapter = getAdapter();
585
566
  return adapter == null ? context.nil : adapter;
586
567
  }
587
568
 
@@ -596,43 +577,9 @@ public class RubyJdbcConnection extends RubyObject {
596
577
  return factory;
597
578
  }
598
579
 
599
- /**
600
- * Called during <code>initialize</code> after the connection factory
601
- * has been set to check if we can connect and/or perform any initialization
602
- * necessary.
603
- * <br/>
604
- * NOTE: connection has not been configured at this point,
605
- * nor should we retry - we're creating a brand new JDBC connection
606
- *
607
- * @param context
608
- * @return connection
609
- */
610
- @Deprecated
611
- @JRubyMethod(name = "init_connection")
612
- public synchronized IRubyObject init_connection(final ThreadContext context) {
613
- try {
614
- return initConnection(context);
615
- }
616
- catch (SQLException e) {
617
- return handleException(context, e); // throws
618
- }
619
- }
620
-
621
- private IRubyObject initConnection(final ThreadContext context) throws SQLException {
622
- final IRubyObject adapter = getAdapter(); // self.adapter
623
- if ( adapter == null || adapter == context.nil ) {
624
- warn(context, "adapter not set, please pass adapter on JdbcConnection#initialize(config, adapter)");
625
- }
626
-
627
- if ( ! lazy ) setConnection( newConnection() );
628
-
629
- return context.nil;
630
- }
631
-
632
580
  private void configureConnection() {
633
581
  if ( ! configureConnection ) return; // return false;
634
582
 
635
- final IRubyObject adapter = getAdapter(); // self.adapter
636
583
  if ( adapter != null && ! adapter.isNil() ) {
637
584
  if ( adapter.respondsTo("configure_connection") ) {
638
585
  final ThreadContext context = getRuntime().getCurrentContext();
@@ -654,7 +601,7 @@ public class RubyJdbcConnection extends RubyObject {
654
601
 
655
602
  @JRubyMethod(name = "jdbc_connection", alias = "connection", required = 1)
656
603
  public final IRubyObject connection(final ThreadContext context, final IRubyObject unwrap) {
657
- if ( unwrap == context.nil || unwrap == context.runtime.getFalse() ) {
604
+ if ( unwrap == context.nil || unwrap == context.fals ) {
658
605
  return connection(context);
659
606
  }
660
607
  Connection connection = connectionImpl(context);
@@ -690,18 +637,25 @@ public class RubyJdbcConnection extends RubyObject {
690
637
 
691
638
  @JRubyMethod(name = "active?", alias = "valid?")
692
639
  public RubyBoolean active_p(final ThreadContext context) {
693
- if ( ! connected ) return context.runtime.getFalse();
694
- if ( isJndi() ) {
640
+ if ( ! connected ) return context.fals;
641
+ if (jndi) {
695
642
  // for JNDI the data-source / pool is supposed to
696
643
  // manage connections for us thus no valid check!
697
644
  boolean active = getConnectionFactory() != null;
698
645
  return context.runtime.newBoolean( active );
699
646
  }
700
- final Connection connection = getConnection();
701
- if ( connection == null ) return context.runtime.getFalse(); // unlikely
647
+ final Connection connection = getConnection(false);
648
+ if ( connection == null ) return context.fals; // unlikely
702
649
  return context.runtime.newBoolean( isConnectionValid(context, connection) );
703
650
  }
704
651
 
652
+ @JRubyMethod(name = "really_valid?")
653
+ public RubyBoolean really_valid_p(final ThreadContext context) {
654
+ final Connection connection = getConnection(true);
655
+ if (connection == null) return context.fals;
656
+ return context.runtime.newBoolean(isConnectionValid(context, connection));
657
+ }
658
+
705
659
  @JRubyMethod(name = "disconnect!")
706
660
  public synchronized IRubyObject disconnect(final ThreadContext context) {
707
661
  setConnection(null); connected = false;
@@ -722,38 +676,43 @@ public class RubyJdbcConnection extends RubyObject {
722
676
 
723
677
  private void connectImpl(final boolean forceConnection) throws SQLException {
724
678
  setConnection( forceConnection ? newConnection() : null );
725
- if ( forceConnection ) configureConnection();
679
+ if (forceConnection) {
680
+ if (getConnectionImpl() == null) throw new SQLException("Didn't get a connection. Wrong URL?");
681
+ configureConnection();
682
+ }
726
683
  }
727
684
 
728
685
  @JRubyMethod(name = "read_only?")
729
686
  public IRubyObject is_read_only(final ThreadContext context) {
730
- final Connection connection = getConnection(false);
731
- if ( connection != null ) {
732
- try {
733
- return context.runtime.newBoolean( connection.isReadOnly() );
687
+ try {
688
+ final Connection connection = getConnectionInternal(false);
689
+ if (connection != null) {
690
+ return context.runtime.newBoolean(connection.isReadOnly());
734
691
  }
735
- catch (SQLException e) { return handleException(context, e); }
692
+ } catch (SQLException e) {
693
+ return handleException(context, e);
736
694
  }
737
695
  return context.nil;
738
696
  }
739
697
 
740
698
  @JRubyMethod(name = "read_only=")
741
699
  public IRubyObject set_read_only(final ThreadContext context, final IRubyObject flag) {
742
- final Connection connection = getConnection(true);
743
700
  try {
701
+ final Connection connection = getConnectionInternal(true);
744
702
  connection.setReadOnly( flag.isTrue() );
745
703
  return context.runtime.newBoolean( connection.isReadOnly() );
704
+ } catch (SQLException e) {
705
+ return handleException(context, e);
746
706
  }
747
- catch (SQLException e) { return handleException(context, e); }
748
707
  }
749
708
 
750
709
  @JRubyMethod(name = { "open?" /* "conn?" */ })
751
710
  public IRubyObject open_p(final ThreadContext context) {
752
- final Connection connection = getConnection(false);
711
+ try {
712
+ final Connection connection = getConnectionInternal(false);
753
713
 
754
- if (connection == null) return context.runtime.getFalse();
714
+ if (connection == null) return context.fals;
755
715
 
756
- try {
757
716
  // NOTE: isClosed method generally cannot be called to determine
758
717
  // whether a connection to a database is valid or invalid ...
759
718
  return context.runtime.newBoolean(!connection.isClosed());
@@ -766,10 +725,10 @@ public class RubyJdbcConnection extends RubyObject {
766
725
  public IRubyObject close(final ThreadContext context) {
767
726
  final Connection connection = getConnection(false);
768
727
 
769
- if (connection == null) return context.runtime.getFalse();
728
+ if (connection == null) return context.fals;
770
729
 
771
730
  try {
772
- if (connection.isClosed()) return context.runtime.getFalse();
731
+ if (connection.isClosed()) return context.fals;
773
732
 
774
733
  setConnection(null); // does connection.close();
775
734
  } catch (Exception e) {
@@ -779,69 +738,65 @@ public class RubyJdbcConnection extends RubyObject {
779
738
 
780
739
  // ActiveRecord expects a closed connection to not try and re-open a connection
781
740
  // whereas JNDI expects that.
782
- if (!isJndi()) disconnect(context);
741
+ if (!jndi) disconnect(context);
783
742
 
784
- return context.runtime.getTrue();
743
+ return context.tru;
785
744
  }
786
745
 
787
746
  @JRubyMethod(name = "database_name")
788
747
  public IRubyObject database_name(final ThreadContext context) {
789
- return withConnection(context, new Callable<IRubyObject>() {
790
- public IRubyObject call(final Connection connection) throws SQLException {
791
- String name = connection.getCatalog();
792
- if ( name == null ) {
793
- name = connection.getMetaData().getUserName();
794
- if ( name == null ) return context.nil;
795
- }
796
- return context.runtime.newString(name);
748
+ return withConnection(context, connection -> {
749
+ String name = connection.getCatalog();
750
+ if ( name == null ) {
751
+ name = connection.getMetaData().getUserName();
752
+ if ( name == null ) return context.nil;
797
753
  }
754
+ return context.runtime.newString(name);
798
755
  });
799
756
  }
800
757
 
801
758
  @JRubyMethod(name = "execute", required = 1)
802
759
  public IRubyObject execute(final ThreadContext context, final IRubyObject sql) {
803
760
  final String query = sqlString(sql);
804
- return withConnection(context, new Callable<IRubyObject>() {
805
- public IRubyObject call(final Connection connection) throws SQLException {
806
- Statement statement = null;
807
- try {
808
- statement = createStatement(context, connection);
809
-
810
- // For DBs that do support multiple statements, lets return the last result set
811
- // to be consistent with AR
812
- boolean hasResultSet = doExecute(statement, query);
813
- int updateCount = statement.getUpdateCount();
761
+ return withConnection(context, connection -> {
762
+ Statement statement = null;
763
+ try {
764
+ statement = createStatement(context, connection);
814
765
 
815
- IRubyObject result = context.nil; // If no results, return nil
816
- ResultSet resultSet;
766
+ // For DBs that do support multiple statements, lets return the last result set
767
+ // to be consistent with AR
768
+ boolean hasResultSet = doExecute(statement, query);
769
+ int updateCount = statement.getUpdateCount();
817
770
 
818
- while (hasResultSet || updateCount != -1) {
771
+ IRubyObject result = context.nil; // If no results, return nil
772
+ ResultSet resultSet;
819
773
 
820
- if (hasResultSet) {
821
- resultSet = statement.getResultSet();
774
+ while (hasResultSet || updateCount != -1) {
822
775
 
823
- // Unfortunately the result set gets closed when getMoreResults()
824
- // is called, so we have to process the result sets as we get them
825
- // this shouldn't be an issue in most cases since we're only getting 1 result set anyways
826
- result = mapExecuteResult(context, connection, resultSet);
827
- resultSet.close();
828
- } else {
829
- result = context.runtime.newFixnum(updateCount);
830
- }
776
+ if (hasResultSet) {
777
+ resultSet = statement.getResultSet();
831
778
 
832
- // Check to see if there is another result set
833
- hasResultSet = statement.getMoreResults();
834
- updateCount = statement.getUpdateCount();
779
+ // Unfortunately the result set gets closed when getMoreResults()
780
+ // is called, so we have to process the result sets as we get them
781
+ // this shouldn't be an issue in most cases since we're only getting 1 result set anyways
782
+ result = mapExecuteResult(context, connection, resultSet);
783
+ resultSet.close();
784
+ } else {
785
+ result = context.runtime.newFixnum(updateCount);
835
786
  }
836
787
 
837
- return result;
838
-
839
- } catch (final SQLException e) {
840
- debugErrorSQL(context, query);
841
- throw e;
842
- } finally {
843
- close(statement);
788
+ // Check to see if there is another result set
789
+ hasResultSet = statement.getMoreResults();
790
+ updateCount = statement.getUpdateCount();
844
791
  }
792
+
793
+ return result;
794
+
795
+ } catch (final SQLException e) {
796
+ debugErrorSQL(context, query);
797
+ throw e;
798
+ } finally {
799
+ close(statement);
845
800
  }
846
801
  });
847
802
  }
@@ -880,15 +835,31 @@ public class RubyJdbcConnection extends RubyObject {
880
835
  return mapQueryResult(context, connection, resultSet);
881
836
  }
882
837
 
838
+ private static String[] createStatementPk(IRubyObject pk) {
839
+ String[] statementPk;
840
+ if (pk instanceof RubyArray) {
841
+ RubyArray ary = (RubyArray) pk;
842
+ int size = ary.size();
843
+ statementPk = new String[size];
844
+ for (int i = 0; i < size; i++) {
845
+ statementPk[i] = sqlString(ary.eltInternal(i));
846
+ }
847
+ } else {
848
+ statementPk = new String[] { sqlString(pk) };
849
+ }
850
+ return statementPk;
851
+ }
852
+
883
853
  /**
884
854
  * Executes an INSERT SQL statement
885
855
  * @param context
886
856
  * @param sql
857
+ * @param pk Rails PK
887
858
  * @return ActiveRecord::Result
888
859
  * @throws SQLException
889
860
  */
890
- @JRubyMethod(name = "execute_insert", required = 1)
891
- public IRubyObject execute_insert(final ThreadContext context, final IRubyObject sql) {
861
+ @JRubyMethod(name = "execute_insert_pk", required = 2)
862
+ public IRubyObject execute_insert_pk(final ThreadContext context, final IRubyObject sql, final IRubyObject pk) {
892
863
  return withConnection(context, new Callable<IRubyObject>() {
893
864
  public IRubyObject call(final Connection connection) throws SQLException {
894
865
  Statement statement = null;
@@ -896,9 +867,14 @@ public class RubyJdbcConnection extends RubyObject {
896
867
  try {
897
868
 
898
869
  statement = createStatement(context, connection);
899
- statement.executeUpdate(query, Statement.RETURN_GENERATED_KEYS);
900
- return mapGeneratedKeys(context, connection, statement);
901
870
 
871
+ if (pk == context.nil || pk == context.fals || !supportsGeneratedKeys(connection)) {
872
+ statement.executeUpdate(query, Statement.RETURN_GENERATED_KEYS);
873
+ } else {
874
+ statement.executeUpdate(query, createStatementPk(pk));
875
+ }
876
+
877
+ return mapGeneratedKeys(context, connection, statement);
902
878
  } catch (final SQLException e) {
903
879
  debugErrorSQL(context, query);
904
880
  throw e;
@@ -909,27 +885,38 @@ public class RubyJdbcConnection extends RubyObject {
909
885
  });
910
886
  }
911
887
 
888
+ @Deprecated
889
+ @JRubyMethod(name = "execute_insert", required = 1)
890
+ public IRubyObject execute_insert(final ThreadContext context, final IRubyObject sql) {
891
+ return execute_insert_pk(context, sql, context.nil);
892
+ }
893
+
912
894
  /**
913
895
  * Executes an INSERT SQL statement using a prepared statement
914
896
  * @param context
915
897
  * @param sql
916
898
  * @param binds RubyArray of values to be bound to the query
899
+ * @param pk Rails PK
917
900
  * @return ActiveRecord::Result
918
901
  * @throws SQLException
919
902
  */
920
- @JRubyMethod(name = "execute_insert", required = 2)
921
- public IRubyObject execute_insert(final ThreadContext context, final IRubyObject sql, final IRubyObject binds) {
903
+ @JRubyMethod(name = "execute_insert_pk", required = 3)
904
+ public IRubyObject execute_insert_pk(final ThreadContext context, final IRubyObject sql, final IRubyObject binds,
905
+ final IRubyObject pk) {
922
906
  return withConnection(context, new Callable<IRubyObject>() {
923
907
  public IRubyObject call(final Connection connection) throws SQLException {
924
908
  PreparedStatement statement = null;
925
909
  final String query = sqlString(sql);
926
910
  try {
911
+ if (pk == context.nil || pk == context.fals || !supportsGeneratedKeys(connection)) {
912
+ statement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
913
+ } else {
914
+ statement = connection.prepareStatement(query, createStatementPk(pk));
915
+ }
927
916
 
928
- statement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
929
917
  setStatementParameters(context, connection, statement, (RubyArray) binds);
930
918
  statement.executeUpdate();
931
919
  return mapGeneratedKeys(context, connection, statement);
932
-
933
920
  } catch (final SQLException e) {
934
921
  debugErrorSQL(context, query);
935
922
  throw e;
@@ -940,6 +927,12 @@ public class RubyJdbcConnection extends RubyObject {
940
927
  });
941
928
  }
942
929
 
930
+ @Deprecated
931
+ @JRubyMethod(name = "execute_insert", required = 2)
932
+ public IRubyObject execute_insert(final ThreadContext context, final IRubyObject binds, final IRubyObject sql) {
933
+ return execute_insert_pk(context, sql, binds, context.nil);
934
+ }
935
+
943
936
  /**
944
937
  * Executes an UPDATE (DELETE) SQL statement
945
938
  * @param context
@@ -949,22 +942,20 @@ public class RubyJdbcConnection extends RubyObject {
949
942
  */
950
943
  @JRubyMethod(name = {"execute_update", "execute_delete"}, required = 1)
951
944
  public IRubyObject execute_update(final ThreadContext context, final IRubyObject sql) {
952
- return withConnection(context, new Callable<IRubyObject>() {
953
- public IRubyObject call(final Connection connection) throws SQLException {
954
- Statement statement = null;
955
- final String query = sqlString(sql);
945
+ return withConnection(context, (Callable<IRubyObject>) connection -> {
946
+ Statement statement = null;
947
+ final String query = sqlString(sql);
956
948
 
957
- try {
958
- statement = createStatement(context, connection);
949
+ try {
950
+ statement = createStatement(context, connection);
959
951
 
960
- final int rowCount = statement.executeUpdate(query);
961
- return context.runtime.newFixnum(rowCount);
962
- } catch (final SQLException e) {
963
- debugErrorSQL(context, query);
964
- throw e;
965
- } finally {
966
- close(statement);
967
- }
952
+ final int rowCount = statement.executeUpdate(query);
953
+ return context.runtime.newFixnum(rowCount);
954
+ } catch (final SQLException e) {
955
+ debugErrorSQL(context, query);
956
+ throw e;
957
+ } finally {
958
+ close(statement);
968
959
  }
969
960
  });
970
961
  }
@@ -980,21 +971,19 @@ public class RubyJdbcConnection extends RubyObject {
980
971
  */
981
972
  @JRubyMethod(name = {"execute_prepared_update", "execute_prepared_delete"}, required = 2)
982
973
  public IRubyObject execute_prepared_update(final ThreadContext context, final IRubyObject sql, final IRubyObject binds) {
983
- return withConnection(context, new Callable<IRubyObject>() {
984
- public IRubyObject call(final Connection connection) throws SQLException {
985
- PreparedStatement statement = null;
986
- final String query = sqlString(sql);
987
- try {
988
- statement = connection.prepareStatement(query);
989
- setStatementParameters(context, connection, statement, (RubyArray) binds);
990
- final int rowCount = statement.executeUpdate();
991
- return context.runtime.newFixnum(rowCount);
992
- } catch (final SQLException e) {
993
- debugErrorSQL(context, query);
994
- throw e;
995
- } finally {
996
- close(statement);
997
- }
974
+ return withConnection(context, (Callable<IRubyObject>) connection -> {
975
+ PreparedStatement statement = null;
976
+ final String query = sqlString(sql);
977
+ try {
978
+ statement = connection.prepareStatement(query);
979
+ setStatementParameters(context, connection, statement, (RubyArray) binds);
980
+ final int rowCount = statement.executeUpdate();
981
+ return context.runtime.newFixnum(rowCount);
982
+ } catch (final SQLException e) {
983
+ debugErrorSQL(context, query);
984
+ throw e;
985
+ } finally {
986
+ close(statement);
998
987
  }
999
988
  });
1000
989
  }
@@ -1041,50 +1030,48 @@ public class RubyJdbcConnection extends RubyObject {
1041
1030
 
1042
1031
  private IRubyObject doExecuteQueryRaw(final ThreadContext context,
1043
1032
  final String query, final int maxRows, final Block block, final RubyArray binds) {
1044
- return withConnection(context, new Callable<IRubyObject>() {
1045
- public IRubyObject call(final Connection connection) throws SQLException {
1046
- Statement statement = null; boolean hasResult;
1047
- try {
1048
- if ( binds == null || binds.isEmpty()) { // plain statement
1049
- statement = createStatement(context, connection);
1050
- statement.setMaxRows(maxRows); // zero means there is no limit
1051
- hasResult = statement.execute(query);
1052
- }
1053
- else {
1054
- final PreparedStatement prepStatement;
1055
- statement = prepStatement = connection.prepareStatement(query);
1056
- if (fetchSize != 0) statement.setFetchSize(fetchSize);
1057
- statement.setMaxRows(maxRows); // zero means there is no limit
1058
- setStatementParameters(context, connection, prepStatement, binds);
1059
- hasResult = prepStatement.execute();
1060
- }
1033
+ return withConnection(context, connection -> {
1034
+ Statement statement = null; boolean hasResult;
1035
+ try {
1036
+ if ( binds == null || binds.isEmpty()) { // plain statement
1037
+ statement = createStatement(context, connection);
1038
+ statement.setMaxRows(maxRows); // zero means there is no limit
1039
+ hasResult = statement.execute(query);
1040
+ }
1041
+ else {
1042
+ final PreparedStatement prepStatement;
1043
+ statement = prepStatement = connection.prepareStatement(query);
1044
+ if (fetchSize != 0) statement.setFetchSize(fetchSize);
1045
+ statement.setMaxRows(maxRows); // zero means there is no limit
1046
+ setStatementParameters(context, connection, prepStatement, binds);
1047
+ hasResult = prepStatement.execute();
1048
+ }
1061
1049
 
1062
- if (block.isGiven()) {
1063
- if (hasResult) {
1064
- // yield(id1, name1) ... row 1 result data
1065
- // yield(id2, name2) ... row 2 result data
1066
- return yieldResultRows(context, connection, statement.getResultSet(), block);
1067
- }
1068
- return context.nil;
1069
- }
1050
+ if (block.isGiven()) {
1070
1051
  if (hasResult) {
1071
- return mapToRawResult(context, connection, statement.getResultSet(), false);
1052
+ // yield(id1, name1) ... row 1 result data
1053
+ // yield(id2, name2) ... row 2 result data
1054
+ return yieldResultRows(context, connection, statement.getResultSet(), block);
1072
1055
  }
1073
- return context.runtime.newEmptyArray();
1074
- }
1075
- catch (final SQLException e) {
1076
- debugErrorSQL(context, query);
1077
- throw e;
1056
+ return context.nil;
1078
1057
  }
1079
- finally {
1080
- close(statement);
1058
+ if (hasResult) {
1059
+ return mapToRawResult(context, connection, statement.getResultSet(), false);
1081
1060
  }
1061
+ return context.runtime.newEmptyArray();
1062
+ }
1063
+ catch (final SQLException e) {
1064
+ debugErrorSQL(context, query);
1065
+ throw e;
1066
+ }
1067
+ finally {
1068
+ close(statement);
1082
1069
  }
1083
1070
  });
1084
1071
  }
1085
1072
 
1086
1073
  protected static String sqlString(final IRubyObject sql) {
1087
- return sql instanceof RubyString ? ((RubyString) sql).decodeString() : sql.convertToString().decodeString();
1074
+ return sql.convertToString().decodeString();
1088
1075
  }
1089
1076
 
1090
1077
  /**
@@ -1097,26 +1084,24 @@ public class RubyJdbcConnection extends RubyObject {
1097
1084
  */
1098
1085
  @JRubyMethod(required = 1)
1099
1086
  public IRubyObject execute_query(final ThreadContext context, final IRubyObject sql) {
1100
- return withConnection(context, new Callable<IRubyObject>() {
1101
- public IRubyObject call(final Connection connection) throws SQLException {
1102
- Statement statement = null;
1103
- final String query = sqlString(sql);
1104
- try {
1105
- statement = createStatement(context, connection);
1087
+ return withConnection(context, connection -> {
1088
+ Statement statement = null;
1089
+ final String query = sqlString(sql);
1090
+ try {
1091
+ statement = createStatement(context, connection);
1106
1092
 
1107
- // At least until AR 5.1 #exec_query still gets called for things that don't return results in some cases :(
1108
- if (statement.execute(query)) {
1109
- return mapQueryResult(context, connection, statement.getResultSet());
1110
- }
1093
+ // At least until AR 5.1 #exec_query still gets called for things that don't return results in some cases :(
1094
+ if (statement.execute(query)) {
1095
+ return mapQueryResult(context, connection, statement.getResultSet());
1096
+ }
1111
1097
 
1112
- return context.nil;
1098
+ return newEmptyResult(context);
1113
1099
 
1114
- } catch (final SQLException e) {
1115
- debugErrorSQL(context, query);
1116
- throw e;
1117
- } finally {
1118
- close(statement);
1119
- }
1100
+ } catch (final SQLException e) {
1101
+ debugErrorSQL(context, query);
1102
+ throw e;
1103
+ } finally {
1104
+ close(statement);
1120
1105
  }
1121
1106
  });
1122
1107
  }
@@ -1129,13 +1114,11 @@ public class RubyJdbcConnection extends RubyObject {
1129
1114
  */
1130
1115
  @JRubyMethod(required = 1)
1131
1116
  public IRubyObject prepare_statement(final ThreadContext context, final IRubyObject sql) {
1132
- return withConnection(context, new Callable<IRubyObject>() {
1133
- public IRubyObject call(Connection connection) throws SQLException {
1134
- final String query = sql.convertToString().getUnicodeValue();
1135
- PreparedStatement statement = connection.prepareStatement(query);
1136
- if (fetchSize != 0) statement.setFetchSize(fetchSize);
1137
- return JavaUtil.convertJavaToRuby(context.runtime, statement);
1138
- }
1117
+ return withConnection(context, connection -> {
1118
+ final String query = sql.convertToString().getUnicodeValue();
1119
+ PreparedStatement statement = connection.prepareStatement(query);
1120
+ if (fetchSize != 0) statement.setFetchSize(fetchSize);
1121
+ return JavaUtil.convertJavaToRuby(context.runtime, statement);
1139
1122
  });
1140
1123
  }
1141
1124
 
@@ -1158,40 +1141,40 @@ public class RubyJdbcConnection extends RubyObject {
1158
1141
  @JRubyMethod(required = 3)
1159
1142
  public IRubyObject execute_prepared_query(final ThreadContext context, final IRubyObject sql,
1160
1143
  final IRubyObject binds, final IRubyObject cachedStatement) {
1161
- return withConnection(context, new Callable<IRubyObject>() {
1162
- public IRubyObject call(final Connection connection) throws SQLException {
1163
- final boolean cached = !(cachedStatement == null || cachedStatement.isNil());
1164
- final String query = sql.convertToString().getUnicodeValue();
1165
- PreparedStatement statement = null;
1144
+ return withConnection(context, connection -> {
1145
+ final boolean cached = !(cachedStatement == null || cachedStatement.isNil());
1146
+ String query = null;
1147
+ PreparedStatement statement = null;
1166
1148
 
1167
- try {
1168
- if (cached) {
1169
- statement = (PreparedStatement) JavaEmbedUtils.rubyToJava(cachedStatement);
1170
- } else {
1171
- statement = connection.prepareStatement(query);
1172
- if (fetchSize != 0) statement.setFetchSize(fetchSize);
1173
- }
1149
+ try {
1150
+ if (cached) {
1151
+ statement = (PreparedStatement) JavaEmbedUtils.rubyToJava(cachedStatement);
1152
+ } else {
1153
+ query = sql.convertToString().getUnicodeValue();
1154
+ statement = connection.prepareStatement(query);
1155
+ if (fetchSize != 0) statement.setFetchSize(fetchSize);
1156
+ }
1174
1157
 
1175
- setStatementParameters(context, connection, statement, (RubyArray) binds);
1158
+ setStatementParameters(context, connection, statement, (RubyArray) binds);
1176
1159
 
1177
- if (statement.execute()) {
1178
- ResultSet resultSet = statement.getResultSet();
1179
- IRubyObject results = mapQueryResult(context, connection, resultSet);
1180
- resultSet.close();
1160
+ if (statement.execute()) {
1161
+ ResultSet resultSet = statement.getResultSet();
1162
+ IRubyObject results = mapQueryResult(context, connection, resultSet);
1163
+ resultSet.close();
1181
1164
 
1182
- return results;
1183
- } else {
1184
- return context.nil;
1185
- }
1186
- } catch (final SQLException e) {
1187
- debugErrorSQL(context, query);
1188
- throw e;
1189
- } finally {
1190
- if ( cached ) {
1191
- statement.clearParameters();
1192
- } else {
1193
- close(statement);
1194
- }
1165
+ return results;
1166
+ } else {
1167
+ return newEmptyResult(context);
1168
+ }
1169
+ } catch (final SQLException e) {
1170
+ if (query == null) query = sql.convertToString().getUnicodeValue();
1171
+ debugErrorSQL(context, query);
1172
+ throw e;
1173
+ } finally {
1174
+ if ( cached ) {
1175
+ statement.clearParameters();
1176
+ } else {
1177
+ close(statement);
1195
1178
  }
1196
1179
  }
1197
1180
  });
@@ -1203,35 +1186,6 @@ public class RubyJdbcConnection extends RubyObject {
1203
1186
  return mapToResult(context, connection, resultSet, columns);
1204
1187
  }
1205
1188
 
1206
- /**
1207
- * @deprecated please do not use this method
1208
- */
1209
- @Deprecated // only used by Oracle adapter - also it's really a bad idea
1210
- @JRubyMethod(name = "execute_id_insert", required = 2)
1211
- public IRubyObject execute_id_insert(final ThreadContext context, final IRubyObject sql, final IRubyObject id) {
1212
- final Ruby runtime = context.runtime;
1213
-
1214
- callMethod("warn", RubyString.newUnicodeString(runtime, "DEPRECATED: execute_id_insert(sql, id) will be removed"));
1215
-
1216
- return withConnection(context, new Callable<IRubyObject>() {
1217
- public IRubyObject call(final Connection connection) throws SQLException {
1218
- PreparedStatement statement = null;
1219
- final String insertSQL = sql.convertToString().getUnicodeValue();
1220
- try {
1221
- statement = connection.prepareStatement(insertSQL);
1222
- statement.setLong(1, RubyNumeric.fix2long(id));
1223
- statement.executeUpdate();
1224
- }
1225
- catch (final SQLException e) {
1226
- debugErrorSQL(context, insertSQL);
1227
- throw e;
1228
- }
1229
- finally { close(statement); }
1230
- return id;
1231
- }
1232
- });
1233
- }
1234
-
1235
1189
  @JRubyMethod(name = "supported_data_types")
1236
1190
  public IRubyObject supported_data_types(final ThreadContext context) throws SQLException {
1237
1191
  final Connection connection = getConnection(true);
@@ -1255,12 +1209,10 @@ public class RubyJdbcConnection extends RubyObject {
1255
1209
  protected static final int PRIMARY_KEYS_COLUMN_NAME = 4;
1256
1210
 
1257
1211
  private List<RubyString> primaryKeys(final ThreadContext context, final String tableName) {
1258
- return withConnection(context, new Callable<List<RubyString>>() {
1259
- public List<RubyString> call(final Connection connection) throws SQLException {
1260
- final String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
1261
- final TableName table = extractTableName(connection, null, null, _tableName);
1262
- return primaryKeys(context, connection, table);
1263
- }
1212
+ return withConnection(context, connection -> {
1213
+ final String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
1214
+ final TableName table = extractTableName(connection, null, null, _tableName);
1215
+ return primaryKeys(context, connection, table);
1264
1216
  });
1265
1217
  }
1266
1218
 
@@ -1268,7 +1220,7 @@ public class RubyJdbcConnection extends RubyObject {
1268
1220
  final Connection connection, final TableName table) throws SQLException {
1269
1221
  final DatabaseMetaData metaData = connection.getMetaData();
1270
1222
  ResultSet resultSet = null;
1271
- final List<RubyString> keyNames = new ArrayList<RubyString>();
1223
+ final List<RubyString> keyNames = new ArrayList<>();
1272
1224
  try {
1273
1225
  resultSet = metaData.getPrimaryKeys(table.catalog, table.schema, table.name);
1274
1226
  final Ruby runtime = context.runtime;
@@ -1282,26 +1234,6 @@ public class RubyJdbcConnection extends RubyObject {
1282
1234
  return keyNames;
1283
1235
  }
1284
1236
 
1285
- @Deprecated //@JRubyMethod(name = "tables")
1286
- public IRubyObject tables(ThreadContext context) {
1287
- return tables(context, null, null, null, TABLE_TYPE);
1288
- }
1289
-
1290
- @Deprecated //@JRubyMethod(name = "tables")
1291
- public IRubyObject tables(ThreadContext context, IRubyObject catalog) {
1292
- return tables(context, toStringOrNull(catalog), null, null, TABLE_TYPE);
1293
- }
1294
-
1295
- @Deprecated //@JRubyMethod(name = "tables")
1296
- public IRubyObject tables(ThreadContext context, IRubyObject catalog, IRubyObject schemaPattern) {
1297
- return tables(context, toStringOrNull(catalog), toStringOrNull(schemaPattern), null, TABLE_TYPE);
1298
- }
1299
-
1300
- @Deprecated //@JRubyMethod(name = "tables")
1301
- public IRubyObject tables(ThreadContext context, IRubyObject catalog, IRubyObject schemaPattern, IRubyObject tablePattern) {
1302
- return tables(context, toStringOrNull(catalog), toStringOrNull(schemaPattern), toStringOrNull(tablePattern), TABLE_TYPE);
1303
- }
1304
-
1305
1237
  @JRubyMethod(name = "tables", required = 0, optional = 4)
1306
1238
  public IRubyObject tables(final ThreadContext context, final IRubyObject[] args) {
1307
1239
  switch ( args.length ) {
@@ -1319,11 +1251,7 @@ public class RubyJdbcConnection extends RubyObject {
1319
1251
 
1320
1252
  protected IRubyObject tables(final ThreadContext context,
1321
1253
  final String catalog, final String schemaPattern, final String tablePattern, final String[] types) {
1322
- return withConnection(context, new Callable<IRubyObject>() {
1323
- public IRubyObject call(final Connection connection) throws SQLException {
1324
- return matchTables(context, connection, catalog, schemaPattern, tablePattern, types, false);
1325
- }
1326
- });
1254
+ return withConnection(context, connection -> matchTables(context, connection, catalog, schemaPattern, tablePattern, types, false));
1327
1255
  }
1328
1256
 
1329
1257
  protected String[] getTableTypes() {
@@ -1353,40 +1281,36 @@ public class RubyJdbcConnection extends RubyObject {
1353
1281
 
1354
1282
  protected IRubyObject tableExists(final ThreadContext context,
1355
1283
  final String defaultSchema, final String tableName) {
1356
- return withConnection(context, new Callable<RubyBoolean>() {
1357
- public RubyBoolean call(final Connection connection) throws SQLException {
1358
- final TableName components = extractTableName(connection, defaultSchema, tableName);
1359
- return context.runtime.newBoolean( tableExists(context, connection, components) );
1360
- }
1284
+ return withConnection(context, connection -> {
1285
+ final TableName components = extractTableName(connection, defaultSchema, tableName);
1286
+ return context.runtime.newBoolean( tableExists(context, connection, components) );
1361
1287
  });
1362
1288
  }
1363
1289
 
1364
1290
  @JRubyMethod(name = {"columns", "columns_internal"}, required = 1, optional = 2)
1365
1291
  public RubyArray columns_internal(final ThreadContext context, final IRubyObject[] args)
1366
1292
  throws SQLException {
1367
- return withConnection(context, new Callable<RubyArray>() {
1368
- public RubyArray call(final Connection connection) throws SQLException {
1369
- ResultSet columns = null;
1370
- try {
1371
- final String tableName = args[0].toString();
1372
- // optionals (NOTE: catalog argumnet was never used before 1.3.0) :
1373
- final String catalog = args.length > 1 ? toStringOrNull(args[1]) : null;
1374
- final String defaultSchema = args.length > 2 ? toStringOrNull(args[2]) : null;
1375
-
1376
- final TableName components;
1377
- components = extractTableName(connection, catalog, defaultSchema, tableName);
1293
+ return withConnection(context, connection -> {
1294
+ ResultSet columns = null;
1295
+ try {
1296
+ final String tableName = args[0].toString();
1297
+ // optionals (NOTE: catalog argumnet was never used before 1.3.0) :
1298
+ final String catalog = args.length > 1 ? toStringOrNull(args[1]) : null;
1299
+ final String defaultSchema = args.length > 2 ? toStringOrNull(args[2]) : null;
1378
1300
 
1379
- if ( ! tableExists(context, connection, components) ) {
1380
- throw new SQLException("table: " + tableName + " does not exist");
1381
- }
1301
+ final TableName components;
1302
+ components = extractTableName(connection, catalog, defaultSchema, tableName);
1382
1303
 
1383
- final DatabaseMetaData metaData = connection.getMetaData();
1384
- columns = metaData.getColumns(components.catalog, components.schema, components.name, null);
1385
- return mapColumnsResult(context, metaData, components, columns);
1386
- }
1387
- finally {
1388
- close(columns);
1304
+ if ( ! tableExists(context, connection, components) ) {
1305
+ throw new SQLException("table: " + tableName + " does not exist");
1389
1306
  }
1307
+
1308
+ final DatabaseMetaData metaData = connection.getMetaData();
1309
+ columns = metaData.getColumns(components.catalog, components.schema, components.name, null);
1310
+ return mapColumnsResult(context, metaData, components, columns);
1311
+ }
1312
+ finally {
1313
+ close(columns);
1390
1314
  }
1391
1315
  });
1392
1316
  }
@@ -1416,70 +1340,68 @@ public class RubyJdbcConnection extends RubyObject {
1416
1340
  * should filter the return from this method instead.
1417
1341
  */
1418
1342
  protected IRubyObject indexes(final ThreadContext context, final String tableName, final String name, final String schemaName) {
1419
- return withConnection(context, new Callable<IRubyObject>() {
1420
- public IRubyObject call(final Connection connection) throws SQLException {
1421
- final Ruby runtime = context.runtime;
1422
- final RubyClass IndexDefinition = getIndexDefinition(context);
1423
-
1424
- String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
1425
- String _schemaName = caseConvertIdentifierForJdbc(connection, schemaName);
1426
- final TableName table = extractTableName(connection, null, _schemaName, _tableName);
1343
+ return withConnection(context, (Callable<IRubyObject>) connection -> {
1344
+ final Ruby runtime = context.runtime;
1345
+ final RubyClass IndexDefinition = getIndexDefinition(context);
1427
1346
 
1428
- final List<RubyString> primaryKeys = primaryKeys(context, connection, table);
1347
+ String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
1348
+ String _schemaName = caseConvertIdentifierForJdbc(connection, schemaName);
1349
+ final TableName table = extractTableName(connection, null, _schemaName, _tableName);
1429
1350
 
1430
- ResultSet indexInfoSet = null;
1431
- final RubyArray indexes = RubyArray.newArray(runtime, 8);
1432
- try {
1433
- final DatabaseMetaData metaData = connection.getMetaData();
1434
- indexInfoSet = metaData.getIndexInfo(table.catalog, table.schema, table.name, false, true);
1435
- String currentIndex = null;
1436
- RubyArray currentColumns = null;
1351
+ final List<RubyString> primaryKeys = primaryKeys(context, connection, table);
1437
1352
 
1438
- while ( indexInfoSet.next() ) {
1439
- String indexName = indexInfoSet.getString(INDEX_INFO_NAME);
1440
- if ( indexName == null ) continue;
1353
+ ResultSet indexInfoSet = null;
1354
+ final RubyArray indexes = RubyArray.newArray(runtime, 8);
1355
+ try {
1356
+ final DatabaseMetaData metaData = connection.getMetaData();
1357
+ indexInfoSet = metaData.getIndexInfo(table.catalog, table.schema, table.name, false, true);
1358
+ String currentIndex = null;
1441
1359
 
1442
- indexName = caseConvertIdentifierForRails(metaData, indexName);
1360
+ while ( indexInfoSet.next() ) {
1361
+ String indexName = indexInfoSet.getString(INDEX_INFO_NAME);
1362
+ if ( indexName == null ) continue;
1363
+ RubyArray currentColumns = null;
1443
1364
 
1444
- final String columnName = indexInfoSet.getString(INDEX_INFO_COLUMN_NAME);
1445
- final RubyString rubyColumnName = cachedString(
1446
- context, caseConvertIdentifierForRails(metaData, columnName)
1447
- );
1448
- if ( primaryKeys.contains(rubyColumnName) ) continue;
1365
+ indexName = caseConvertIdentifierForRails(metaData, indexName);
1449
1366
 
1450
- // We are working on a new index
1451
- if ( ! indexName.equals(currentIndex) ) {
1452
- currentIndex = indexName;
1367
+ final String columnName = indexInfoSet.getString(INDEX_INFO_COLUMN_NAME);
1368
+ final RubyString rubyColumnName = cachedString(
1369
+ context, caseConvertIdentifierForRails(metaData, columnName)
1370
+ );
1371
+ if ( primaryKeys.contains(rubyColumnName) ) continue;
1453
1372
 
1454
- String indexTableName = indexInfoSet.getString(INDEX_INFO_TABLE_NAME);
1455
- indexTableName = caseConvertIdentifierForRails(metaData, indexTableName);
1373
+ // We are working on a new index
1374
+ if ( ! indexName.equals(currentIndex) ) {
1375
+ currentIndex = indexName;
1456
1376
 
1457
- final boolean nonUnique = indexInfoSet.getBoolean(INDEX_INFO_NON_UNIQUE);
1377
+ String indexTableName = indexInfoSet.getString(INDEX_INFO_TABLE_NAME);
1378
+ indexTableName = caseConvertIdentifierForRails(metaData, indexTableName);
1458
1379
 
1459
- IRubyObject[] args = new IRubyObject[] {
1460
- cachedString(context, indexTableName), // table_name
1461
- cachedString(context, indexName), // index_name
1462
- nonUnique ? runtime.getFalse() : runtime.getTrue(), // unique
1463
- currentColumns = RubyArray.newArray(runtime, 4) // [] column names
1464
- // orders, (since AR 3.2) where, type, using (AR 4.0)
1465
- };
1380
+ final boolean nonUnique = indexInfoSet.getBoolean(INDEX_INFO_NON_UNIQUE);
1466
1381
 
1467
- indexes.append( IndexDefinition.newInstance(context, args, Block.NULL_BLOCK) ); // IndexDefinition.new
1468
- }
1382
+ IRubyObject[] args = new IRubyObject[] {
1383
+ cachedString(context, indexTableName), // table_name
1384
+ cachedString(context, indexName), // index_name
1385
+ nonUnique ? context.fals : context.tru, // unique
1386
+ currentColumns = RubyArray.newArray(runtime, 4) // [] column names
1387
+ // orders, (since AR 3.2) where, type, using (AR 4.0)
1388
+ };
1469
1389
 
1470
- // one or more columns can be associated with an index
1471
- if ( currentColumns != null ) currentColumns.append(rubyColumnName);
1390
+ indexes.append( IndexDefinition.newInstance(context, args, Block.NULL_BLOCK) ); // IndexDefinition.new
1472
1391
  }
1473
1392
 
1474
- return indexes;
1393
+ // one or more columns can be associated with an index
1394
+ if ( currentColumns != null ) currentColumns.append(rubyColumnName);
1395
+ }
1475
1396
 
1476
- } finally { close(indexInfoSet); }
1477
- }
1397
+ return indexes;
1398
+
1399
+ } finally { close(indexInfoSet); }
1478
1400
  });
1479
1401
  }
1480
1402
 
1481
1403
  protected RubyClass getIndexDefinition(final ThreadContext context) {
1482
- final RubyClass adapterClass = getAdapter().getMetaClass();
1404
+ final RubyClass adapterClass = adapter.getMetaClass();
1483
1405
  IRubyObject IDef = adapterClass.getConstantAt("IndexDefinition");
1484
1406
  return IDef != null ? (RubyClass) IDef : getIndexDefinition(context.runtime);
1485
1407
  }
@@ -1490,57 +1412,55 @@ public class RubyJdbcConnection extends RubyObject {
1490
1412
  }
1491
1413
 
1492
1414
  protected IRubyObject foreignKeys(final ThreadContext context, final String tableName, final String schemaName, final String catalog) {
1493
- return withConnection(context, new Callable<IRubyObject>() {
1494
- public IRubyObject call(final Connection connection) throws SQLException {
1495
- final Ruby runtime = context.runtime;
1496
- final RubyClass FKDefinition = getForeignKeyDefinition(context);
1415
+ return withConnection(context, (Callable<IRubyObject>) connection -> {
1416
+ final Ruby runtime = context.runtime;
1417
+ final RubyClass FKDefinition = getForeignKeyDefinition(context);
1497
1418
 
1498
- String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
1499
- String _schemaName = caseConvertIdentifierForJdbc(connection, schemaName);
1500
- final TableName table = extractTableName(connection, catalog, _schemaName, _tableName);
1419
+ String _tableName = caseConvertIdentifierForJdbc(connection, tableName);
1420
+ String _schemaName = caseConvertIdentifierForJdbc(connection, schemaName);
1421
+ final TableName table = extractTableName(connection, catalog, _schemaName, _tableName);
1501
1422
 
1502
- ResultSet fkInfoSet = null;
1503
- final List<IRubyObject> fKeys = new ArrayList<IRubyObject>(8);
1504
- try {
1505
- final DatabaseMetaData metaData = connection.getMetaData();
1506
- fkInfoSet = metaData.getImportedKeys(table.catalog, table.schema, table.name);
1423
+ ResultSet fkInfoSet = null;
1424
+ final List<IRubyObject> fKeys = new ArrayList<>(8);
1425
+ try {
1426
+ final DatabaseMetaData metaData = connection.getMetaData();
1427
+ fkInfoSet = metaData.getImportedKeys(table.catalog, table.schema, table.name);
1507
1428
 
1508
- while ( fkInfoSet.next() ) {
1509
- final RubyHash options = RubyHash.newHash(runtime);
1429
+ while ( fkInfoSet.next() ) {
1430
+ final RubyHash options = RubyHash.newHash(runtime);
1510
1431
 
1511
- String fkName = fkInfoSet.getString("FK_NAME");
1512
- if (fkName != null) {
1513
- fkName = caseConvertIdentifierForRails(metaData, fkName);
1514
- options.put(runtime.newSymbol("name"), fkName);
1515
- }
1432
+ String fkName = fkInfoSet.getString("FK_NAME");
1433
+ if (fkName != null) {
1434
+ fkName = caseConvertIdentifierForRails(metaData, fkName);
1435
+ options.put(runtime.newSymbol("name"), fkName);
1436
+ }
1516
1437
 
1517
- String columnName = fkInfoSet.getString("FKCOLUMN_NAME");
1518
- options.put(runtime.newSymbol("column"), caseConvertIdentifierForRails(metaData, columnName));
1438
+ String columnName = fkInfoSet.getString("FKCOLUMN_NAME");
1439
+ options.put(runtime.newSymbol("column"), caseConvertIdentifierForRails(metaData, columnName));
1519
1440
 
1520
- columnName = fkInfoSet.getString("PKCOLUMN_NAME");
1521
- options.put(runtime.newSymbol("primary_key"), caseConvertIdentifierForRails(metaData, columnName));
1441
+ columnName = fkInfoSet.getString("PKCOLUMN_NAME");
1442
+ options.put(runtime.newSymbol("primary_key"), caseConvertIdentifierForRails(metaData, columnName));
1522
1443
 
1523
- String fkTableName = fkInfoSet.getString("FKTABLE_NAME");
1524
- fkTableName = caseConvertIdentifierForRails(metaData, fkTableName);
1444
+ String fkTableName = fkInfoSet.getString("FKTABLE_NAME");
1445
+ fkTableName = caseConvertIdentifierForRails(metaData, fkTableName);
1525
1446
 
1526
- String pkTableName = fkInfoSet.getString("PKTABLE_NAME");
1527
- pkTableName = caseConvertIdentifierForRails(metaData, pkTableName);
1447
+ String pkTableName = fkInfoSet.getString("PKTABLE_NAME");
1448
+ pkTableName = caseConvertIdentifierForRails(metaData, pkTableName);
1528
1449
 
1529
- final String onDelete = extractForeignKeyRule( fkInfoSet.getInt("DELETE_RULE") );
1530
- if ( onDelete != null ) options.op_aset(context, runtime.newSymbol("on_delete"), runtime.newSymbol(onDelete));
1450
+ final String onDelete = extractForeignKeyRule( fkInfoSet.getInt("DELETE_RULE") );
1451
+ if ( onDelete != null ) options.op_aset(context, runtime.newSymbol("on_delete"), runtime.newSymbol(onDelete));
1531
1452
 
1532
- final String onUpdate = extractForeignKeyRule( fkInfoSet.getInt("UPDATE_RULE") );
1533
- if ( onUpdate != null ) options.op_aset(context, runtime.newSymbol("on_update"), runtime.newSymbol(onUpdate));
1453
+ final String onUpdate = extractForeignKeyRule( fkInfoSet.getInt("UPDATE_RULE") );
1454
+ if ( onUpdate != null ) options.op_aset(context, runtime.newSymbol("on_update"), runtime.newSymbol(onUpdate));
1534
1455
 
1535
- IRubyObject from_table = cachedString(context, fkTableName);
1536
- IRubyObject to_table = cachedString(context, pkTableName);
1537
- fKeys.add( FKDefinition.newInstance(context, from_table, to_table, options, Block.NULL_BLOCK) ); // ForeignKeyDefinition.new
1538
- }
1456
+ IRubyObject from_table = cachedString(context, fkTableName);
1457
+ IRubyObject to_table = cachedString(context, pkTableName);
1458
+ fKeys.add( FKDefinition.newInstance(context, from_table, to_table, options, Block.NULL_BLOCK) ); // ForeignKeyDefinition.new
1459
+ }
1539
1460
 
1540
- return runtime.newArray(fKeys);
1461
+ return runtime.newArray(fKeys);
1541
1462
 
1542
- } finally { close(fkInfoSet); }
1543
- }
1463
+ } finally { close(fkInfoSet); }
1544
1464
  });
1545
1465
  }
1546
1466
 
@@ -1555,7 +1475,7 @@ public class RubyJdbcConnection extends RubyObject {
1555
1475
  }
1556
1476
 
1557
1477
  protected RubyClass getForeignKeyDefinition(final ThreadContext context) {
1558
- final RubyClass adapterClass = getAdapter().getMetaClass();
1478
+ final RubyClass adapterClass = adapter.getMetaClass();
1559
1479
  IRubyObject FKDef = adapterClass.getConstantAt("ForeignKeyDefinition");
1560
1480
  return FKDef != null ? (RubyClass) FKDef : getForeignKeyDefinition(context.runtime);
1561
1481
  }
@@ -1563,42 +1483,34 @@ public class RubyJdbcConnection extends RubyObject {
1563
1483
 
1564
1484
  @JRubyMethod(name = "supports_foreign_keys?")
1565
1485
  public IRubyObject supports_foreign_keys_p(final ThreadContext context) throws SQLException {
1566
- return withConnection(context, new Callable<IRubyObject>() {
1567
- public IRubyObject call(final Connection connection) throws SQLException {
1568
- final DatabaseMetaData metaData = connection.getMetaData();
1569
- return context.runtime.newBoolean( metaData.supportsIntegrityEnhancementFacility() );
1570
- }
1486
+ return withConnection(context, (Callable<IRubyObject>) connection -> {
1487
+ final DatabaseMetaData metaData = connection.getMetaData();
1488
+ return context.runtime.newBoolean( metaData.supportsIntegrityEnhancementFacility() );
1571
1489
  });
1572
1490
  }
1573
1491
 
1574
1492
  @JRubyMethod(name = "supports_views?")
1575
1493
  public IRubyObject supports_views_p(final ThreadContext context) throws SQLException {
1576
- return withConnection(context, new Callable<IRubyObject>() {
1577
- public IRubyObject call(final Connection connection) throws SQLException {
1578
- final DatabaseMetaData metaData = connection.getMetaData();
1579
- final ResultSet tableTypes = metaData.getTableTypes();
1580
- try {
1581
- while ( tableTypes.next() ) {
1582
- if ( "VIEW".equalsIgnoreCase( tableTypes.getString(1) ) ) {
1583
- return context.runtime.newBoolean( true );
1584
- }
1494
+ return withConnection(context, (Callable<IRubyObject>) connection -> {
1495
+ final DatabaseMetaData metaData = connection.getMetaData();
1496
+ final ResultSet tableTypes = metaData.getTableTypes();
1497
+ try {
1498
+ while ( tableTypes.next() ) {
1499
+ if ( "VIEW".equalsIgnoreCase( tableTypes.getString(1) ) ) {
1500
+ return context.runtime.newBoolean( true );
1585
1501
  }
1586
1502
  }
1587
- finally {
1588
- close(tableTypes);
1589
- }
1590
- return context.runtime.newBoolean( false );
1591
1503
  }
1504
+ finally {
1505
+ close(tableTypes);
1506
+ }
1507
+ return context.runtime.newBoolean( false );
1592
1508
  });
1593
1509
  }
1594
1510
 
1595
1511
  @JRubyMethod(name = "with_jdbc_connection", alias = "with_connection_retry_guard", frame = true)
1596
1512
  public IRubyObject with_jdbc_connection(final ThreadContext context, final Block block) {
1597
- return withConnection(context, new Callable<IRubyObject>() {
1598
- public IRubyObject call(final Connection connection) throws SQLException {
1599
- return block.call(context, convertJavaToRuby(connection));
1600
- }
1601
- });
1513
+ return withConnection(context, connection -> block.call(context, convertJavaToRuby(connection)));
1602
1514
  }
1603
1515
 
1604
1516
  /*
@@ -1659,24 +1571,22 @@ public class RubyJdbcConnection extends RubyObject {
1659
1571
  // TODO: Fix this, the columns don't have the info needed to handle this anymore
1660
1572
  // currently commented out so that it will compile
1661
1573
 
1662
- return withConnection(context, new Callable<Integer>() {
1663
- public Integer call(final Connection connection) throws SQLException {
1664
- PreparedStatement statement = null;
1665
- try {
1666
- statement = connection.prepareStatement(sql);
1667
- /*
1668
- if ( binary ) { // blob
1669
- setBlobParameter(context, connection, statement, 1, value, column, Types.BLOB);
1670
- }
1671
- else { // clob
1672
- setClobParameter(context, connection, statement, 1, value, column, Types.CLOB);
1673
- }
1674
- setStatementParameter(context, context.runtime, connection, statement, 2, idValue, idColumn);
1675
- */
1676
- return statement.executeUpdate();
1574
+ return withConnection(context, connection -> {
1575
+ PreparedStatement statement = null;
1576
+ try {
1577
+ statement = connection.prepareStatement(sql);
1578
+ /*
1579
+ if ( binary ) { // blob
1580
+ setBlobParameter(context, connection, statement, 1, value, column, Types.BLOB);
1677
1581
  }
1678
- finally { close(statement); }
1582
+ else { // clob
1583
+ setClobParameter(context, connection, statement, 1, value, column, Types.CLOB);
1584
+ }
1585
+ setStatementParameter(context, context.runtime, connection, statement, 2, idValue, idColumn);
1586
+ */
1587
+ return statement.executeUpdate();
1679
1588
  }
1589
+ finally { close(statement); }
1680
1590
  });
1681
1591
  }
1682
1592
 
@@ -1732,7 +1642,7 @@ public class RubyJdbcConnection extends RubyObject {
1732
1642
  final IRubyObject self, final IRubyObject config, final Block block) {
1733
1643
  final IRubyObject ds_or_name = rawDataSourceOrName(context, config);
1734
1644
 
1735
- if ( ds_or_name == null ) return context.runtime.getFalse();
1645
+ if ( ds_or_name == null ) return context.fals;
1736
1646
 
1737
1647
  final javax.sql.DataSource dataSource;
1738
1648
  final Object dsOrName = ds_or_name.toJava(Object.class);
@@ -1788,7 +1698,7 @@ public class RubyJdbcConnection extends RubyObject {
1788
1698
  }
1789
1699
  }
1790
1700
 
1791
- if ( configValue == null || configValue == context.nil || configValue == runtime.getFalse() ) {
1701
+ if ( configValue == null || configValue == context.nil || configValue == context.fals ) {
1792
1702
  return null;
1793
1703
  }
1794
1704
  return configValue;
@@ -1811,13 +1721,6 @@ public class RubyJdbcConnection extends RubyObject {
1811
1721
  }
1812
1722
  }
1813
1723
 
1814
- @Deprecated
1815
- @JRubyMethod(name = "setup_jdbc_factory", visibility = Visibility.PROTECTED)
1816
- public IRubyObject set_driver_factory(final ThreadContext context) {
1817
- setDriverFactory(context);
1818
- return get_connection_factory(context.runtime);
1819
- }
1820
-
1821
1724
  private ConnectionFactory setDriverFactory(final ThreadContext context) {
1822
1725
 
1823
1726
  final IRubyObject url = getConfigValue(context, "url");
@@ -1917,12 +1820,6 @@ public class RubyJdbcConnection extends RubyObject {
1917
1820
  return props;
1918
1821
  }
1919
1822
 
1920
- @JRubyMethod(name = "setup_jndi_factory", visibility = Visibility.PROTECTED)
1921
- public IRubyObject set_data_source_factory(final ThreadContext context) {
1922
- setDataSourceFactory(context);
1923
- return get_connection_factory(context.runtime);
1924
- }
1925
-
1926
1823
  private ConnectionFactory setDataSourceFactory(final ThreadContext context) {
1927
1824
  final javax.sql.DataSource dataSource; final String lookupName;
1928
1825
  IRubyObject value = getConfigValue(context, "data_source");
@@ -1944,28 +1841,10 @@ public class RubyJdbcConnection extends RubyObject {
1944
1841
  private static volatile boolean defaultConfigJndi;
1945
1842
  private static transient ConnectionFactory defaultConnectionFactory;
1946
1843
 
1947
- /**
1948
- * Sets the connection factory from the available configuration.
1949
- * @param context
1950
- * @see #initialize
1951
- */
1952
- @Deprecated
1953
- @JRubyMethod(name = "setup_connection_factory", visibility = Visibility.PROTECTED)
1954
- public IRubyObject setup_connection_factory(final ThreadContext context) {
1955
- setupConnectionFactory(context);
1956
- return get_connection_factory(context.runtime);
1957
- }
1958
-
1959
- private IRubyObject get_connection_factory(final Ruby runtime) {
1960
- return JavaUtil.convertJavaToRuby(runtime, connectionFactory);
1961
- }
1962
-
1963
1844
  /**
1964
1845
  * @return whether the connection factory is JNDI based
1965
1846
  */
1966
1847
  private boolean setupConnectionFactory(final ThreadContext context) {
1967
- final IRubyObject config = getConfig();
1968
-
1969
1848
  if ( defaultConfig == null ) {
1970
1849
  synchronized(RubyJdbcConnection.class) {
1971
1850
  if ( defaultConfig == null ) {
@@ -1997,18 +1876,17 @@ public class RubyJdbcConnection extends RubyObject {
1997
1876
 
1998
1877
  @JRubyMethod(name = "jndi?", alias = "jndi_connection?")
1999
1878
  public RubyBoolean jndi_p(final ThreadContext context) {
2000
- return context.runtime.newBoolean( isJndi() );
1879
+ return context.runtime.newBoolean(jndi);
2001
1880
  }
2002
1881
 
2003
1882
  protected boolean isJndi() { return this.jndi; }
2004
1883
 
2005
1884
  @JRubyMethod(name = "config")
2006
- public IRubyObject config() { return getConfig(); }
1885
+ public IRubyObject config() { return config; }
2007
1886
 
2008
1887
  public IRubyObject getConfig() { return this.config; }
2009
1888
 
2010
1889
  protected final IRubyObject getConfigValue(final ThreadContext context, final String key) {
2011
- final IRubyObject config = getConfig();
2012
1890
  final RubySymbol keySym = context.runtime.newSymbol(key);
2013
1891
  if ( config instanceof RubyHash ) {
2014
1892
  final IRubyObject value = ((RubyHash) config).fastARef(keySym);
@@ -2019,7 +1897,6 @@ public class RubyJdbcConnection extends RubyObject {
2019
1897
 
2020
1898
  protected final IRubyObject setConfigValue(final ThreadContext context,
2021
1899
  final String key, final IRubyObject value) {
2022
- final IRubyObject config = getConfig();
2023
1900
  final RubySymbol keySym = context.runtime.newSymbol(key);
2024
1901
  if ( config instanceof RubyHash ) {
2025
1902
  return ((RubyHash) config).op_aset(context, keySym, value);
@@ -2029,7 +1906,6 @@ public class RubyJdbcConnection extends RubyObject {
2029
1906
 
2030
1907
  protected final IRubyObject setConfigValueIfNotSet(final ThreadContext context,
2031
1908
  final String key, final IRubyObject value) {
2032
- final IRubyObject config = getConfig();
2033
1909
  final RubySymbol keySym = context.runtime.newSymbol(key);
2034
1910
  if ( config instanceof RubyHash ) {
2035
1911
  final IRubyObject setValue = ((RubyHash) config).fastARef(keySym);
@@ -2049,7 +1925,7 @@ public class RubyJdbcConnection extends RubyObject {
2049
1925
  protected final IRubyObject getAdapter() { return this.adapter; }
2050
1926
 
2051
1927
  protected RubyClass getJdbcColumnClass(final ThreadContext context) {
2052
- return (RubyClass) getAdapter().callMethod(context, "jdbc_column_class");
1928
+ return (RubyClass) adapter.callMethod(context, "jdbc_column_class");
2053
1929
  }
2054
1930
 
2055
1931
  protected ConnectionFactory getConnectionFactory() throws RaiseException {
@@ -2261,7 +2137,7 @@ public class RubyJdbcConnection extends RubyObject {
2261
2137
  @JRubyMethod(name = "raw_date_time?", meta = true)
2262
2138
  public static IRubyObject useRawDateTime(final ThreadContext context, final IRubyObject self) {
2263
2139
  if ( rawDateTime == null ) return context.nil;
2264
- return context.runtime.newBoolean( rawDateTime.booleanValue() );
2140
+ return context.runtime.newBoolean(rawDateTime);
2265
2141
  }
2266
2142
 
2267
2143
  @JRubyMethod(name = "raw_date_time=", meta = true)
@@ -2275,17 +2151,6 @@ public class RubyJdbcConnection extends RubyObject {
2275
2151
  return value;
2276
2152
  }
2277
2153
 
2278
- /**
2279
- * @return AR::Type-casted value
2280
- * @since 1.3.18
2281
- */
2282
- @Deprecated
2283
- protected static IRubyObject typeCastFromDatabase(final ThreadContext context,
2284
- final IRubyObject adapter, final RubySymbol typeName, final RubyString value) {
2285
- final IRubyObject type = adapter.callMethod(context, "lookup_cast_type", typeName);
2286
- return type.callMethod(context, "deserialize", value);
2287
- }
2288
-
2289
2154
  protected IRubyObject dateToRuby(final ThreadContext context,
2290
2155
  final Ruby runtime, final ResultSet resultSet, final int column)
2291
2156
  throws SQLException {
@@ -2296,11 +2161,11 @@ public class RubyJdbcConnection extends RubyObject {
2296
2161
  return resultSet.wasNull() ? context.nil : RubyString.newEmptyString(runtime);
2297
2162
  }
2298
2163
 
2299
- if ( rawDateTime != null && rawDateTime.booleanValue() ) {
2164
+ if ( rawDateTime != null && rawDateTime) {
2300
2165
  return RubyString.newString(runtime, DateTimeUtils.dateToString(value));
2301
2166
  }
2302
2167
 
2303
- return DateTimeUtils.newDateAsTime(context, value, null).callMethod(context, "to_date");
2168
+ return DateTimeUtils.newDateAsTime(context, value, DateTimeZone.UTC).callMethod(context, "to_date");
2304
2169
  }
2305
2170
 
2306
2171
  protected IRubyObject timeToRuby(final ThreadContext context,
@@ -2312,7 +2177,7 @@ public class RubyJdbcConnection extends RubyObject {
2312
2177
  return resultSet.wasNull() ? context.nil : RubyString.newEmptyString(runtime);
2313
2178
  }
2314
2179
 
2315
- if ( rawDateTime != null && rawDateTime.booleanValue() ) {
2180
+ if ( rawDateTime != null && rawDateTime) {
2316
2181
  return RubyString.newString(runtime, DateTimeUtils.timeToString(value));
2317
2182
  }
2318
2183
 
@@ -2328,7 +2193,7 @@ public class RubyJdbcConnection extends RubyObject {
2328
2193
  return resultSet.wasNull() ? context.nil : RubyString.newEmptyString(runtime);
2329
2194
  }
2330
2195
 
2331
- if ( rawDateTime != null && rawDateTime.booleanValue() ) {
2196
+ if ( rawDateTime != null && rawDateTime) {
2332
2197
  return RubyString.newString(runtime, DateTimeUtils.timestampToString(value));
2333
2198
  }
2334
2199
 
@@ -2340,19 +2205,6 @@ public class RubyJdbcConnection extends RubyObject {
2340
2205
  return DateTimeUtils.newTime(context, value, getDefaultTimeZone(context));
2341
2206
  }
2342
2207
 
2343
- @Deprecated
2344
- protected static RubyString timestampToRubyString(final Ruby runtime, String value) {
2345
- // Timestamp's format: yyyy-mm-dd hh:mm:ss.fffffffff
2346
- String suffix; // assumes java.sql.Timestamp internals :
2347
- if ( value.endsWith( suffix = " 00:00:00.0" ) ) {
2348
- value = value.substring( 0, value.length() - suffix.length() );
2349
- }
2350
- else if ( value.endsWith( suffix = ".0" ) ) {
2351
- value = value.substring( 0, value.length() - suffix.length() );
2352
- }
2353
- return RubyString.newUnicodeString(runtime, value);
2354
- }
2355
-
2356
2208
  protected static Boolean rawBoolean;
2357
2209
  static {
2358
2210
  final String booleanRaw = SafePropertyAccessor.getProperty("arjdbc.boolean.raw");
@@ -2364,7 +2216,7 @@ public class RubyJdbcConnection extends RubyObject {
2364
2216
  @JRubyMethod(name = "raw_boolean?", meta = true)
2365
2217
  public static IRubyObject useRawBoolean(final ThreadContext context, final IRubyObject self) {
2366
2218
  if ( rawBoolean == null ) return context.nil;
2367
- return context.runtime.newBoolean( rawBoolean.booleanValue() );
2219
+ return context.runtime.newBoolean(rawBoolean);
2368
2220
  }
2369
2221
 
2370
2222
  @JRubyMethod(name = "raw_boolean=", meta = true)
@@ -2396,13 +2248,13 @@ public class RubyJdbcConnection extends RubyObject {
2396
2248
  protected IRubyObject booleanToRuby(final ThreadContext context,
2397
2249
  final Ruby runtime, final ResultSet resultSet, final int column)
2398
2250
  throws SQLException {
2399
- if ( rawBoolean != null && rawBoolean.booleanValue() ) {
2251
+ if ( rawBoolean != null && rawBoolean) {
2400
2252
  final String value = resultSet.getString(column);
2401
2253
  if ( value == null /* && resultSet.wasNull() */ ) return context.nil;
2402
2254
  return RubyString.newUnicodeString(runtime, value);
2403
2255
  }
2404
2256
  final boolean value = resultSet.getBoolean(column);
2405
- if ( value == false && resultSet.wasNull() ) return context.nil;
2257
+ if (!value && resultSet.wasNull()) return context.nil;
2406
2258
  return runtime.newBoolean(value);
2407
2259
  }
2408
2260
 
@@ -2620,7 +2472,7 @@ public class RubyJdbcConnection extends RubyObject {
2620
2472
  }
2621
2473
  }
2622
2474
 
2623
- protected static final Map<String, Integer> JDBC_TYPE_FOR = new HashMap<String, Integer>(32, 1);
2475
+ protected static final Map<String, Integer> JDBC_TYPE_FOR = new HashMap<>(32, 1);
2624
2476
  static {
2625
2477
  JDBC_TYPE_FOR.put("string", Types.VARCHAR);
2626
2478
  JDBC_TYPE_FOR.put("text", Types.CLOB);
@@ -2662,7 +2514,7 @@ public class RubyJdbcConnection extends RubyObject {
2662
2514
  final String internedType = internedTypeFor(context, attribute);
2663
2515
  final Integer sqlType = jdbcTypeFor(internedType);
2664
2516
  if ( sqlType != null ) {
2665
- return sqlType.intValue();
2517
+ return sqlType;
2666
2518
  }
2667
2519
 
2668
2520
  return Types.OTHER; // -1 as well as 0 are used in Types
@@ -2849,11 +2701,6 @@ public class RubyJdbcConnection extends RubyObject {
2849
2701
  statement.setTimestamp(index, timestamp, getCalendar(dateTime.getZone()));
2850
2702
  }
2851
2703
 
2852
- @Deprecated
2853
- protected static Timestamp convertToTimestamp(final RubyFloat value) {
2854
- return DateTimeUtils.convertToTimestamp(value);
2855
- }
2856
-
2857
2704
  protected static Calendar getCalendar(final DateTimeZone zone) { // final java.util.Date hint
2858
2705
  if (DateTimeZone.UTC == zone) return getCalendarUTC();
2859
2706
  if (DateTimeZone.getDefault() == zone) return new GregorianCalendar();
@@ -2899,9 +2746,14 @@ public class RubyJdbcConnection extends RubyObject {
2899
2746
  value = value.callMethod(context, "to_date");
2900
2747
  }
2901
2748
 
2902
- // NOTE: Here we rely in ActiveRecord (ActiveSupport) to get
2903
- // the date as a string in the database format.
2904
- statement.setDate(index, Date.valueOf(value.callMethod(context, "to_s", context.runtime.newSymbol("db")).toString()));
2749
+ if (value instanceof RubyDate) {
2750
+ RubyDate rubyDate = (RubyDate) value;
2751
+ statement.setDate(index, rubyDate.toJava(Date.class));
2752
+ return;
2753
+ }
2754
+
2755
+ // NOTE: assuming Date#to_s does right ...
2756
+ statement.setDate(index, Date.valueOf(value.toString()));
2905
2757
  }
2906
2758
 
2907
2759
  protected void setBooleanParameter(final ThreadContext context,
@@ -2938,7 +2790,7 @@ public class RubyJdbcConnection extends RubyObject {
2938
2790
  // For some reason the driver doesn't like "character varying" as a type
2939
2791
  if ( type.eql(context.runtime.newSymbol("string")) ) return "varchar";
2940
2792
 
2941
- final RubyHash nativeTypes = (RubyHash) getAdapter().callMethod(context, "native_database_types");
2793
+ final RubyHash nativeTypes = (RubyHash) adapter.callMethod(context, "native_database_types");
2942
2794
  // e.g. `integer: { name: 'integer' }`
2943
2795
  final RubyHash typeInfo = (RubyHash) nativeTypes.op_aref(context, type);
2944
2796
 
@@ -2999,16 +2851,7 @@ public class RubyJdbcConnection extends RubyObject {
2999
2851
  }
3000
2852
 
3001
2853
  /**
3002
- * Always returns a connection (might cause a reconnect if there's none).
3003
- * @return connection
3004
- * @throws <code>ActiveRecord::ConnectionNotEstablished</code>, <code>ActiveRecord::JDBCError</code>
3005
- */
3006
- protected Connection getConnection() throws RaiseException {
3007
- return getConnection(false);
3008
- }
3009
-
3010
- /**
3011
- * @see #getConnection()
2854
+ * Returns a connection (might cause a reconnect if there's none).
3012
2855
  * @param required set to true if a connection is required to exists (e.g. on commit)
3013
2856
  * @return connection
3014
2857
  * @throws <code>ActiveRecord::ConnectionNotEstablished</code> if disconnected
@@ -3023,17 +2866,15 @@ public class RubyJdbcConnection extends RubyObject {
3023
2866
  }
3024
2867
  }
3025
2868
 
3026
- private Connection getConnectionInternal(final boolean required) throws SQLException {
2869
+ protected Connection getConnectionInternal(final boolean required) throws SQLException {
3027
2870
  Connection connection = getConnectionImpl();
3028
- if ( connection == null ) {
3029
- if ( required ) {
3030
- if ( ! connected ) handleNotConnected(); // raise ConnectionNotEstablished
3031
- synchronized (this) {
2871
+ if (connection == null && required) {
2872
+ if (!connected) handleNotConnected(); // raise ConnectionNotEstablished
2873
+ synchronized (this) {
2874
+ connection = getConnectionImpl();
2875
+ if ( connection == null ) {
2876
+ connectImpl(true); // throws SQLException
3032
2877
  connection = getConnectionImpl();
3033
- if ( connection == null ) {
3034
- connectImpl( true ); // throws SQLException
3035
- connection = getConnectionImpl();
3036
- }
3037
2878
  }
3038
2879
  }
3039
2880
  }
@@ -3164,7 +3005,7 @@ public class RubyJdbcConnection extends RubyObject {
3164
3005
  try {
3165
3006
  tablesSet = metaData.getTables(catalog, _schemaPattern, _tablePattern, types);
3166
3007
  if ( checkExistsOnly ) { // only check if given table exists
3167
- return tablesSet.next() ? context.runtime.getTrue() : null;
3008
+ return tablesSet.next() ? context.tru : null;
3168
3009
  }
3169
3010
  else {
3170
3011
  return mapTables(context, connection, catalog, _schemaPattern, _tablePattern, tablesSet);
@@ -3173,15 +3014,6 @@ public class RubyJdbcConnection extends RubyObject {
3173
3014
  finally { close(tablesSet); }
3174
3015
  }
3175
3016
 
3176
- @Deprecated
3177
- protected IRubyObject matchTables(final Ruby runtime,
3178
- final Connection connection,
3179
- final String catalog, final String schemaPattern,
3180
- final String tablePattern, final String[] types,
3181
- final boolean checkExistsOnly) throws SQLException {
3182
- return matchTables(runtime.getCurrentContext(), connection, catalog, schemaPattern, tablePattern, types, checkExistsOnly);
3183
- }
3184
-
3185
3017
  // NOTE java.sql.DatabaseMetaData.getTables :
3186
3018
  protected final static int TABLES_TABLE_CAT = 1;
3187
3019
  protected final static int TABLES_TABLE_SCHEM = 2;
@@ -3270,7 +3102,7 @@ public class RubyJdbcConnection extends RubyObject {
3270
3102
  final String tabName = results.getString(TABLE_NAME);
3271
3103
  final RubyString tableName = cachedString(context, caseConvertIdentifierForRails(metaData, tabName));
3272
3104
 
3273
- final IRubyObject type_metadata = getAdapter().callMethod(context, "fetch_type_metadata", sqlType);
3105
+ final IRubyObject type_metadata = adapter.callMethod(context, "fetch_type_metadata", sqlType);
3274
3106
 
3275
3107
  // (name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment: nil)
3276
3108
  final IRubyObject[] args = new IRubyObject[] {
@@ -3286,7 +3118,7 @@ public class RubyJdbcConnection extends RubyObject {
3286
3118
  ResultSet primaryKeys = null;
3287
3119
  try {
3288
3120
  primaryKeys = metaData.getPrimaryKeys(components.catalog, components.schema, components.name);
3289
- final List<String> primaryKeyNames = new ArrayList<String>(4);
3121
+ final List<String> primaryKeyNames = new ArrayList<>(4);
3290
3122
  while ( primaryKeys.next() ) {
3291
3123
  primaryKeyNames.add( primaryKeys.getString(COLUMN_NAME) );
3292
3124
  }
@@ -3335,7 +3167,7 @@ public class RubyJdbcConnection extends RubyObject {
3335
3167
  // not have and auto-generated ID column :
3336
3168
  boolean next = genKeys.next() && genKeys.getMetaData().getColumnCount() > 0;
3337
3169
  // singleResult == null - guess if only single key returned
3338
- if ( singleResult == null || singleResult.booleanValue() ) {
3170
+ if ( singleResult == null || singleResult) {
3339
3171
  if ( next ) {
3340
3172
  firstKey = mapGeneratedKey(runtime, genKeys);
3341
3173
  if ( singleResult != null || ! genKeys.next() ) {
@@ -3368,7 +3200,7 @@ public class RubyJdbcConnection extends RubyObject {
3368
3200
  if (supportsGeneratedKeys == null) {
3369
3201
  supportsGeneratedKeys = this.supportsGeneratedKeys = connection.getMetaData().supportsGetGeneratedKeys();
3370
3202
  }
3371
- return supportsGeneratedKeys.booleanValue();
3203
+ return supportsGeneratedKeys;
3372
3204
  }
3373
3205
 
3374
3206
  /**
@@ -3400,8 +3232,8 @@ public class RubyJdbcConnection extends RubyObject {
3400
3232
  final ColumnData[] columns = extractColumns(context, connection, resultSet, false);
3401
3233
 
3402
3234
  final Ruby runtime = context.runtime;
3403
- final IRubyObject[] blockArgs = new IRubyObject[columns.length];
3404
3235
  while ( resultSet.next() ) {
3236
+ final IRubyObject[] blockArgs = new IRubyObject[columns.length];
3405
3237
  for ( int i = 0; i < columns.length; i++ ) {
3406
3238
  final ColumnData column = columns[i];
3407
3239
  blockArgs[i] = jdbcToRuby(context, runtime, column.index, column.type, resultSet);
@@ -3427,16 +3259,6 @@ public class RubyJdbcConnection extends RubyObject {
3427
3259
  return setupColumns(context, connection, resultSet.getMetaData(), downCase);
3428
3260
  }
3429
3261
 
3430
- /**
3431
- * @deprecated use {@link #extractColumns(ThreadContext, Connection, ResultSet, boolean)}
3432
- */
3433
- @Deprecated
3434
- protected ColumnData[] extractColumns(final Ruby runtime,
3435
- final Connection connection, final ResultSet resultSet,
3436
- final boolean downCase) throws SQLException {
3437
- return extractColumns(runtime.getCurrentContext(), connection, resultSet, downCase);
3438
- }
3439
-
3440
3262
  protected <T> T withConnection(final ThreadContext context, final Callable<T> block)
3441
3263
  throws RaiseException {
3442
3264
  try {
@@ -3542,13 +3364,12 @@ public class RubyJdbcConnection extends RubyObject {
3542
3364
  }
3543
3365
 
3544
3366
  protected boolean isTransient(final Exception exception) {
3545
- if ( exception instanceof SQLTransientException ) return true;
3546
- return false;
3367
+ return exception instanceof SQLTransientException;
3547
3368
  }
3548
3369
 
3549
3370
  protected boolean isRecoverable(final Exception exception) {
3550
- if ( exception instanceof SQLRecoverableException) return true;
3551
- return false; // exception instanceof SQLException; // pre JDBC 4.0 drivers?
3371
+ return exception instanceof SQLRecoverableException;
3372
+ // exception instanceof SQLException; // pre JDBC 4.0 drivers?
3552
3373
  }
3553
3374
 
3554
3375
  private static Throwable getCause(Throwable exception) {
@@ -3706,6 +3527,11 @@ public class RubyJdbcConnection extends RubyObject {
3706
3527
  return Result.newInstance(context, columnsToArray(context, columns), rows, Block.NULL_BLOCK); // Result.new
3707
3528
  }
3708
3529
 
3530
+ protected static IRubyObject newEmptyResult(final ThreadContext context) {
3531
+ final RubyClass Result = getResult(context.runtime);
3532
+ return Result.newInstance(context, RubyArray.newEmptyArray(context.runtime), RubyArray.newEmptyArray(context.runtime), Block.NULL_BLOCK); // Result.new
3533
+ }
3534
+
3709
3535
  private static RubyArray columnsToArray(ThreadContext context, ColumnData[] columns) {
3710
3536
  final IRubyObject[] cols = new IRubyObject[columns.length];
3711
3537
 
@@ -3928,6 +3754,12 @@ public class RubyJdbcConnection extends RubyObject {
3928
3754
  }
3929
3755
  }
3930
3756
 
3757
+ public static void debugMessage(final ThreadContext context, final IRubyObject obj) {
3758
+ if ( isDebug(context.runtime) ) {
3759
+ debugMessage(context.runtime, obj.callMethod(context, "inspect"));
3760
+ }
3761
+ }
3762
+
3931
3763
  public static void debugMessage(final Ruby runtime, final String msg, final Object e) {
3932
3764
  if ( isDebug(runtime) ) {
3933
3765
  final PrintStream out = runtime != null ? runtime.getOut() : System.out;
@@ -3952,7 +3784,7 @@ public class RubyJdbcConnection extends RubyObject {
3952
3784
  public static void debugStackTrace(final ThreadContext context, final Throwable e) {
3953
3785
  if ( debug || ( context != null && context.runtime.isDebug() ) ) {
3954
3786
  final PrintStream out = context != null ? context.runtime.getOut() : System.out;
3955
- if ( debugStackTrace == null || debugStackTrace.booleanValue() ) {
3787
+ if ( debugStackTrace == null || debugStackTrace) {
3956
3788
  e.printStackTrace(out);
3957
3789
  }
3958
3790
  else {
@@ -3968,8 +3800,7 @@ public class RubyJdbcConnection extends RubyObject {
3968
3800
  private static boolean driverUsedLogged;
3969
3801
 
3970
3802
  private void logDriverUsed(final Connection connection) {
3971
- if ( isDebug() ) {
3972
- if ( driverUsedLogged ) return;
3803
+ if (debug && !driverUsedLogged) {
3973
3804
  driverUsedLogged = true;
3974
3805
  try {
3975
3806
  final DatabaseMetaData meta = connection.getMetaData();