activerecord-jdbc-adapter 70.2-java → 72.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +26 -26
  3. data/.gitignore +8 -0
  4. data/Gemfile +17 -4
  5. data/README.md +10 -5
  6. data/RUNNING_TESTS.md +36 -0
  7. data/activerecord-jdbc-adapter.gemspec +2 -2
  8. data/lib/arjdbc/abstract/connection_management.rb +25 -10
  9. data/lib/arjdbc/abstract/core.rb +15 -13
  10. data/lib/arjdbc/abstract/database_statements.rb +36 -36
  11. data/lib/arjdbc/abstract/relation_query_attribute_monkey_patch.rb +24 -0
  12. data/lib/arjdbc/abstract/statement_cache.rb +2 -7
  13. data/lib/arjdbc/abstract/transaction_support.rb +39 -22
  14. data/lib/arjdbc/jdbc/adapter.rb +0 -1
  15. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  16. data/lib/arjdbc/jdbc/column.rb +0 -34
  17. data/lib/arjdbc/jdbc/connection_methods.rb +1 -1
  18. data/lib/arjdbc/mysql/adapter.rb +108 -32
  19. data/lib/arjdbc/mysql/adapter_hash_config.rb +159 -0
  20. data/lib/arjdbc/mysql.rb +1 -1
  21. data/lib/arjdbc/postgresql/adapter.rb +267 -114
  22. data/lib/arjdbc/postgresql/adapter_hash_config.rb +98 -0
  23. data/lib/arjdbc/postgresql/base/array_encoder.rb +3 -1
  24. data/lib/arjdbc/postgresql/database_statements.rb +20 -0
  25. data/lib/arjdbc/postgresql/oid_types.rb +10 -29
  26. data/lib/arjdbc/postgresql/schema_statements.rb +57 -0
  27. data/lib/arjdbc/postgresql.rb +1 -1
  28. data/lib/arjdbc/sqlite3/adapter.rb +343 -172
  29. data/lib/arjdbc/sqlite3/adapter_hash_config.rb +91 -0
  30. data/lib/arjdbc/sqlite3/column.rb +117 -0
  31. data/lib/arjdbc/sqlite3/connection_methods.rb +7 -2
  32. data/lib/arjdbc/sqlite3/pragmas.rb +105 -0
  33. data/lib/arjdbc/sqlite3.rb +1 -1
  34. data/lib/arjdbc/version.rb +1 -1
  35. data/lib/arjdbc.rb +13 -1
  36. data/rakelib/02-test.rake +2 -2
  37. data/rakelib/rails.rake +2 -0
  38. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +9 -2
  39. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +12 -5
  40. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +14 -3
  41. metadata +15 -11
  42. data/lib/arjdbc/jdbc/base_ext.rb +0 -17
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ArJdbc
4
+ module SQLite3Config
5
+ def build_connection_config(config)
6
+ config = config.deep_dup
7
+
8
+ load_jdbc_driver
9
+
10
+ config[:driver] ||= "org.sqlite.JDBC"
11
+
12
+ parse_sqlite3_config!(config)
13
+
14
+ database = config[:database]
15
+
16
+ # NOTE: "jdbc:sqlite::memory:" syntax is supported
17
+ config[:url] ||= "jdbc:sqlite:#{database == ':memory:' ? '' : database}"
18
+ config[:connection_alive_sql] ||= "SELECT 1"
19
+
20
+ config[:properties] = build_properties(config)
21
+
22
+ config
23
+ end
24
+
25
+ private
26
+
27
+ def load_jdbc_driver
28
+ require "jdbc/sqlite3"
29
+
30
+ ::Jdbc::SQLite3.load_driver(:require) if defined?(::Jdbc::SQLite3.load_driver)
31
+ rescue LoadError
32
+ # assuming driver.jar is on the class-path
33
+ end
34
+
35
+ def build_properties(config)
36
+ properties = config[:properties] || {}
37
+
38
+ if config[:readonly]
39
+ # See
40
+ # * http://sqlite.org/c3ref/open.html
41
+ # * http://sqlite.org/c3ref/c_open_autoproxy.html
42
+ # => 0x01 = readonly, 0x40 = uri (default in JDBC)
43
+ properties[:open_mode] =
44
+ ::SQLite3::Constants::Open::READONLY | ::SQLite3::Constants::Open::URI
45
+ end
46
+
47
+ if config[:flags]
48
+ properties[:open_mode] ||= 0
49
+ properties[:open_mode] |= config[:flags]
50
+
51
+ # JDBC driver has an extra flag for it
52
+ if config[:flags] & ::SQLite3::Constants::Open::SHAREDCACHE != 0
53
+ properties[:shared_cache] = true
54
+ end
55
+ end
56
+
57
+ timeout = config[:timeout]
58
+ if timeout && timeout.to_s !~ /\A\d+\Z/
59
+ raise ActiveRecord::StatementInvalid.new(
60
+ "TypeError: Timeout must be nil or a number (got: #{timeout}).",
61
+ connection_pool: ActiveRecord::ConnectionAdapters::NullPool.new
62
+ )
63
+ end
64
+
65
+ properties["busy_timeout"] ||= timeout unless timeout.nil?
66
+
67
+ properties
68
+ end
69
+
70
+ def parse_sqlite3_config!(config)
71
+ database = (config[:database] ||= config[:dbfile])
72
+
73
+ if database != ":memory:"
74
+ # make sure to have an absolute path. Ruby and Java don't agree
75
+ # on working directory
76
+ base_dir = defined?(Rails.root) ? Rails.root : nil
77
+ config[:database] = File.expand_path(database, base_dir)
78
+ dirname = File.dirname(config[:database])
79
+ Dir.mkdir(dirname) unless File.directory?(dirname)
80
+ end
81
+ rescue Errno::ENOENT => e
82
+ if e.message.include?("No such file or directory")
83
+ raise ActiveRecord::NoDatabaseError.new(
84
+ connection_pool: ActiveRecord::ConnectionAdapters::NullPool.new
85
+ )
86
+ end
87
+
88
+ raise
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord::ConnectionAdapters
4
+ class SQLite3Column < JdbcColumn
5
+
6
+ attr_reader :rowid
7
+
8
+ def initialize(*, auto_increment: nil, rowid: false, generated_type: nil, **)
9
+ super
10
+
11
+ @auto_increment = auto_increment
12
+ @default = nil if default =~ /NULL/
13
+ @rowid = rowid
14
+ @generated_type = generated_type
15
+ end
16
+
17
+ def self.string_to_binary(value)
18
+ value
19
+ end
20
+
21
+ def self.binary_to_string(value)
22
+ if value.respond_to?(:encoding) && value.encoding != Encoding::ASCII_8BIT
23
+ value = value.force_encoding(Encoding::ASCII_8BIT)
24
+ end
25
+ value
26
+ end
27
+
28
+ # @override {ActiveRecord::ConnectionAdapters::JdbcColumn#default_value}
29
+ def default_value(value)
30
+ # JDBC returns column default strings with actual single quotes :
31
+ return $1 if value =~ /^'(.*)'$/
32
+
33
+ value
34
+ end
35
+
36
+ def auto_increment?
37
+ @auto_increment
38
+ end
39
+
40
+ def auto_incremented_by_db?
41
+ auto_increment? || rowid
42
+ end
43
+
44
+ def virtual?
45
+ !@generated_type.nil?
46
+ end
47
+
48
+ def virtual_stored?
49
+ virtual? && @generated_type == :stored
50
+ end
51
+
52
+ def has_default?
53
+ super && !virtual?
54
+ end
55
+
56
+ def init_with(coder)
57
+ @auto_increment = coder["auto_increment"]
58
+ super
59
+ end
60
+
61
+ def encode_with(coder)
62
+ coder["auto_increment"] = @auto_increment
63
+ super
64
+ end
65
+
66
+ def ==(other)
67
+ other.is_a?(Column) &&
68
+ super &&
69
+ auto_increment? == other.auto_increment?
70
+ end
71
+ alias :eql? :==
72
+
73
+ def hash
74
+ Column.hash ^
75
+ super.hash ^
76
+ auto_increment?.hash ^
77
+ rowid.hash
78
+ end
79
+
80
+ # @override {ActiveRecord::ConnectionAdapters::Column#type_cast}
81
+ def type_cast(value)
82
+ return nil if value.nil?
83
+ case type
84
+ when :string then value
85
+ when :primary_key
86
+ value.respond_to?(:to_i) ? value.to_i : ( value ? 1 : 0 )
87
+ when :float then value.to_f
88
+ when :decimal then self.class.value_to_decimal(value)
89
+ when :boolean then self.class.value_to_boolean(value)
90
+ else super
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+ # @override {ActiveRecord::ConnectionAdapters::Column#extract_limit}
97
+ def extract_limit(sql_type)
98
+ return nil if sql_type =~ /^(real)\(\d+/i
99
+ super
100
+ end
101
+
102
+ def extract_precision(sql_type)
103
+ case sql_type
104
+ when /^(real)\((\d+)(,\d+)?\)/i then $2.to_i
105
+ else super
106
+ end
107
+ end
108
+
109
+ def extract_scale(sql_type)
110
+ case sql_type
111
+ when /^(real)\((\d+)\)/i then 0
112
+ when /^(real)\((\d+)(,(\d+))\)/i then $4.to_i
113
+ else super
114
+ end
115
+ end
116
+ end
117
+ end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  ArJdbc::ConnectionMethods.module_eval do
3
3
  def sqlite3_connection(config)
4
+ raise ArgumentError, 'Configuration must not be empty' if config.blank?
5
+
4
6
  config = config.deep_dup
5
7
  config[:adapter_spec] ||= ::ArJdbc::SQLite3
6
8
  config[:adapter_class] = ActiveRecord::ConnectionAdapters::SQLite3Adapter unless config.key?(:adapter_class)
@@ -18,7 +20,7 @@ ArJdbc::ConnectionMethods.module_eval do
18
20
  parse_sqlite3_config!(config)
19
21
  rescue Errno::ENOENT => error
20
22
  if error.message.include?('No such file or directory')
21
- raise ActiveRecord::NoDatabaseError
23
+ raise ActiveRecord::NoDatabaseError.new(connection_pool: ActiveRecord::ConnectionAdapters::NullPool.new)
22
24
  else
23
25
  raise
24
26
  end
@@ -50,7 +52,10 @@ ArJdbc::ConnectionMethods.module_eval do
50
52
 
51
53
  timeout = config[:timeout]
52
54
  if timeout && timeout.to_s !~ /\A\d+\Z/
53
- raise TypeError.new "Timeout must be nil or a number (got: #{timeout})."
55
+ raise ActiveRecord::StatementInvalid.new(
56
+ "TypeError: Timeout must be nil or a number (got: #{timeout}).",
57
+ connection_pool: ActiveRecord::ConnectionAdapters::NullPool.new
58
+ )
54
59
  end
55
60
 
56
61
  options = config[:properties]
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SQLite3
4
+ # defines methods to de generate pragma statements
5
+ module Pragmas
6
+ class << self
7
+ # The enumeration of valid synchronous modes.
8
+ SYNCHRONOUS_MODES = [["full", 2], ["normal", 1], ["off", 0]].freeze
9
+
10
+ # The enumeration of valid temp store modes.
11
+ TEMP_STORE_MODES = [["default", 0], ["file", 1], ["memory", 2]].freeze
12
+
13
+ # The enumeration of valid auto vacuum modes.
14
+ AUTO_VACUUM_MODES = [["none", 0], ["full", 1], ["incremental", 2]].freeze
15
+
16
+ # The list of valid journaling modes.
17
+ JOURNAL_MODES = [["delete"], ["truncate"], ["persist"], ["memory"], ["wal"], ["off"]].freeze
18
+
19
+ # The list of valid locking modes.
20
+ LOCKING_MODES = [["normal"], ["exclusive"]].freeze
21
+
22
+ # The list of valid encodings.
23
+ ENCODINGS = [["utf-8"], ["utf-16"], ["utf-16le"], ["utf-16be"]].freeze
24
+
25
+ # The list of valid WAL checkpoints.
26
+ WAL_CHECKPOINTS = [["passive"], ["full"], ["restart"], ["truncate"]].freeze
27
+
28
+ # Enforce foreign key constraints
29
+ # https://www.sqlite.org/pragma.html#pragma_foreign_keys
30
+ # https://www.sqlite.org/foreignkeys.html
31
+ def foreign_keys(value)
32
+ gen_boolean_pragma(:foreign_keys, value)
33
+ end
34
+
35
+ # Journal mode WAL allows for greater concurrency (many readers + one writer)
36
+ # https://www.sqlite.org/pragma.html#pragma_journal_mode
37
+ def journal_mode(value)
38
+ gen_enum_pragma(:journal_mode, value, JOURNAL_MODES)
39
+ end
40
+
41
+ # Set more relaxed level of database durability
42
+ # 2 = "FULL" (sync on every write), 1 = "NORMAL" (sync every 1000 written pages) and 0 = "NONE"
43
+ # https://www.sqlite.org/pragma.html#pragma_synchronous
44
+ def synchronous(value)
45
+ gen_enum_pragma(:synchronous, value, SYNCHRONOUS_MODES)
46
+ end
47
+
48
+ def temp_store(value)
49
+ gen_enum_pragma(:temp_store, value, TEMP_STORE_MODES)
50
+ end
51
+
52
+ # Set the global memory map so all processes can share some data
53
+ # https://www.sqlite.org/pragma.html#pragma_mmap_size
54
+ # https://www.sqlite.org/mmap.html
55
+ def mmap_size(value)
56
+ "PRAGMA mmap_size = #{value.to_i}"
57
+ end
58
+
59
+ # Impose a limit on the WAL file to prevent unlimited growth
60
+ # https://www.sqlite.org/pragma.html#pragma_journal_size_limit
61
+ def journal_size_limit(value)
62
+ "PRAGMA journal_size_limit = #{value.to_i}"
63
+ end
64
+
65
+ # Set the local connection cache to 2000 pages
66
+ # https://www.sqlite.org/pragma.html#pragma_cache_size
67
+ def cache_size(value)
68
+ "PRAGMA cache_size = #{value.to_i}"
69
+ end
70
+
71
+ private
72
+
73
+ def gen_boolean_pragma(name, mode)
74
+ case mode
75
+ when String
76
+ case mode.downcase
77
+ when "on", "yes", "true", "y", "t" then mode = "'ON'"
78
+ when "off", "no", "false", "n", "f" then mode = "'OFF'"
79
+ else
80
+ raise ActiveRecord::JDBCError, "unrecognized pragma parameter #{mode.inspect}"
81
+ end
82
+ when true, 1
83
+ mode = "ON"
84
+ when false, 0, nil
85
+ mode = "OFF"
86
+ else
87
+ raise ActiveRecord::JDBCError, "unrecognized pragma parameter #{mode.inspect}"
88
+ end
89
+
90
+ "PRAGMA #{name} = #{mode}"
91
+ end
92
+
93
+ def gen_enum_pragma(name, mode, enums)
94
+ match = enums.find { |p| p.find { |i| i.to_s.downcase == mode.to_s.downcase } }
95
+
96
+ unless match
97
+ # Unknown pragma value
98
+ raise ActiveRecord::JDBCError, "unrecognized #{name} #{mode.inspect}"
99
+ end
100
+
101
+ "PRAGMA #{name} = '#{match.first.upcase}'"
102
+ end
103
+ end
104
+ end
105
+ end
@@ -1,3 +1,3 @@
1
1
  require 'arjdbc'
2
2
  require 'arjdbc/sqlite3/adapter'
3
- require 'arjdbc/sqlite3/connection_methods'
3
+ # require 'arjdbc/sqlite3/connection_methods'
@@ -1,3 +1,3 @@
1
1
  module ArJdbc
2
- VERSION = '70.2'
2
+ VERSION = '72.0'
3
3
  end
data/lib/arjdbc.rb CHANGED
@@ -12,8 +12,20 @@ if defined?(JRUBY_VERSION)
12
12
  rescue LoadError => e
13
13
  warn "activerecord-jdbc-adapter failed to load railtie: #{e.inspect}"
14
14
  end if defined?(Rails) && ActiveRecord::VERSION::MAJOR >= 3
15
+
16
+ ActiveSupport.on_load(:active_record) do
17
+ ActiveRecord::ConnectionAdapters.register(
18
+ "sqlite3", "ActiveRecord::ConnectionAdapters::SQLite3Adapter", "arjdbc/sqlite3/adapter"
19
+ )
20
+ ActiveRecord::ConnectionAdapters.register(
21
+ "postgresql", "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter", "arjdbc/postgresql/adapter"
22
+ )
23
+ ActiveRecord::ConnectionAdapters.register(
24
+ "mysql2", "ActiveRecord::ConnectionAdapters::Mysql2Adapter", "arjdbc/mysql/adapter"
25
+ )
26
+ end
15
27
  else
16
28
  warn "activerecord-jdbc-adapter is for use with JRuby only"
17
29
  end
18
30
 
19
- require 'arjdbc/version'
31
+ require 'arjdbc/version'
data/rakelib/02-test.rake CHANGED
@@ -36,11 +36,11 @@ 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'
43
- test_task.options = '--use-color=t'
43
+ test_task.options = '--use-color=t --progress-style=mark'
44
44
  test_task.verbose = true if $VERBOSE
45
45
  yield(test_task) if block_given?
46
46
  end
data/rakelib/rails.rake CHANGED
@@ -34,6 +34,7 @@ namespace :rails do
34
34
  File.join(root_dir, 'lib'),
35
35
  File.join(root_dir, driver, 'lib'),
36
36
  File.join(root_dir, 'test/rails'),
37
+ File.join(root_dir, 'jdbc-sqlite3', 'lib'), # Added for connection management tests which hardcode sqlite3
37
38
  ar_test_dir
38
39
  ]
39
40
 
@@ -51,6 +52,7 @@ namespace :rails do
51
52
  ruby_opts_string += " -C \"#{ar_path}\""
52
53
  ruby_opts_string += " -rbundler/setup"
53
54
  ruby_opts_string += " -rminitest -rminitest/excludes" unless ENV['NO_EXCLUDES'].eql?('true')
55
+ ruby_opts_string += " -rmonkey_patches"
54
56
  file_list = ENV["TEST"] ? FileList[ ENV["TEST"].split(',') ] : test_files_finder.call
55
57
  file_list_string = file_list.map { |fn| "\"#{fn}\"" }.join(' ')
56
58
  # test_loader_code = "-e \"ARGV.each{|f| require f}\"" # :direct
@@ -126,6 +126,7 @@ public class RubyJdbcConnection extends RubyObject {
126
126
  private IRubyObject adapter; // the AbstractAdapter instance we belong to
127
127
  private volatile boolean connected = true;
128
128
  private RubyClass attributeClass;
129
+ private RubyClass timeZoneClass;
129
130
 
130
131
  private boolean lazy = false; // final once set on initialize
131
132
  private boolean jndi; // final once set on initialize
@@ -135,6 +136,7 @@ public class RubyJdbcConnection extends RubyObject {
135
136
  protected RubyJdbcConnection(Ruby runtime, RubyClass metaClass) {
136
137
  super(runtime, metaClass);
137
138
  attributeClass = runtime.getModule("ActiveModel").getClass("Attribute");
139
+ timeZoneClass = runtime.getModule("ActiveSupport").getClass("TimeWithZone");
138
140
  }
139
141
 
140
142
  private static final ObjectAllocator ALLOCATOR = new ObjectAllocator() {
@@ -793,7 +795,8 @@ public class RubyJdbcConnection extends RubyObject {
793
795
  // Unfortunately the result set gets closed when getMoreResults()
794
796
  // is called, so we have to process the result sets as we get them
795
797
  // this shouldn't be an issue in most cases since we're only getting 1 result set anyways
796
- result = mapExecuteResult(context, connection, resultSet);
798
+ //result = mapExecuteResult(context, connection, resultSet);
799
+ result = mapToRawResult(context, connection, resultSet, false);
797
800
  resultSet.close();
798
801
  } else {
799
802
  result = context.runtime.newFixnum(updateCount);
@@ -2440,6 +2443,9 @@ public class RubyJdbcConnection extends RubyObject {
2440
2443
  if (attributeClass.isInstance(attribute)) {
2441
2444
  type = jdbcTypeForAttribute(context, attribute);
2442
2445
  value = valueForDatabase(context, attribute);
2446
+ } else if (timeZoneClass.isInstance(attribute)) {
2447
+ type = jdbcTypeFor("timestamp");
2448
+ value = attribute;
2443
2449
  } else {
2444
2450
  type = jdbcTypeForPrimitiveAttribute(context, attribute);
2445
2451
  value = attribute;
@@ -2726,8 +2732,9 @@ public class RubyJdbcConnection extends RubyObject {
2726
2732
  statement.setDouble(index, ((RubyNumeric) value).getDoubleValue());
2727
2733
  }
2728
2734
  else { // e.g. `BigDecimal '42.00000000000000000001'`
2735
+ Ruby runtime = context.runtime;
2729
2736
  statement.setBigDecimal(index,
2730
- RubyBigDecimal.newInstance(context, context.runtime.getModule("BigDecimal"), value, RubyFixnum.newFixnum(context.runtime, Integer.MAX_VALUE)).getValue());
2737
+ RubyBigDecimal.newInstance(context, runtime.getModule("BigDecimal"), value, RubyFixnum.zero(runtime)).getValue());
2731
2738
  }
2732
2739
  }
2733
2740
 
@@ -74,11 +74,7 @@ public class MySQLRubyJdbcConnection extends RubyJdbcConnection {
74
74
  return createMySQLJdbcConnectionClass(runtime, jdbcConnection);
75
75
  }
76
76
 
77
- protected static final ObjectAllocator ALLOCATOR = new ObjectAllocator() {
78
- public IRubyObject allocate(Ruby runtime, RubyClass klass) {
79
- return new MySQLRubyJdbcConnection(runtime, klass);
80
- }
81
- };
77
+ protected static final ObjectAllocator ALLOCATOR = MySQLRubyJdbcConnection::new;
82
78
 
83
79
  @JRubyMethod
84
80
  public IRubyObject query(final ThreadContext context, final IRubyObject sql) throws SQLException {
@@ -119,6 +115,17 @@ public class MySQLRubyJdbcConnection extends RubyJdbcConnection {
119
115
  return driverWrapper;
120
116
  }
121
117
 
118
+ @JRubyMethod(name = "ping")
119
+ public RubyBoolean db_ping(final ThreadContext context) {
120
+ final Connection connection = getConnection(true);
121
+ if (connection == null) return context.fals;
122
+
123
+ // NOTE: It seems only `connection.isValid(aliveTimeout)` is needed
124
+ // for JDBC 4.0 and up. https://jira.mariadb.org/browse/CONJ-51
125
+
126
+ return context.runtime.newBoolean(isConnectionValid(context, connection));
127
+ }
128
+
122
129
  private static transient Class MYSQL_CONNECTION;
123
130
  private static transient Boolean MYSQL_CONNECTION_FOUND;
124
131
 
@@ -473,7 +473,10 @@ public class SQLite3RubyJdbcConnection extends RubyJdbcConnection {
473
473
  // Assume we will only call this with an array.
474
474
  final RubyArray statements = (RubyArray) statementsArg;
475
475
  return withConnection(context, connection -> {
476
+ final Ruby runtime = context.runtime;
477
+
476
478
  Statement statement = null;
479
+
477
480
  try {
478
481
  statement = createStatement(context, connection);
479
482
 
@@ -481,8 +484,15 @@ public class SQLite3RubyJdbcConnection extends RubyJdbcConnection {
481
484
  for (int i = 0; i < length; i++) {
482
485
  statement.addBatch(sqlString(statements.eltOk(i)));
483
486
  }
484
- statement.executeBatch();
485
- return context.nil;
487
+
488
+ int[] rows = statement.executeBatch();
489
+
490
+ RubyArray rowsAffected = runtime.newArray();
491
+
492
+ for (int i = 0; i < rows.length; i++) {
493
+ rowsAffected.append(runtime.newFixnum(rows[i]));
494
+ }
495
+ return rowsAffected;
486
496
  } catch (final SQLException e) {
487
497
  // Generate list semicolon list of statements which should match AR error formatting more.
488
498
  debugErrorSQL(context, sqlString(statements.join(context, context.runtime.newString(";\n"))));
@@ -511,7 +521,8 @@ public class SQLite3RubyJdbcConnection extends RubyJdbcConnection {
511
521
  statement.setDouble(index, ((RubyNumeric) value).getDoubleValue());
512
522
  }
513
523
  else { // e.g. `BigDecimal '42.00000000000000000001'`
514
- RubyBigDecimal val = RubyBigDecimal.newInstance(context, context.runtime.getModule("BigDecimal"), value, RubyFixnum.newFixnum(context.runtime, Integer.MAX_VALUE));
524
+ Ruby runtime = context.runtime;
525
+ RubyBigDecimal val = RubyBigDecimal.newInstance(context, runtime.getModule("BigDecimal"), value, RubyFixnum.zero(runtime));
515
526
  statement.setString(index, val.getValue().toString());
516
527
  }
517
528
  }
metadata CHANGED
@@ -1,32 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-jdbc-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: '70.2'
4
+ version: '72.0'
5
5
  platform: java
6
6
  authors:
7
7
  - Nick Sieger, Ola Bini, Karol Bucek and JRuby contributors
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-04-09 00:00:00.000000000 Z
10
+ date: 2025-09-23 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
13
+ name: activerecord
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: '7.0'
19
- name: activerecord
18
+ version: 7.2.2
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - "~>"
25
24
  - !ruby/object:Gem::Version
26
- version: '7.0'
25
+ version: 7.2.2
27
26
  description: 'AR-JDBC is a database adapter for Rails'' ActiveRecord component designed
28
27
  to be used with JRuby built upon Java''s JDBC API for database access. Provides
29
- (ActiveRecord) built-in adapters: MySQL, PostgreSQL, SQLite3, and SQLServer.'
28
+ (ActiveRecord) built-in adapters: MySQL, PostgreSQL, and SQLite3.'
30
29
  email:
31
30
  - nick@nicksieger.com
32
31
  - ola.bini@gmail.com
@@ -69,6 +68,7 @@ files:
69
68
  - lib/arjdbc/abstract/connection_management.rb
70
69
  - lib/arjdbc/abstract/core.rb
71
70
  - lib/arjdbc/abstract/database_statements.rb
71
+ - lib/arjdbc/abstract/relation_query_attribute_monkey_patch.rb
72
72
  - lib/arjdbc/abstract/statement_cache.rb
73
73
  - lib/arjdbc/abstract/transaction_support.rb
74
74
  - lib/arjdbc/discover.rb
@@ -85,7 +85,6 @@ files:
85
85
  - lib/arjdbc/jdbc/adapter.rb
86
86
  - lib/arjdbc/jdbc/adapter_java.jar
87
87
  - lib/arjdbc/jdbc/adapter_require.rb
88
- - lib/arjdbc/jdbc/base_ext.rb
89
88
  - lib/arjdbc/jdbc/callbacks.rb
90
89
  - lib/arjdbc/jdbc/column.rb
91
90
  - lib/arjdbc/jdbc/connection.rb
@@ -100,22 +99,29 @@ files:
100
99
  - lib/arjdbc/jdbc/type_converter.rb
101
100
  - lib/arjdbc/mysql.rb
102
101
  - lib/arjdbc/mysql/adapter.rb
102
+ - lib/arjdbc/mysql/adapter_hash_config.rb
103
103
  - lib/arjdbc/mysql/connection_methods.rb
104
104
  - lib/arjdbc/oracle/adapter.rb
105
105
  - lib/arjdbc/postgresql.rb
106
106
  - lib/arjdbc/postgresql/adapter.rb
107
+ - lib/arjdbc/postgresql/adapter_hash_config.rb
107
108
  - lib/arjdbc/postgresql/base/array_decoder.rb
108
109
  - lib/arjdbc/postgresql/base/array_encoder.rb
109
110
  - lib/arjdbc/postgresql/base/array_parser.rb
110
111
  - lib/arjdbc/postgresql/base/pgconn.rb
111
112
  - lib/arjdbc/postgresql/column.rb
112
113
  - lib/arjdbc/postgresql/connection_methods.rb
114
+ - lib/arjdbc/postgresql/database_statements.rb
113
115
  - lib/arjdbc/postgresql/name.rb
114
116
  - lib/arjdbc/postgresql/oid_types.rb
117
+ - lib/arjdbc/postgresql/schema_statements.rb
115
118
  - lib/arjdbc/railtie.rb
116
119
  - lib/arjdbc/sqlite3.rb
117
120
  - lib/arjdbc/sqlite3/adapter.rb
121
+ - lib/arjdbc/sqlite3/adapter_hash_config.rb
122
+ - lib/arjdbc/sqlite3/column.rb
118
123
  - lib/arjdbc/sqlite3/connection_methods.rb
124
+ - lib/arjdbc/sqlite3/pragmas.rb
119
125
  - lib/arjdbc/tasks.rb
120
126
  - lib/arjdbc/tasks/database_tasks.rb
121
127
  - lib/arjdbc/tasks/databases.rake
@@ -181,7 +187,6 @@ homepage: https://github.com/jruby/activerecord-jdbc-adapter
181
187
  licenses:
182
188
  - BSD-2-Clause
183
189
  metadata: {}
184
- post_install_message:
185
190
  rdoc_options:
186
191
  - "--main"
187
192
  - README.md
@@ -198,8 +203,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
198
203
  - !ruby/object:Gem::Version
199
204
  version: '0'
200
205
  requirements: []
201
- rubygems_version: 3.3.26
202
- signing_key:
206
+ rubygems_version: 3.6.2
203
207
  specification_version: 4
204
208
  summary: JDBC adapter for ActiveRecord, for use within JRuby on Rails.
205
209
  test_files: []
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveRecord
4
- class << Base
5
- m = Module.new do
6
- # Allow adapters to provide their own {#reset_column_information} method.
7
- # @note This only affects the current thread's connection.
8
- def reset_column_information # :nodoc:
9
- # invoke the adapter-specific reset_column_information method
10
- connection.reset_column_information if connection.respond_to?(:reset_column_information)
11
- super
12
- end
13
- end
14
-
15
- self.prepend(m)
16
- end
17
- end