Skip to content

Commit

Permalink
Merge pull request #1156 from JesseChavez/rails_71_tests_one
Browse files Browse the repository at this point in the history
Changes to fix many failing tests for MySQL and PostgreSQL
  • Loading branch information
enebo authored Aug 6, 2024
2 parents 9cc3533 + cb0498d commit eab3685
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 79 deletions.
2 changes: 1 addition & 1 deletion lib/arjdbc/abstract/database_statements.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def convert_legacy_binds_to_attributes(binds)
end
end

def raw_execute(sql, name, async: false, allow_retry: false, materialize_transactions: false)
def raw_execute(sql, name, async: false, allow_retry: false, materialize_transactions: true)
log(sql, name, async: async) do
with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
conn.execute(sql)
Expand Down
25 changes: 19 additions & 6 deletions lib/arjdbc/mysql/adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,26 @@ def jdbc_connection_class
def new_client(conn_params, adapter_instance)
jdbc_connection_class.new(conn_params, adapter_instance)
end

private
def initialize_type_map(m)
super

m.register_type(%r(char)i) do |sql_type|
limit = extract_limit(sql_type)
Type.lookup(:string, adapter: :mysql2, limit: limit)
end

m.register_type %r(^enum)i, Type.lookup(:string, adapter: :mysql2)
m.register_type %r(^set)i, Type.lookup(:string, adapter: :mysql2)
end
end

# NOTE: redefines constant defined in abstract class however this time
# will use methods defined in the mysql abstract class and map properly
# mysql types.
TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }

def initialize(...)
super

Expand All @@ -58,11 +76,6 @@ def initialize(...)
@connection_parameters ||= @config
end

# NOTE: redefines constant defined in abstract class however this time
# will use methods defined in the mysql abstract class and map properly
# mysql types.
TYPE_MAP = Type::TypeMap.new.tap { |m| initialize_type_map(m) }

def self.database_exists?(config)
conn = ActiveRecord::Base.mysql2_connection(config)
conn && conn.really_valid?
Expand Down Expand Up @@ -186,7 +199,7 @@ def _quote(value)
#++

def active?
!(@raw_connection.nil? || @raw_connection.closed?) && @lock.synchronize { @raw_connection&.execute_query("/* ping */ SELECT 1") } || false
!(@raw_connection.nil? || @raw_connection.closed?) && @lock.synchronize { @raw_connection&.ping } || false
end

alias :reset! :reconnect!
Expand Down
36 changes: 24 additions & 12 deletions lib/arjdbc/postgresql/adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -301,14 +301,21 @@ def release_advisory_lock(lock_id) # :nodoc:
query_value("SELECT pg_advisory_unlock(#{lock_id})")
end

def enable_extension(name)
exec_query("CREATE EXTENSION IF NOT EXISTS \"#{name}\"").tap {
reload_type_map
}
def enable_extension(name, **)
schema, name = name.to_s.split(".").values_at(-2, -1)
sql = +"CREATE EXTENSION IF NOT EXISTS \"#{name}\""
sql << " SCHEMA #{schema}" if schema

internal_exec_query(sql).tap { reload_type_map }
end

def disable_extension(name)
exec_query("DROP EXTENSION IF EXISTS \"#{name}\" CASCADE").tap {
# Removes an extension from the database.
#
# [<tt>:force</tt>]
# Set to +:cascade+ to drop dependent objects as well.
# Defaults to false.
def disable_extension(name, force: false)
internal_exec_query("DROP EXTENSION IF EXISTS \"#{name}\"#{' CASCADE' if force == :cascade}").tap {
reload_type_map
}
end
Expand All @@ -322,7 +329,7 @@ def extension_enabled?(name)
end

def extensions
exec_query("SELECT extname FROM pg_extension", "SCHEMA").cast_values
internal_exec_query("SELECT extname FROM pg_extension", "SCHEMA", allow_retry: true, materialize_transactions: false).cast_values
end

# Returns a list of defined enum types, and their values.
Expand Down Expand Up @@ -474,11 +481,16 @@ def write_query?(sql) # :nodoc:
# end

def reset!
clear_cache!
reset_transaction
@connection.rollback # Have to deal with rollbacks differently than the AR adapter
@connection.execute 'DISCARD ALL'
@connection.configure_connection
@lock.synchronize do
return connect! unless @raw_connection

# Have to deal with rollbacks differently than the AR adapter
@raw_connection.rollback

@raw_connection.execute("DISCARD ALL")

super
end
end

def default_sequence_name(table_name, pk = "id") #:nodoc:
Expand Down
22 changes: 0 additions & 22 deletions lib/arjdbc/postgresql/oid_types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,28 +67,6 @@ def assert_valid_registration(oid, oid_type)

# @private
module OIDTypes

# @override
def enable_extension(name)
result = super(name)
@extensions = nil
reload_type_map
result
end

# @override
def disable_extension(name)
result = super(name)
@extensions = nil
reload_type_map
result
end

# @override
def extensions
@extensions ||= super
end

def get_oid_type(oid, fmod, column_name, sql_type = '') # :nodoc:
# Note: type_map is storing a bunch of oid type prefixed with a namespace even
# if they are not namespaced (e.g. ""."oidvector"). builtin types which are
Expand Down
44 changes: 6 additions & 38 deletions lib/arjdbc/sqlite3/adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -706,44 +706,6 @@ def configure_connection
# https://www.sqlite.org/pragma.html#pragma_cache_size
raw_execute("PRAGMA cache_size = 2000", "SCHEMA")
end

def configure_connection
if @config[:timeout] && @config[:retries]
raise ArgumentError, "Cannot specify both timeout and retries arguments"
elsif @config[:timeout]
# FIXME:
# @raw_connection.busy_timeout(self.class.type_cast_config_to_integer(@config[:timeout]))
elsif @config[:retries]
retries = self.class.type_cast_config_to_integer(@config[:retries])
raw_connection.busy_handler do |count|
count <= retries
end
end

# Enforce foreign key constraints
# https://www.sqlite.org/pragma.html#pragma_foreign_keys
# https://www.sqlite.org/foreignkeys.html
raw_execute("PRAGMA foreign_keys = ON", "SCHEMA")
unless @memory_database
# Journal mode WAL allows for greater concurrency (many readers + one writer)
# https://www.sqlite.org/pragma.html#pragma_journal_mode
raw_execute("PRAGMA journal_mode = WAL", "SCHEMA")
# Set more relaxed level of database durability
# 2 = "FULL" (sync on every write), 1 = "NORMAL" (sync every 1000 written pages) and 0 = "NONE"
# https://www.sqlite.org/pragma.html#pragma_synchronous
raw_execute("PRAGMA synchronous = NORMAL", "SCHEMA")
# Set the global memory map so all processes can share some data
# https://www.sqlite.org/pragma.html#pragma_mmap_size
# https://www.sqlite.org/mmap.html
raw_execute("PRAGMA mmap_size = #{128.megabytes}", "SCHEMA")
end
# Impose a limit on the WAL file to prevent unlimited growth
# https://www.sqlite.org/pragma.html#pragma_journal_size_limit
raw_execute("PRAGMA journal_size_limit = #{64.megabytes}", "SCHEMA")
# Set the local connection cache to 2000 pages
# https://www.sqlite.org/pragma.html#pragma_cache_size
raw_execute("PRAGMA cache_size = 2000", "SCHEMA")
end
end
# DIFFERENCE: A registration here is moved down to concrete class so we are not registering part of an adapter.
end
Expand Down Expand Up @@ -779,6 +741,12 @@ def initialize(...)

conn_params = @config.compact

# NOTE: strict strings is not supported by the jdbc driver yet,
# hope it will supported soon, I open a issue in their repository.
# https://github.com/xerial/sqlite-jdbc/issues/1153
#
# @config[:strict] = ConnectionAdapters::SQLite3Adapter.strict_strings_by_default unless @config.key?(:strict)

@connection_parameters = conn_params
end

Expand Down
11 changes: 11 additions & 0 deletions src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,17 @@ protected DriverWrapper newDriverWrapper(final ThreadContext context, final Stri
return driverWrapper;
}

@JRubyMethod(name = "ping")
public RubyBoolean db_ping(final ThreadContext context) {
final Connection connection = getConnection(true);
if (connection == null) return context.fals;

// NOTE: It seems only `connection.isValid(aliveTimeout)` is needed
// for JDBC 4.0 and up. https://jira.mariadb.org/browse/CONJ-51

return context.runtime.newBoolean(isConnectionValid(context, connection));
}

private static transient Class MYSQL_CONNECTION;
private static transient Boolean MYSQL_CONNECTION_FOUND;

Expand Down

0 comments on commit eab3685

Please sign in to comment.