activerecord-jdbc-alt-adapter 72.1.0-java → 80.1.0.beta1-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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +23 -16
  3. data/.github/workflows/ruby.yml +123 -18
  4. data/.mise.toml +3 -0
  5. data/Gemfile +43 -48
  6. data/README.md +3 -2
  7. data/RUNNING_TESTS.md +9 -1
  8. data/Rakefile +63 -15
  9. data/activerecord-jdbc-adapter.gemspec +2 -2
  10. data/activerecord-jdbc-alt-adapter.gemspec +1 -1
  11. data/lib/arjdbc/abstract/core.rb +0 -17
  12. data/lib/arjdbc/abstract/database_statements.rb +19 -38
  13. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  14. data/lib/arjdbc/mssql/adapter.rb +12 -11
  15. data/lib/arjdbc/mssql/column.rb +2 -2
  16. data/lib/arjdbc/mssql/database_statements.rb +31 -29
  17. data/lib/arjdbc/mssql/explain_support.rb +6 -1
  18. data/lib/arjdbc/mssql/schema_creation.rb +1 -1
  19. data/lib/arjdbc/mssql/schema_statements.rb +4 -0
  20. data/lib/arjdbc/mssql/type_metadata.rb +36 -0
  21. data/lib/arjdbc/mssql/types/binary_types.rb +5 -4
  22. data/lib/arjdbc/mssql/types/deprecated_types.rb +15 -12
  23. data/lib/arjdbc/mssql/types/string_types.rb +10 -8
  24. data/lib/arjdbc/mssql.rb +1 -1
  25. data/lib/arjdbc/postgresql/adapter.rb +4 -5
  26. data/lib/arjdbc/postgresql/database_statements.rb +45 -0
  27. data/lib/arjdbc/postgresql/schema_statements.rb +24 -0
  28. data/lib/arjdbc/sqlite3/adapter.rb +51 -7
  29. data/lib/arjdbc/sqlite3/database_statements.rb +26 -0
  30. data/lib/arjdbc/tasks/mssql_database_tasks.rb +1 -21
  31. data/lib/arjdbc/version.rb +1 -1
  32. data/pom.xml +3 -3
  33. data/rakelib/02-test.rake +1 -1
  34. data/rakelib/db.rake +5 -3
  35. data/rakelib/rails.rake +0 -1
  36. data/src/java/arjdbc/ArJdbcModule.java +13 -10
  37. data/src/java/arjdbc/db2/DB2Module.java +4 -4
  38. data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +8 -9
  39. data/src/java/arjdbc/h2/H2Module.java +2 -1
  40. data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +8 -7
  41. data/src/java/arjdbc/hsqldb/HSQLDBModule.java +5 -6
  42. data/src/java/arjdbc/jdbc/DataSourceConnectionFactory.java +4 -3
  43. data/src/java/arjdbc/jdbc/DriverWrapper.java +13 -8
  44. data/src/java/arjdbc/jdbc/JdbcResult.java +10 -7
  45. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +171 -155
  46. data/src/java/arjdbc/mssql/MSSQLModule.java +3 -3
  47. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +13 -9
  48. data/src/java/arjdbc/mysql/MySQLModule.java +3 -3
  49. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +25 -23
  50. data/src/java/arjdbc/oracle/OracleModule.java +2 -3
  51. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +22 -18
  52. data/src/java/arjdbc/postgresql/PostgreSQLModule.java +2 -3
  53. data/src/java/arjdbc/postgresql/PostgreSQLResult.java +24 -12
  54. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +16 -12
  55. data/src/java/arjdbc/sqlite3/SQLite3Module.java +2 -3
  56. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +78 -29
  57. data/src/java/arjdbc/util/DateTimeUtils.java +7 -5
  58. data/src/java/arjdbc/util/ObjectSupport.java +2 -2
  59. data/src/java/arjdbc/util/StringHelper.java +1 -1
  60. metadata +8 -6
  61. data/.travis.yml +0 -128
@@ -219,6 +219,10 @@ module ArJdbc
219
219
  true
220
220
  end
221
221
 
222
+ def supports_native_partitioning?
223
+ database_version >= 100_000
224
+ end
225
+
222
226
  def supports_insert_returning?
223
227
  true
224
228
  end
@@ -953,9 +957,6 @@ module ActiveRecord::ConnectionAdapters
953
957
  FEATURE_NOT_SUPPORTED = "0A000" # :nodoc:
954
958
 
955
959
  def execute_and_clear(sql, name, binds, prepare: false, async: false)
956
- sql = transform_query(sql)
957
- check_if_write_query(sql)
958
-
959
960
  if !prepare || without_prepared_statement?(binds)
960
961
  result = exec_no_cache(sql, name, binds, async: async)
961
962
  else
@@ -972,7 +973,6 @@ module ActiveRecord::ConnectionAdapters
972
973
 
973
974
  def exec_no_cache(sql, name, binds, async: false)
974
975
  materialize_transactions
975
- mark_transaction_written_if_write(sql)
976
976
 
977
977
  # make sure we carry over any changes to ActiveRecord.default_timezone that have been
978
978
  # made since we established the connection
@@ -990,7 +990,6 @@ module ActiveRecord::ConnectionAdapters
990
990
 
991
991
  def exec_cache(sql, name, binds, async: false)
992
992
  materialize_transactions
993
- mark_transaction_written_if_write(sql)
994
993
  update_typemap_for_default_timezone
995
994
 
996
995
  stmt_key = prepare_statement(sql, binds)
@@ -15,6 +15,51 @@ module ArJdbc
15
15
 
16
16
  "EXPLAIN (#{options.join(", ").upcase})"
17
17
  end
18
+
19
+ private
20
+
21
+ def internal_exec_query(sql, name = nil, binds = [], prepare: false, async: false, allow_retry: false, materialize_transactions: true)
22
+ sql = preprocess_query(sql)
23
+
24
+ # puts "[1]internal----->sql: #{sql}, binds: #{binds}"
25
+ type_casted_binds = type_casted_binds(binds)
26
+ # puts "[2]internal----->sql: #{type_casted_binds.size}, binds: #{type_casted_binds}"
27
+
28
+ with_raw_connection do |conn|
29
+ if without_prepared_statement?(binds)
30
+ log(sql, name, async: async) { conn.execute_query(sql) }
31
+ else
32
+ log(sql, name, type_casted_binds, async: async) do
33
+ # this is different from normal AR that always caches
34
+ cached_statement = fetch_cached_statement(sql) if prepare && @jdbc_statement_cache_enabled
35
+ conn.execute_prepared_query(sql, type_casted_binds, cached_statement)
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ def perform_query(raw_connection, sql, binds, type_casted_binds, prepare:, notification_payload:, batch:)
42
+ result = raw_connection.execute(sql)
43
+
44
+ count = 0
45
+ count = result.count if result.respond_to?(:count)
46
+
47
+ verified!
48
+ notification_payload[:row_count] = count
49
+ result
50
+ end
51
+
52
+ def cast_result(raw_result)
53
+ return ActiveRecord::Result.empty if raw_result.nil?
54
+
55
+ fields = raw_result.fields
56
+
57
+ if fields.empty?
58
+ ActiveRecord::Result.empty
59
+ else
60
+ ActiveRecord::Result.new(fields, raw_result.values)
61
+ end
62
+ end
18
63
  end
19
64
  end
20
65
  end
@@ -6,6 +6,30 @@ module ArJdbc
6
6
  ForeignKeyDefinition = ActiveRecord::ConnectionAdapters::ForeignKeyDefinition
7
7
  Utils = ActiveRecord::ConnectionAdapters::PostgreSQL::Utils
8
8
 
9
+ def decode_string_array(value)
10
+ return value if value.is_a?(Array)
11
+ _arjdbc_array_parser.parse_pg_array(value)
12
+ end
13
+
14
+ # Returns an array of the names of all schemas presently in the effective search path,
15
+ # in their priority order.
16
+ def current_schemas # :nodoc:
17
+ schemas = query_value("SELECT current_schemas(false)", "SCHEMA")
18
+ decode_string_array(schemas)
19
+ end
20
+
21
+ private
22
+
23
+ def _arjdbc_array_parser
24
+ @_arjdbc_array_parser ||= begin
25
+ obj = Object.new
26
+ obj.extend(ActiveRecord::ConnectionAdapters::PostgreSQL::ArrayParser)
27
+ obj
28
+ end
29
+ end
30
+
31
+ public
32
+
9
33
  def foreign_keys(table_name)
10
34
  scope = quoted_scope(table_name)
11
35
  fk_info = internal_exec_query(<<~SQL, "SCHEMA", allow_retry: true, materialize_transactions: false)
@@ -22,6 +22,8 @@ require "arjdbc/sqlite3/pragmas"
22
22
 
23
23
  require "arjdbc/abstract/relation_query_attribute_monkey_patch"
24
24
 
25
+ require "arjdbc/sqlite3/database_statements"
26
+
25
27
  module SQLite3
26
28
  module Constants
27
29
  module Open
@@ -223,17 +225,29 @@ module ArJdbc
223
225
 
224
226
  # REFERENTIAL INTEGRITY ====================================
225
227
 
228
+ def execute_batch(statements, name = nil, **kwargs)
229
+ if statements.is_a?(Array)
230
+ # SQLite JDBC doesn't support multiple statements in one execute
231
+ # Execute each statement separately
232
+ statements.each do |sql|
233
+ raw_execute(sql, name, **kwargs.merge(batch: true))
234
+ end
235
+ else
236
+ raw_execute(statements, name, batch: true, **kwargs)
237
+ end
238
+ end
239
+
226
240
  def disable_referential_integrity # :nodoc:
227
241
  old_foreign_keys = query_value("PRAGMA foreign_keys")
228
242
  old_defer_foreign_keys = query_value("PRAGMA defer_foreign_keys")
229
243
 
230
244
  begin
231
- execute("PRAGMA defer_foreign_keys = ON")
232
- execute("PRAGMA foreign_keys = OFF")
245
+ execute("PRAGMA defer_foreign_keys = ON", "SCHEMA")
246
+ execute("PRAGMA foreign_keys = OFF", "SCHEMA")
233
247
  yield
234
248
  ensure
235
- execute("PRAGMA defer_foreign_keys = #{old_defer_foreign_keys}")
236
- execute("PRAGMA foreign_keys = #{old_foreign_keys}")
249
+ execute("PRAGMA defer_foreign_keys = #{old_defer_foreign_keys}", "SCHEMA")
250
+ execute("PRAGMA foreign_keys = #{old_foreign_keys}", "SCHEMA")
237
251
  end
238
252
  end
239
253
 
@@ -388,6 +402,24 @@ module ArJdbc
388
402
  end
389
403
  end
390
404
 
405
+ # Returns a list of defined virtual tables (for Rails 8 compatibility)
406
+ VIRTUAL_TABLE_REGEX = /USING\s+(\w+)(?:\s*\((.*)\))?/im
407
+ def virtual_tables
408
+ query = <<~SQL
409
+ SELECT name, sql FROM sqlite_master
410
+ WHERE type = 'table' AND sql LIKE 'CREATE VIRTUAL TABLE%';
411
+ SQL
412
+
413
+ exec_query(query, "SCHEMA").cast_values.each_with_object({}) do |(name, sql), memo|
414
+ match = sql.match(VIRTUAL_TABLE_REGEX)
415
+ next unless match
416
+
417
+ module_name = match[1]
418
+ arguments = match[2] || ""
419
+ memo[name] = [module_name, arguments.strip]
420
+ end.to_a
421
+ end
422
+
391
423
  def build_insert_sql(insert) # :nodoc:
392
424
  sql = +"INSERT #{insert.into} #{insert.values_list}"
393
425
 
@@ -791,7 +823,17 @@ module ArJdbc
791
823
  DEFAULT_PRAGMAS.merge(pragmas).each do |pragma, value|
792
824
  if ::SQLite3::Pragmas.respond_to?(pragma)
793
825
  stmt = ::SQLite3::Pragmas.public_send(pragma, value)
794
- raw_execute(stmt, "SCHEMA")
826
+ # Skip pragma execution if we're inside a transaction and it's not allowed
827
+ begin
828
+ raw_connection.execute(stmt)
829
+ rescue => e
830
+ if e.message.include?("Safety level may not be changed inside a transaction")
831
+ # Log warning and skip this pragma
832
+ warn "Cannot set pragma '#{pragma}' inside a transaction, skipping"
833
+ else
834
+ raise
835
+ end
836
+ end
795
837
  else
796
838
  warn "Unknown SQLite pragma: #{pragma}"
797
839
  end
@@ -845,8 +887,9 @@ module ActiveRecord::ConnectionAdapters
845
887
  include ArJdbc::Abstract::ConnectionManagement
846
888
  include ArJdbc::Abstract::DatabaseStatements
847
889
  include ArJdbc::Abstract::StatementCache
848
- include ArJdbc::Abstract::TransactionSupport
890
+ # Don't include TransactionSupport - use Rails' SQLite3::DatabaseStatements instead
849
891
 
892
+ include ::ArJdbc::SQLite3::DatabaseStatements
850
893
 
851
894
  ##
852
895
  # :singleton-method:
@@ -954,7 +997,8 @@ module ActiveRecord::ConnectionAdapters
954
997
 
955
998
  # because the JDBC driver doesn't like multiple SQL statements in one JDBC statement
956
999
  def combine_multi_statements(total_sql)
957
- total_sql
1000
+ # For Rails 8 compatibility - join multiple statements with semicolon
1001
+ total_sql.is_a?(Array) ? total_sql.join(";\n") : total_sql
958
1002
  end
959
1003
 
960
1004
  def type_map
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ArJdbc
4
+ module SQLite3
5
+ module DatabaseStatements
6
+ private
7
+
8
+ def perform_query(raw_connection, sql, binds, type_casted_binds, prepare:, notification_payload:, batch:)
9
+ result = raw_connection.execute(sql)
10
+
11
+ count = 0
12
+ count = result.count if result.respond_to?(:count)
13
+
14
+ verified!
15
+ notification_payload[:row_count] = count
16
+ result
17
+ end
18
+
19
+ def cast_result(raw_result)
20
+ return ActiveRecord::Result.empty if raw_result.nil?
21
+
22
+ raw_result
23
+ end
24
+ end
25
+ end
26
+ end
@@ -4,7 +4,7 @@ require 'active_record/tasks/database_tasks'
4
4
 
5
5
  module ArJdbc
6
6
  module Tasks # :nodoc:
7
- class MSSQLDatabaseTasks # :nodoc:
7
+ class MSSQLDatabaseTasks < ActiveRecord::Tasks::AbstractTasks # :nodoc:
8
8
  def self.using_database_configurations?
9
9
  true
10
10
  end
@@ -127,25 +127,5 @@ module ArJdbc
127
127
  msg
128
128
  end
129
129
  end
130
-
131
- module DatabaseTasksMSSQL
132
- extend ActiveSupport::Concern
133
-
134
- module ClassMethods
135
-
136
- def check_protected_environments!
137
- super
138
- rescue ActiveRecord::JDBCError => e
139
- case e.message
140
- when /cannot open database .* requested by the login/i
141
- else
142
- raise
143
- end
144
- end
145
-
146
- end
147
- end
148
-
149
- ActiveRecord::Tasks::DatabaseTasks.send(:include, DatabaseTasksMSSQL)
150
130
  end
151
131
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ArJdbc
4
- VERSION = "72.1.0"
4
+ VERSION = "80.1.0.beta1"
5
5
  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.2.6.0</jruby.version>
15
+ <jruby.version>10.0.0.1</jruby.version>
16
16
  </properties>
17
17
 
18
18
  <issueManagement>
@@ -103,8 +103,8 @@
103
103
  <artifactId>maven-compiler-plugin</artifactId>
104
104
  <version>2.5.1</version>
105
105
  <configuration>
106
- <source>1.8</source>
107
- <target>1.8</target>
106
+ <source>21</source>
107
+ <target>21</target>
108
108
  </configuration>
109
109
  </plugin>
110
110
  </plugins>
data/rakelib/02-test.rake CHANGED
@@ -36,7 +36,7 @@ def test_task_for(adapter, options = {})
36
36
  test_task.libs = []
37
37
  if defined?(JRUBY_VERSION)
38
38
  test_task.libs << 'lib'
39
- test_task.libs << "jdbc-#{driver}/lib" if driver && File.exists?("jdbc-#{driver}/lib")
39
+ test_task.libs << "jdbc-#{driver}/lib" if driver && File.exist?("jdbc-#{driver}/lib")
40
40
  test_task.libs.push *FileList["activerecord-jdbc#{adapter}*/lib"]
41
41
  end
42
42
  test_task.libs << 'test'
data/rakelib/db.rake CHANGED
@@ -39,7 +39,7 @@ GRANT ALL PRIVILEGES ON `test\_%`.* TO #{MYSQL_CONFIG[:username]}@localhost;
39
39
  task :postgresql do
40
40
  require File.expand_path('../../test/shared_helper', __FILE__)
41
41
  fail 'could not create test database: psql executable not found' unless psql = which('psql')
42
- fail 'could not create test database: missing "postgres" role' unless PostgresHelper.postgres_role?
42
+ fail 'could not create test database: missing "arjdbc" role' unless PostgresHelper.postgres_role?
43
43
 
44
44
  load 'test/db/postgres_config.rb' # rescue nil
45
45
  puts POSTGRES_CONFIG.inspect if $VERBOSE
@@ -53,11 +53,13 @@ CREATE DATABASE #{POSTGRES_CONFIG[:database]} OWNER #{POSTGRES_CONFIG[:username]
53
53
  ENCODING '#{POSTGRES_CONFIG[:encoding]}' LC_COLLATE '#{POSTGRES_CONFIG[:collate]}' LC_CTYPE '#{POSTGRES_CONFIG[:collate]}';
54
54
  SQL
55
55
 
56
- params = { '-U' => ENV['PSQL_USER'] || 'postgres' }
56
+ params = { '-U' => ENV['PGUSER'] || 'arjdbc', '-d' => 'postgres' }
57
+ params['-h'] = ENV['PGHOST'] if ENV['PGHOST']
58
+ params['-p'] = ENV['PGPORT'] if ENV['PGPORT']
57
59
  params['-q'] = nil unless $VERBOSE
58
60
 
59
61
  puts "Creating PostgreSQL (test) database: #{POSTGRES_CONFIG[:database]}"
60
- sh "cat #{script.path} | #{psql} #{params.to_a.join(' ')}", verbose: $VERBOSE
62
+ sh "PGPASSWORD=#{ENV['PGPASSWORD'] || 'arjdbc'} cat #{script.path} | #{psql} #{params.to_a.join(' ')}", verbose: $VERBOSE
61
63
  end
62
64
  task postgres: :postgresql
63
65
 
data/rakelib/rails.rake CHANGED
@@ -58,7 +58,6 @@ namespace :rails do
58
58
  ruby_opts_string += " -C \"#{ar_path}\""
59
59
  ruby_opts_string += " -rbundler/setup"
60
60
  ruby_opts_string += " -rminitest -rminitest/excludes" unless ENV['NO_EXCLUDES'].eql?('true')
61
- ruby_opts_string += " -rmonkey_patches"
62
61
  file_list = ENV["TEST"] ? FileList[ ENV["TEST"].split(',') ] : test_files_finder.call
63
62
  file_list_string = file_list.map { |fn| "\"#{fn}\"" }.join(' ')
64
63
  # test_loader_code = "-e \"ARGV.each{|f| require f}\"" # :direct
@@ -43,6 +43,9 @@ import org.jruby.util.ByteList;
43
43
 
44
44
  import arjdbc.jdbc.RubyJdbcConnection;
45
45
  import static arjdbc.jdbc.RubyJdbcConnection.getJdbcConnection;
46
+ import static org.jruby.api.Access.getModule;
47
+ import static org.jruby.api.Access.objectClass;
48
+ import static org.jruby.api.Create.allocArray;
46
49
 
47
50
  /**
48
51
  * ::ArJdbc
@@ -52,9 +55,10 @@ import static arjdbc.jdbc.RubyJdbcConnection.getJdbcConnection;
52
55
  public class ArJdbcModule {
53
56
 
54
57
  public static RubyModule load(final Ruby runtime) {
55
- final RubyModule arJdbc = runtime.getOrCreateModule("ArJdbc");
56
- arJdbc.defineAnnotatedMethods( ArJdbcModule.class );
57
- return arJdbc;
58
+ var context = runtime.getCurrentContext();
59
+ return objectClass(context).
60
+ defineModuleUnder(context, "ArJdbc").
61
+ defineMethods(context, ArJdbcModule.class);
58
62
  }
59
63
 
60
64
  public static RubyModule get(final Ruby runtime) {
@@ -142,7 +146,7 @@ public class ArJdbcModule {
142
146
  catch (NoSuchMethodException e) {
143
147
  // "old" e.g. MySQLRubyJdbcConnection.createMySQLJdbcConnectionClass(runtime, jdbcConnection)
144
148
  connection.getMethod("create" + moduleName + "JdbcConnectionClass", Ruby.class, RubyClass.class).
145
- invoke(null, runtime, getJdbcConnection(runtime));
149
+ invoke(null, runtime, getJdbcConnection(context));
146
150
  }
147
151
  }
148
152
  }
@@ -162,20 +166,19 @@ public class ArJdbcModule {
162
166
  */
163
167
  @JRubyMethod(name = "modules", meta = true)
164
168
  public static IRubyObject modules(final ThreadContext context, final IRubyObject self) {
165
- final Ruby runtime = context.getRuntime();
166
169
  final RubyModule arJdbc = (RubyModule) self;
167
170
 
168
171
  final Collection<String> constants = arJdbc.getConstantNames();
169
- final RubyArray modules = runtime.newArray( constants.size() );
172
+ final RubyArray modules = allocArray(context, constants.size());
170
173
 
171
174
  for ( final String name : constants ) {
172
- final IRubyObject constant = arJdbc.getConstant(name, false);
175
+ final IRubyObject constant = arJdbc.getConstant(context, name, false);
173
176
  // isModule: return false for Ruby Classes
174
177
  if ( constant != null && constant.isModule() ) {
175
178
  if ( "Util".equals(name) ) continue;
176
179
  if ( "SerializedAttributesHelper".equals(name) ) continue; // deprecated
177
180
  if ( "Version".equals(name) ) continue; // deprecated
178
- modules.append( constant );
181
+ modules.append(context, constant);
179
182
  }
180
183
  }
181
184
  return modules;
@@ -230,9 +233,9 @@ public class ArJdbcModule {
230
233
  return null;
231
234
  }
232
235
 
233
- final RubyModule jdbc = runtime.getModule("Jdbc");
236
+ final RubyModule jdbc = getModule(context, "Jdbc");
234
237
  if ( jdbc != null ) { // Jdbc::MySQL
235
- final RubyModule constant = (RubyModule) jdbc.getConstantAt(constName);
238
+ final RubyModule constant = jdbc.getModule(context, constName);
236
239
  if ( constant != null ) { // ::Jdbc::MySQL.load_driver :
237
240
  if ( constant.respondsTo("load_driver") ) {
238
241
  IRubyObject result = constant.callMethod("load_driver");
@@ -26,6 +26,7 @@ package arjdbc.db2;
26
26
  import static arjdbc.util.QuotingUtils.BYTES_0;
27
27
  import static arjdbc.util.QuotingUtils.BYTES_1;
28
28
  import static arjdbc.util.QuotingUtils.quoteSingleQuotesWithFallback;
29
+ import static org.jruby.api.Create.newString;
29
30
 
30
31
  import org.jruby.Ruby;
31
32
  import org.jruby.RubyModule;
@@ -42,9 +43,8 @@ import org.jruby.runtime.builtin.IRubyObject;
42
43
  public class DB2Module {
43
44
 
44
45
  public static RubyModule load(final RubyModule arJdbc) {
45
- RubyModule db2 = arJdbc.defineModuleUnder("DB2");
46
- db2.defineAnnotatedMethods( DB2Module.class );
47
- return db2;
46
+ var context = arJdbc.getRuntime().getCurrentContext();
47
+ return arJdbc.defineModuleUnder(context, "DB2").defineMethods(context, DB2Module.class);
48
48
  }
49
49
 
50
50
  public static RubyModule load(final Ruby runtime) {
@@ -63,7 +63,7 @@ public class DB2Module {
63
63
  public static IRubyObject quoted_true(
64
64
  final ThreadContext context,
65
65
  final IRubyObject self) {
66
- return RubyString.newString(context.runtime, BYTES_1);
66
+ return newString(context, BYTES_1);
67
67
  }
68
68
 
69
69
  @JRubyMethod(name = "quoted_false", required = 0, frame = false)
@@ -54,17 +54,16 @@ public class DB2RubyJdbcConnection extends RubyJdbcConnection {
54
54
  super(runtime, metaClass);
55
55
  }
56
56
 
57
- public static RubyClass createDB2JdbcConnectionClass(Ruby runtime, RubyClass jdbcConnection) {
58
- RubyClass clazz = getConnectionAdapters(runtime).
59
- defineClassUnder("DB2JdbcConnection", jdbcConnection, ALLOCATOR);
60
- clazz.defineAnnotatedMethods(DB2RubyJdbcConnection.class);
61
-
62
- return clazz;
57
+ public static RubyClass createDB2JdbcConnectionClass(ThreadContext context, RubyClass jdbcConnection) {
58
+ return getConnectionAdapters(context).
59
+ defineClassUnder(context, "DB2JdbcConnection", jdbcConnection, ALLOCATOR).
60
+ defineMethods(context, DB2RubyJdbcConnection.class);
63
61
  }
64
62
 
65
63
  public static RubyClass load(final Ruby runtime) {
66
- RubyClass jdbcConnection = getJdbcConnection(runtime);
67
- return createDB2JdbcConnectionClass(runtime, jdbcConnection);
64
+ var context = runtime.getCurrentContext();
65
+ RubyClass jdbcConnection = getJdbcConnection(context);
66
+ return createDB2JdbcConnectionClass(context, jdbcConnection);
68
67
  }
69
68
 
70
69
  protected static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
@@ -112,7 +111,7 @@ public class DB2RubyJdbcConnection extends RubyJdbcConnection {
112
111
  try {
113
112
  statement = connection.prepareStatement("VALUES IDENTITY_VAL_LOCAL()");
114
113
  genKeys = statement.executeQuery();
115
- return doMapGeneratedKeys(context.runtime, genKeys, true);
114
+ return doMapGeneratedKeys(context, genKeys, true);
116
115
  }
117
116
  catch (final SQLException e) {
118
117
  debugMessage(context.runtime, "failed to get generated keys: ", e);
@@ -37,7 +37,8 @@ import org.jruby.RubyModule;
37
37
  public class H2Module {
38
38
 
39
39
  public static RubyModule load(final RubyModule arJdbc) {
40
- RubyModule h2 = arJdbc.defineModuleUnder("H2");
40
+ var context = arJdbc.getRuntime().getCurrentContext();
41
+ RubyModule h2 = arJdbc.defineModuleUnder(context, "H2");
41
42
  // NOTE: currently no Java implemented Ruby methods
42
43
  // h2.defineAnnotatedMethods( H2Module.class );
43
44
  return h2;
@@ -28,9 +28,11 @@ package arjdbc.h2;
28
28
  import java.sql.Connection;
29
29
  import java.sql.SQLException;
30
30
 
31
+ import arjdbc.db2.DB2RubyJdbcConnection;
31
32
  import org.jruby.Ruby;
32
33
  import org.jruby.RubyClass;
33
34
  import org.jruby.runtime.ObjectAllocator;
35
+ import org.jruby.runtime.ThreadContext;
34
36
  import org.jruby.runtime.builtin.IRubyObject;
35
37
 
36
38
  /**
@@ -45,16 +47,15 @@ public class H2RubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection {
45
47
  super(runtime, metaClass);
46
48
  }
47
49
 
48
- public static RubyClass createH2JdbcConnectionClass(Ruby runtime, RubyClass jdbcConnection) {
49
- RubyClass clazz = getConnectionAdapters(runtime).
50
- defineClassUnder("H2JdbcConnection", jdbcConnection, ALLOCATOR);
51
- clazz.defineAnnotatedMethods(H2RubyJdbcConnection.class);
52
- return clazz;
50
+ public static RubyClass createH2JdbcConnectionClass(ThreadContext context, RubyClass jdbcConnection) {
51
+ return getConnectionAdapters(context).
52
+ defineClassUnder(context, "H2JdbcConnection", jdbcConnection, ALLOCATOR).
53
+ defineMethods(context, H2RubyJdbcConnection.class);
53
54
  }
54
55
 
55
56
  public static RubyClass load(final Ruby runtime) {
56
- RubyClass jdbcConnection = getJdbcConnection(runtime);
57
- return createH2JdbcConnectionClass(runtime, jdbcConnection);
57
+ var context = runtime.getCurrentContext();
58
+ return createH2JdbcConnectionClass(context, getJdbcConnection(context));
58
59
  }
59
60
 
60
61
  protected static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
@@ -28,10 +28,10 @@ package arjdbc.hsqldb;
28
28
  import static arjdbc.util.QuotingUtils.BYTES_0;
29
29
  import static arjdbc.util.QuotingUtils.BYTES_1;
30
30
  import static arjdbc.util.QuotingUtils.quoteSingleQuotesWithFallback;
31
+ import static org.jruby.api.Create.newString;
31
32
 
32
33
  import org.jruby.Ruby;
33
34
  import org.jruby.RubyModule;
34
- import org.jruby.RubyString;
35
35
  import org.jruby.anno.JRubyMethod;
36
36
  import org.jruby.runtime.ThreadContext;
37
37
  import org.jruby.runtime.builtin.IRubyObject;
@@ -39,9 +39,8 @@ import org.jruby.runtime.builtin.IRubyObject;
39
39
  public class HSQLDBModule {
40
40
 
41
41
  public static RubyModule load(final RubyModule arJdbc) {
42
- RubyModule hsqldb = arJdbc.defineModuleUnder("HSQLDB");
43
- hsqldb.defineAnnotatedMethods( HSQLDBModule.class );
44
- return hsqldb;
42
+ var context = arJdbc.getRuntime().getCurrentContext();
43
+ return arJdbc.defineModuleUnder(context, "HSQLDB").defineMethods(context, HSQLDBModule.class);
45
44
  }
46
45
 
47
46
  public static RubyModule load(final Ruby runtime) {
@@ -60,14 +59,14 @@ public class HSQLDBModule {
60
59
  public static IRubyObject quoted_true(
61
60
  final ThreadContext context,
62
61
  final IRubyObject self) {
63
- return RubyString.newString(context.getRuntime(), BYTES_1);
62
+ return newString(context, BYTES_1);
64
63
  }
65
64
 
66
65
  @JRubyMethod(name = "quoted_false", required = 0, frame = false)
67
66
  public static IRubyObject quoted_false(
68
67
  final ThreadContext context,
69
68
  final IRubyObject self) {
70
- return RubyString.newString(context.getRuntime(), BYTES_0);
69
+ return newString(context, BYTES_0);
71
70
  }
72
71
 
73
72
  }
@@ -36,6 +36,7 @@ import org.jruby.util.SafePropertyAccessor;
36
36
 
37
37
  import static arjdbc.jdbc.RubyJdbcConnection.getConnectionNotEstablished;
38
38
  import static arjdbc.jdbc.RubyJdbcConnection.wrapException;
39
+ import static org.jruby.api.Access.runtimeErrorClass;
39
40
 
40
41
  /**
41
42
  *
@@ -103,7 +104,7 @@ final class DataSourceConnectionFactory implements ConnectionFactory {
103
104
  if ( ! ( bound instanceof DataSource ) ) {
104
105
  if ( bound == null ) throw new NameNotFoundException(); // unlikely to happen
105
106
  final String msg = "bound object at '" + name + "' is not a " + DataSource.class.getName() + " but a " + bound.getClass().getName() + "\n" + bound;
106
- throw wrapException(context, getConnectionNotEstablished(context.runtime), new ClassCastException(msg), msg);
107
+ throw wrapException(context, getConnectionNotEstablished(context), new ClassCastException(msg), msg);
107
108
  }
108
109
  return (DataSource) bound;
109
110
  }
@@ -124,10 +125,10 @@ final class DataSourceConnectionFactory implements ConnectionFactory {
124
125
  else {
125
126
  message = "unable to lookup data source - name: '" + name + "' not found";
126
127
  }
127
- throw wrapException(context, getConnectionNotEstablished(context.runtime), e, message);
128
+ throw wrapException(context, getConnectionNotEstablished(context), e, message);
128
129
  }
129
130
  catch (NamingException e) {
130
- throw wrapException(context, context.runtime.getRuntimeError(), e);
131
+ throw wrapException(context, runtimeErrorClass(context), e);
131
132
  }
132
133
  }
133
134
 
@@ -23,6 +23,7 @@
23
23
  */
24
24
  package arjdbc.jdbc;
25
25
 
26
+ import java.lang.reflect.InvocationTargetException;
26
27
  import java.sql.Connection;
27
28
  import java.sql.Driver;
28
29
  import java.sql.SQLException;
@@ -45,7 +46,7 @@ public class DriverWrapper {
45
46
  private final Properties properties;
46
47
 
47
48
  DriverWrapper(final Ruby runtime, final String name, final Properties properties)
48
- throws ClassCastException, InstantiationException, IllegalAccessException {
49
+ throws ClassCastException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
49
50
  this.driver = allocateDriver( loadDriver(runtime, name) );
50
51
  this.properties = properties == null ? new Properties() : properties;
51
52
  }
@@ -59,18 +60,22 @@ public class DriverWrapper {
59
60
  }
60
61
 
61
62
  private Driver allocateDriver(final Class<? extends Driver> driverClass)
62
- throws InstantiationException, IllegalAccessException {
63
- return driverClass.newInstance();
63
+ throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
64
+ return driverClass.getDeclaredConstructor().newInstance();
64
65
  }
65
66
 
66
67
  protected static Class<? extends Driver> loadDriver(final Ruby runtime, final String name)
67
68
  throws ClassCastException {
68
- @SuppressWarnings("unchecked")
69
- Class<? extends Driver> klass = runtime.getJavaSupport().loadJavaClassVerbose(name);
70
- if ( ! Driver.class.isAssignableFrom(klass) ) {
71
- throw new ClassCastException(klass + " is not assignable from " + Driver.class);
69
+ try {
70
+ @SuppressWarnings("unchecked")
71
+ Class<? extends Driver> klass = (Class<? extends Driver>) runtime.getJavaSupport().loadJavaClass(name);
72
+ if ( ! Driver.class.isAssignableFrom(klass) ) {
73
+ throw new ClassCastException(klass + " is not assignable from " + Driver.class);
74
+ }
75
+ return klass;
76
+ } catch (ClassNotFoundException e) {
77
+ throw new RuntimeException("Cannot load driver class: " + name, e);
72
78
  }
73
- return klass;
74
79
  }
75
80
 
76
81
  public Connection connect(final String url, final String user, final String pass)