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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +26 -26
- data/.gitignore +8 -0
- data/Gemfile +17 -4
- data/README.md +10 -5
- data/RUNNING_TESTS.md +36 -0
- data/activerecord-jdbc-adapter.gemspec +2 -2
- data/lib/arjdbc/abstract/connection_management.rb +25 -10
- data/lib/arjdbc/abstract/core.rb +15 -13
- data/lib/arjdbc/abstract/database_statements.rb +36 -36
- data/lib/arjdbc/abstract/relation_query_attribute_monkey_patch.rb +24 -0
- data/lib/arjdbc/abstract/statement_cache.rb +2 -7
- data/lib/arjdbc/abstract/transaction_support.rb +39 -22
- data/lib/arjdbc/jdbc/adapter.rb +0 -1
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/column.rb +0 -34
- data/lib/arjdbc/jdbc/connection_methods.rb +1 -1
- data/lib/arjdbc/mysql/adapter.rb +108 -32
- data/lib/arjdbc/mysql/adapter_hash_config.rb +159 -0
- data/lib/arjdbc/mysql.rb +1 -1
- data/lib/arjdbc/postgresql/adapter.rb +267 -114
- data/lib/arjdbc/postgresql/adapter_hash_config.rb +98 -0
- data/lib/arjdbc/postgresql/base/array_encoder.rb +3 -1
- data/lib/arjdbc/postgresql/database_statements.rb +20 -0
- data/lib/arjdbc/postgresql/oid_types.rb +10 -29
- data/lib/arjdbc/postgresql/schema_statements.rb +57 -0
- data/lib/arjdbc/postgresql.rb +1 -1
- data/lib/arjdbc/sqlite3/adapter.rb +343 -172
- data/lib/arjdbc/sqlite3/adapter_hash_config.rb +91 -0
- data/lib/arjdbc/sqlite3/column.rb +117 -0
- data/lib/arjdbc/sqlite3/connection_methods.rb +7 -2
- data/lib/arjdbc/sqlite3/pragmas.rb +105 -0
- data/lib/arjdbc/sqlite3.rb +1 -1
- data/lib/arjdbc/version.rb +1 -1
- data/lib/arjdbc.rb +13 -1
- data/rakelib/02-test.rake +2 -2
- data/rakelib/rails.rake +2 -0
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +9 -2
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +12 -5
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +14 -3
- metadata +15 -11
- 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
|
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
|
data/lib/arjdbc/sqlite3.rb
CHANGED
data/lib/arjdbc/version.rb
CHANGED
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.
|
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,
|
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
|
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
|
-
|
485
|
-
|
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
|
-
|
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: '
|
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:
|
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:
|
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:
|
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,
|
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.
|
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: []
|
data/lib/arjdbc/jdbc/base_ext.rb
DELETED
@@ -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
|