diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb index 7628ef5537..7dd5169e43 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -20,6 +20,26 @@ module ActiveRecord end module ConnectionAdapters + module AbstractPool # :nodoc: + def get_schema_cache(connection) + @schema_cache ||= SchemaCache.new(connection) + @schema_cache.connection = connection + @schema_cache + end + + def set_schema_cache(cache) + @schema_cache = cache + end + end + + class NullPool # :nodoc: + include ConnectionAdapters::AbstractPool + + def initialize + @schema_cache = nil + end + end + # Connection pool base class for managing Active Record database # connections. # @@ -336,6 +356,7 @@ module ActiveRecord include MonitorMixin include QueryCache::ConnectionPoolConfiguration + include ConnectionAdapters::AbstractPool attr_accessor :automatic_reconnect, :checkout_timeout, :schema_cache attr_reader :spec, :connections, :size, :reaper @@ -837,7 +858,6 @@ module ActiveRecord def new_connection Base.send(spec.adapter_method, spec.config).tap do |conn| - conn.schema_cache = schema_cache.dup if schema_cache conn.check_version end end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index bf0bb84c93..57a8e7ad98 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -78,7 +78,7 @@ module ActiveRecord SIMPLE_INT = /\A\d+\z/ attr_accessor :pool - attr_reader :schema_cache, :visitor, :owner, :logger, :lock, :prepared_statements, :prevent_writes + attr_reader :visitor, :owner, :logger, :lock, :prepared_statements, :prevent_writes alias :in_use? :owner set_callback :checkin, :after, :enable_lazy_transactions! @@ -114,9 +114,8 @@ module ActiveRecord @instrumenter = ActiveSupport::Notifications.instrumenter @logger = logger @config = config - @pool = nil + @pool = ActiveRecord::ConnectionAdapters::NullPool.new @idle_since = Concurrent.monotonic_time - @schema_cache = SchemaCache.new self @quoted_column_names, @quoted_table_names = {}, {} @prevent_writes = false @visitor = arel_visitor @@ -206,9 +205,13 @@ module ActiveRecord @owner = Thread.current end + def schema_cache + @pool.get_schema_cache(self) + end + def schema_cache=(cache) cache.connection = self - @schema_cache = cache + @pool.set_schema_cache(cache) end # this method must only be called while holding connection pool's mutex @@ -487,6 +490,9 @@ module ActiveRecord # # Prevent @connection's finalizer from touching the socket, or # otherwise communicating with its server, when it is collected. + if schema_cache.connection == self + schema_cache.connection = nil + end end # Reset the state of this connection, directing the DBMS to clear diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb index 5b0335c22b..f1ee6a2bce 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb @@ -109,6 +109,7 @@ module ActiveRecord end def discard! # :nodoc: + super @connection.automatic_close = false @connection = nil end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 91318a0af1..738805a160 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -302,6 +302,7 @@ module ActiveRecord end def discard! # :nodoc: + super @connection.socket_io.reopen(IO::NULL) rescue nil @connection = nil end diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index a1d7c893bf..d5375390c7 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -134,7 +134,6 @@ end_error cache = YAML.load(File.read(filename)) if cache.version == current_version - connection.schema_cache = cache connection_pool.schema_cache = cache.dup else warn "Ignoring db/schema_cache.yml because it has expired. The current schema version is #{current_version}, but the one in the cache is #{cache.version}." diff --git a/activerecord/test/cases/connection_pool_test.rb b/activerecord/test/cases/connection_pool_test.rb index a15ad9a45b..82f5f45a4c 100644 --- a/activerecord/test/cases/connection_pool_test.rb +++ b/activerecord/test/cases/connection_pool_test.rb @@ -507,7 +507,6 @@ module ActiveRecord pool.schema_cache = schema_cache pool.with_connection do |conn| - assert_not_same pool.schema_cache, conn.schema_cache assert_equal pool.schema_cache.size, conn.schema_cache.size assert_same pool.schema_cache.columns(:posts), conn.schema_cache.columns(:posts) end