Skip to content

Commit 42a23bf

Browse files
authored
Merge pull request #1150 from JesseChavez/rails_71_support
Initial work to support Active Record 7.1 (Rails 7.1.x)
2 parents 3454cd0 + c77c239 commit 42a23bf

15 files changed

+121
-84
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ nbproject
1919
.project
2020
*.sqlite
2121
*.sqlite3
22+
*.sqlite3-shm
23+
*.sqlite3-wal
2224
*.derby
2325
derby.log
2426
test.hsqldb*
@@ -33,3 +35,7 @@ Gemfile.lock
3335
.settings
3436
activerecord-jdbc.iml
3537
lib/arjdbc/jdbc/adapter_java.jar
38+
.jrubyrc
39+
.rubocop.yml
40+
.solargraph.yml
41+
pik.sh

activerecord-jdbc-adapter.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Gem::Specification.new do |gem|
4141
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
4242
gem.test_files = gem.files.grep(%r{^test/})
4343

44-
gem.add_dependency 'activerecord', '~> 7.1.0'
44+
gem.add_dependency 'activerecord', '~> 7.1.3'
4545

4646
#gem.add_development_dependency 'test-unit', '2.5.4'
4747
#gem.add_development_dependency 'test-unit-context', '>= 0.3.0'

lib/arjdbc/abstract/connection_management.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,13 @@ def disconnect!
3636
# end
3737
# end
3838

39+
private
40+
3941
# DIFFERENCE: we delve into jdbc shared code and this does self.class.new_client.
4042
def connect
41-
@raw_connection = jdbc_connection_class(@config[:adapter_spec]).new(@config, self)
42-
@raw_connection.configure_connection
43+
@raw_connection = self.class.new_client(@connection_parameters, self)
44+
rescue ConnectionNotEstablished => ex
45+
raise ex.set_pool(@pool)
4346
end
4447

4548
def reconnect

lib/arjdbc/abstract/core.rb

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,17 @@
22

33
module ArJdbc
44
module Abstract
5-
65
# This is minimum amount of code needed from base JDBC Adapter class to make common adapters
76
# work. This replaces using jdbc/adapter as a base class for all adapters.
87
module Core
9-
10-
attr_reader :config
11-
12-
def initialize(config)
13-
@config = config
8+
def initialize(...)
9+
super
1410

1511
if self.class.equal? ActiveRecord::ConnectionAdapters::JdbcAdapter
1612
spec = @config.key?(:adapter_spec) ? @config[:adapter_spec] :
1713
( @config[:adapter_spec] = adapter_spec(@config) ) # due resolving visitor
1814
extend spec if spec
1915
end
20-
21-
super(config) # AbstractAdapter
2216
end
2317

2418
# Retrieve the raw `java.sql.Connection` object.

lib/arjdbc/abstract/database_statements.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def exec_insert(sql, name = nil, binds = NO_BINDS, pk = nil, sequence_name = nil
3333

3434
# It appears that at this point (AR 5.0) "prepare" should only ever be true
3535
# if prepared statements are enabled
36-
def internal_exec_query(sql, name = nil, binds = NO_BINDS, prepare: false, async: false)
36+
def internal_exec_query(sql, name = nil, binds = NO_BINDS, prepare: false, async: false, allow_retry: false, materialize_transactions: true)
3737
sql = transform_query(sql)
3838

3939
if preventing_writes? && write_query?(sql)

lib/arjdbc/abstract/statement_cache.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def initialize(*args) # (connection, logger, config)
2424

2525
# Only say we support the statement cache if we are using prepared statements
2626
# and have a max number of statements defined
27-
statement_limit = self.class.type_cast_config_to_integer(config[:statement_limit])
27+
statement_limit = self.class.type_cast_config_to_integer(@config[:statement_limit])
2828
@jdbc_statement_cache_enabled = prepared_statements && (statement_limit.nil? || statement_limit > 0)
2929

3030
@statements = StatementPool.new(statement_limit) # AR (5.0) expects this to be stored as @statements

lib/arjdbc/abstract/transaction_support.rb

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -107,16 +107,3 @@ def release_savepoint(name = current_savepoint_name)
107107
end
108108
end
109109
end
110-
111-
# patch to avoid the usage of WeakMap
112-
require 'active_record/connection_adapters/abstract/transaction'
113-
module ActiveRecord
114-
module ConnectionAdapters
115-
class Transaction
116-
def add_record(record, ensure_finalize = true)
117-
@records ||= []
118-
@records << record
119-
end
120-
end
121-
end
122-
end

lib/arjdbc/mysql/adapter.rb

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ module ConnectionAdapters
2323
class Mysql2Adapter < AbstractMysqlAdapter
2424
ADAPTER_NAME = 'Mysql2'
2525

26-
include Jdbc::ConnectionPoolCallbacks
26+
# include Jdbc::ConnectionPoolCallbacks
2727

2828
include ArJdbc::Abstract::ConnectionManagement
2929
include ArJdbc::Abstract::DatabaseStatements
@@ -33,6 +33,16 @@ class Mysql2Adapter < AbstractMysqlAdapter
3333

3434
include ArJdbc::MySQL
3535

36+
class << self
37+
def jdbc_connection_class
38+
::ActiveRecord::ConnectionAdapters::MySQLJdbcConnection
39+
end
40+
41+
def new_client(conn_params, adapter_instance)
42+
jdbc_connection_class.new(conn_params, adapter_instance)
43+
end
44+
end
45+
3646
def initialize(...)
3747
super
3848

@@ -221,14 +231,19 @@ def get_full_version
221231
@full_version ||= any_raw_connection.full_version
222232
end
223233

224-
def jdbc_connection_class(spec)
225-
::ActiveRecord::ConnectionAdapters::MySQLJdbcConnection
226-
end
227-
228234
def jdbc_column_class
229235
::ActiveRecord::ConnectionAdapters::MySQL::Column
230236
end
231237

238+
def translate_exception(exception, message:, sql:, binds:)
239+
case message
240+
when /Table .* doesn't exist/i
241+
StatementInvalid.new(message, sql: sql, binds: binds, connection_pool: @pool)
242+
else
243+
super
244+
end
245+
end
246+
232247
# defined in MySQL::DatabaseStatements which is not included
233248
def default_insert_value(column)
234249
super unless column.auto_increment?

lib/arjdbc/postgresql/adapter.rb

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,6 @@ module PostgreSQL
3535
# @private
3636
Type = ::ActiveRecord::Type
3737

38-
# @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_connection_class
39-
def self.jdbc_connection_class
40-
::ActiveRecord::ConnectionAdapters::PostgreSQLJdbcConnection
41-
end
42-
4338
# @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_column_class
4439
def jdbc_column_class; ::ActiveRecord::ConnectionAdapters::PostgreSQLColumn end
4540

@@ -52,8 +47,8 @@ def adapter_name
5247
def redshift?
5348
# SELECT version() :
5449
# PostgreSQL 8.0.2 on i686-pc-linux-gnu, compiled by GCC gcc (GCC) 3.4.2 20041017 (Red Hat 3.4.2-6.fc3), Redshift 1.0.647
55-
if ( redshift = config[:redshift] ).nil?
56-
redshift = !! (@connection.database_product || '').index('Redshift')
50+
if (redshift = @config[:redshift]).nil?
51+
redshift = !! (valid_raw_connection.database_product || '').index('Redshift')
5752
end
5853
redshift
5954
end
@@ -73,8 +68,8 @@ def configure_connection
7368
# see http://jdbc.postgresql.org/documentation/91/connect.html
7469
# self.set_client_encoding(encoding)
7570
#end
76-
self.client_min_messages = config[:min_messages] || 'warning'
77-
self.schema_search_path = config[:schema_search_path] || config[:schema_order]
71+
self.client_min_messages = @config[:min_messages] || 'warning'
72+
self.schema_search_path = @config[:schema_search_path] || @config[:schema_order]
7873

7974
# Use standard-conforming strings if available so we don't have to do the E'...' dance.
8075
set_standard_conforming_strings
@@ -93,14 +88,17 @@ def configure_connection
9388

9489
# SET statements from :variables config hash
9590
# http://www.postgresql.org/docs/8.3/static/sql-set.html
96-
(config[:variables] || {}).map do |k, v|
91+
(@config[:variables] || {}).map do |k, v|
9792
if v == ':default' || v == :default
9893
# Sets the value to the global or compile default
9994
execute("SET SESSION #{k} TO DEFAULT", 'SCHEMA')
10095
elsif ! v.nil?
10196
execute("SET SESSION #{k} TO #{quote(v)}", 'SCHEMA')
10297
end
10398
end
99+
100+
@type_map = Type::HashLookupTypeMap.new
101+
initialize_type_map
104102
end
105103

106104
# @private
@@ -370,7 +368,7 @@ def use_insert_returning?
370368

371369
def get_database_version # :nodoc:
372370
begin
373-
version = @connection.database_product
371+
version = valid_raw_connection.database_product
374372
if match = version.match(/([\d\.]*\d).*?/)
375373
version = match[1].split('.').map(&:to_i)
376374
# PostgreSQL version representation does not have more than 4 digits
@@ -426,8 +424,7 @@ def check_version # :nodoc:
426424
end
427425
end
428426

429-
430-
def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
427+
def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil, returning: nil) # :nodoc:
431428
val = super
432429
if !use_insert_returning? && pk
433430
unless sequence_name
@@ -464,11 +461,11 @@ def write_query?(sql) # :nodoc:
464461
# since apparently calling close on the statement object
465462
# doesn't always free the server resources and calling
466463
# 'DISCARD ALL' fails if we are inside a transaction
467-
def clear_cache!
468-
super
469-
# Make sure all query plans are *really* gone
470-
@connection.execute 'DEALLOCATE ALL' if active?
471-
end
464+
# def clear_cache!
465+
# super
466+
# # Make sure all query plans are *really* gone
467+
# @connection.execute 'DEALLOCATE ALL' if active?
468+
# end
472469

473470
def reset!
474471
clear_cache!
@@ -660,6 +657,8 @@ def translate_exception(exception, message:, sql:, binds:)
660657
::ActiveRecord::LockWaitTimeout.new(message, sql: sql, binds: binds)
661658
when /canceling statement/ # This needs to come after lock timeout because the lock timeout message also contains "canceling statement"
662659
::ActiveRecord::QueryCanceled.new(message, sql: sql, binds: binds)
660+
when /relation "animals" does not exist/i
661+
::ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds, connection_pool: @pool)
663662
else
664663
super
665664
end
@@ -742,7 +741,7 @@ class PostgreSQLAdapter < AbstractAdapter
742741
include ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaStatements
743742
include ActiveRecord::ConnectionAdapters::PostgreSQL::Quoting
744743

745-
include Jdbc::ConnectionPoolCallbacks
744+
# include Jdbc::ConnectionPoolCallbacks
746745

747746
include ArJdbc::Abstract::Core
748747
include ArJdbc::Abstract::ConnectionManagement
@@ -761,16 +760,27 @@ class PostgreSQLAdapter < AbstractAdapter
761760
# AR expects OID to be available on the adapter
762761
OID = ActiveRecord::ConnectionAdapters::PostgreSQL::OID
763762

764-
def initialize(connection, logger = nil, connection_parameters = nil, config = {})
763+
class << self
764+
def jdbc_connection_class
765+
::ActiveRecord::ConnectionAdapters::PostgreSQLJdbcConnection
766+
end
767+
768+
def new_client(conn_params, adapter_instance)
769+
jdbc_connection_class.new(conn_params, adapter_instance)
770+
end
771+
end
772+
773+
def initialize(...)
774+
super
775+
776+
conn_params = @config.compact
777+
778+
@connection_parameters = conn_params
779+
765780
# @local_tz is initialized as nil to avoid warnings when connect tries to use it
766781
@local_tz = nil
767782
@max_identifier_length = nil
768783

769-
super(connection, logger, config) # configure_connection happens in super
770-
771-
@type_map = Type::HashLookupTypeMap.new
772-
initialize_type_map
773-
774784
@use_insert_returning = @config.key?(:insert_returning) ?
775785
self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
776786
end
@@ -793,10 +803,6 @@ def self.database_exists?(config)
793803
public :sql_for_insert
794804
alias :postgresql_version :database_version
795805

796-
def jdbc_connection_class(spec)
797-
::ArJdbc::PostgreSQL.jdbc_connection_class
798-
end
799-
800806
private
801807

802808
FEATURE_NOT_SUPPORTED = "0A000" # :nodoc:
@@ -829,8 +835,10 @@ def exec_no_cache(sql, name, binds, async: false)
829835

830836
type_casted_binds = type_casted_binds(binds)
831837
log(sql, name, binds, type_casted_binds, async: async) do
832-
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
833-
@connection.exec_params(sql, type_casted_binds)
838+
with_raw_connection do |conn|
839+
result = conn.exec_params(sql, type_casted_binds)
840+
verified!
841+
result
834842
end
835843
end
836844
end

lib/arjdbc/sqlite3/adapter.rb

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,14 @@ class SQLite3Adapter < AbstractAdapter
774774
# config.active_record.sqlite3_adapter_strict_strings_by_default = true
775775
class_attribute :strict_strings_by_default, default: false # Does not actually do anything right now
776776

777+
def initialize(...)
778+
super
779+
780+
conn_params = @config.compact
781+
782+
@connection_parameters = conn_params
783+
end
784+
777785
def self.represent_boolean_as_integer=(value) # :nodoc:
778786
if value == false
779787
raise "`.represent_boolean_as_integer=` is now always true, so make sure your application can work with it and remove this settings."
@@ -817,15 +825,6 @@ def jdbc_column_class
817825
::ActiveRecord::ConnectionAdapters::SQLite3Column
818826
end
819827

820-
def jdbc_connection_class(spec)
821-
self.class.jdbc_connection_class
822-
end
823-
824-
# @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_connection_class
825-
def self.jdbc_connection_class
826-
::ActiveRecord::ConnectionAdapters::SQLite3JdbcConnection
827-
end
828-
829828
# Note: This is not an override of ours but a moved line from AR Sqlite3Adapter to register ours vs our copied module (which would be their class).
830829
# ActiveSupport.run_load_hooks(:active_record_sqlite3adapter, SQLite3Adapter)
831830

@@ -843,6 +842,14 @@ def _limit
843842
::ActiveRecord::Type.register(:integer, SQLite3Integer, adapter: :sqlite3)
844843

845844
class << self
845+
def jdbc_connection_class
846+
::ActiveRecord::ConnectionAdapters::SQLite3JdbcConnection
847+
end
848+
849+
def new_client(conn_params, adapter_instance)
850+
jdbc_connection_class.new(conn_params, adapter_instance)
851+
end
852+
846853
def dbconsole(config, options = {})
847854
args = []
848855

rakelib/02-test.rake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def test_task_for(adapter, options = {})
4040
test_task.libs.push *FileList["activerecord-jdbc#{adapter}*/lib"]
4141
end
4242
test_task.libs << 'test'
43-
test_task.options = '--use-color=t'
43+
test_task.options = '--use-color=t --progress-style=mark'
4444
test_task.verbose = true if $VERBOSE
4545
yield(test_task) if block_given?
4646
end

0 commit comments

Comments
 (0)