1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge pull request #38190 from seejohnrun/deprecate-primary-as-connection_specification_name

Deprecate "primary" as a connection_specification_name for ActiveRecord::Base
This commit is contained in:
Eileen M. Uchitelle 2020-01-09 13:41:11 -05:00 committed by GitHub
commit 4a477c0e4d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 97 additions and 42 deletions

View file

@ -1,3 +1,9 @@
* Deprecate "primary" as the connection_specification_name for ActiveRecord::Base
`"primary"` has been deprecated as the `connection_specification_name` for `ActiveRecord::Base` in favor of using `"ActiveRecord::Base"`. This change affects calls to `ActiveRecord::Base.connection_handler.retrieve_connection` and `ActiveRecord::Base.connection_handler.remove_connection`. If you're calling these methods with `"primary"`, please switch to `"ActiveRecord::Base"`.
*Eileen M. Uchitelle*, *John Crepezzi*
* Add `ActiveRecord::Validations::NumericalityValidator` with * Add `ActiveRecord::Validations::NumericalityValidator` with
support for casting floats using a database columns' precision value. support for casting floats using a database columns' precision value.

View file

@ -1043,7 +1043,11 @@ module ActiveRecord
pool_config = resolve_pool_config(config) pool_config = resolve_pool_config(config)
db_config = pool_config.db_config db_config = pool_config.db_config
remove_connection(pool_config.connection_specification_name, pool_key) # Protects the connection named `ActiveRecord::Base` from being removed
# if the user calls `establish_connection :primary`.
if owner_to_pool_manager.key?(pool_config.connection_specification_name)
remove_connection(pool_config.connection_specification_name, pool_key)
end
message_bus = ActiveSupport::Notifications.instrumenter message_bus = ActiveSupport::Notifications.instrumenter
payload = {} payload = {}
@ -1053,7 +1057,7 @@ module ActiveRecord
end end
owner_to_pool_manager[pool_config.connection_specification_name] ||= PoolManager.new owner_to_pool_manager[pool_config.connection_specification_name] ||= PoolManager.new
pool_manager = owner_to_pool_manager[pool_config.connection_specification_name] pool_manager = get_pool_manager(pool_config.connection_specification_name)
pool_manager.set_pool_config(pool_key, pool_config) pool_manager.set_pool_config(pool_key, pool_config)
message_bus.instrument("!connection.active_record", payload) do message_bus.instrument("!connection.active_record", payload) do
@ -1102,9 +1106,9 @@ module ActiveRecord
unless pool unless pool
# multiple database application # multiple database application
if ActiveRecord::Base.connection_handler != ActiveRecord::Base.default_connection_handler if ActiveRecord::Base.connection_handler != ActiveRecord::Base.default_connection_handler
raise ConnectionNotEstablished, "No connection pool with '#{spec_name}' found for the '#{ActiveRecord::Base.current_role}' role." raise ConnectionNotEstablished, "No connection pool for '#{spec_name}' found for the '#{ActiveRecord::Base.current_role}' role."
else else
raise ConnectionNotEstablished, "No connection pool with '#{spec_name}' found." raise ConnectionNotEstablished, "No connection pool for '#{spec_name}' found."
end end
end end
@ -1122,8 +1126,8 @@ module ActiveRecord
# connection and the defined connection (if they exist). The result # connection and the defined connection (if they exist). The result
# can be used as an argument for #establish_connection, for easily # can be used as an argument for #establish_connection, for easily
# re-establishing the connection. # re-establishing the connection.
def remove_connection(spec_name, pool_key = :default) def remove_connection(owner, pool_key = :default)
if pool_manager = owner_to_pool_manager[spec_name] if pool_manager = get_pool_manager(owner)
pool_config = pool_manager.remove_pool_config(pool_key) pool_config = pool_manager.remove_pool_config(pool_key)
if pool_config if pool_config
@ -1136,14 +1140,30 @@ module ActiveRecord
# Retrieving the connection pool happens a lot, so we cache it in @owner_to_pool_manager. # Retrieving the connection pool happens a lot, so we cache it in @owner_to_pool_manager.
# This makes retrieving the connection pool O(1) once the process is warm. # This makes retrieving the connection pool O(1) once the process is warm.
# When a connection is established or removed, we invalidate the cache. # When a connection is established or removed, we invalidate the cache.
def retrieve_connection_pool(spec_name, pool_key = :default) def retrieve_connection_pool(owner, pool_key = :default)
pool_config = owner_to_pool_manager[spec_name]&.get_pool_config(pool_key) pool_config = get_pool_manager(owner)&.get_pool_config(pool_key)
pool_config&.pool pool_config&.pool
end end
private private
attr_reader :owner_to_pool_manager attr_reader :owner_to_pool_manager
# Returns the pool manager for an owner.
#
# Using `"primary"` to look up the pool manager for `ActiveRecord::Base` is
# deprecated in favor of looking it up by `"ActiveRecord::Base"`.
#
# During the deprecation period, if `"primary"` is passed, the pool manager
# for `ActiveRecord::Base` will still be returned.
def get_pool_manager(owner)
return owner_to_pool_manager[owner] if owner_to_pool_manager.key?(owner)
if owner == "primary"
ActiveSupport::Deprecation.warn("Using `\"primary\"` as a `connection_specification_name` is deprecated and will be removed in Rails 6.2.0. Please use `ActiveRecord::Base`.")
owner_to_pool_manager[Base.name]
end
end
# Returns an instance of PoolConfig for a given adapter. # Returns an instance of PoolConfig for a given adapter.
# Accepts a hash one layer deep that contains all connection information. # Accepts a hash one layer deep that contains all connection information.
# #
@ -1186,7 +1206,7 @@ module ActiveRecord
raise AdapterNotFound, "database configuration specifies nonexistent #{db_config.adapter} adapter" raise AdapterNotFound, "database configuration specifies nonexistent #{db_config.adapter} adapter"
end end
pool_name = db_config.owner_name || "primary" pool_name = db_config.owner_name || Base.name
db_config.owner_name = nil db_config.owner_name = nil
ConnectionAdapters::PoolConfig.new(pool_name, db_config) ConnectionAdapters::PoolConfig.new(pool_name, db_config)
end end

View file

@ -181,7 +181,7 @@ module ActiveRecord
# Return the specification name from the current class or its parent. # Return the specification name from the current class or its parent.
def connection_specification_name def connection_specification_name
if !defined?(@connection_specification_name) || @connection_specification_name.nil? if !defined?(@connection_specification_name) || @connection_specification_name.nil?
return self == Base ? "primary" : superclass.connection_specification_name return self == Base ? Base.name : superclass.connection_specification_name
end end
@connection_specification_name @connection_specification_name
end end
@ -249,7 +249,7 @@ module ActiveRecord
raise "Anonymous class is not allowed." unless name raise "Anonymous class is not allowed." unless name
config_or_env ||= DEFAULT_ENV.call.to_sym config_or_env ||= DEFAULT_ENV.call.to_sym
pool_name = primary_class? ? "primary" : name pool_name = primary_class? ? Base.name : name
self.connection_specification_name = pool_name self.connection_specification_name = pool_name
db_config = Base.configurations.resolve(config_or_env, pool_name) db_config = Base.configurations.resolve(config_or_env, pool_name)

View file

@ -12,7 +12,7 @@ module ActiveRecord
def setup def setup
@handler = ConnectionHandler.new @handler = ConnectionHandler.new
@spec_name = "primary" @owner_name = "ActiveRecord::Base"
@pool = @handler.establish_connection(ActiveRecord::Base.configurations["arunit"]) @pool = @handler.establish_connection(ActiveRecord::Base.configurations["arunit"])
end end
@ -75,6 +75,35 @@ module ActiveRecord
end end
unless in_memory_db? unless in_memory_db?
def test_establish_connection_with_primary_works_without_deprecation
old_config = ActiveRecord::Base.configurations
config = { "primary" => { "adapter" => "sqlite3", "database" => "db/primary.sqlite3" } }
ActiveRecord::Base.configurations = config
@handler.establish_connection(:primary)
assert_not_deprecated do
@handler.retrieve_connection("primary")
@handler.remove_connection("primary")
end
ensure
ActiveRecord::Base.configurations = old_config
end
def test_retrieve_connection_shows_primary_deprecation_warning_when_established_on_active_record_base
old_config = ActiveRecord::Base.configurations
config = { "primary" => { "adapter" => "sqlite3", "database" => "db/primary.sqlite3" } }
ActiveRecord::Base.configurations = config
ActiveRecord::Base.establish_connection(:primary)
assert_deprecated { @handler.retrieve_connection("primary") }
assert_deprecated { @handler.remove_connection("primary") }
ensure
ActiveRecord::Base.configurations = old_config
ActiveRecord::Base.establish_connection(:arunit)
end
def test_establish_connection_using_3_level_config_defaults_to_default_env_primary_db def test_establish_connection_using_3_level_config_defaults_to_default_env_primary_db
previous_env, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], "default_env" previous_env, ENV["RAILS_ENV"] = ENV["RAILS_ENV"], "default_env"
@ -182,19 +211,19 @@ module ActiveRecord
end end
def test_retrieve_connection def test_retrieve_connection
assert @handler.retrieve_connection(@spec_name) assert @handler.retrieve_connection(@owner_name)
end end
def test_active_connections? def test_active_connections?
assert_not_predicate @handler, :active_connections? assert_not_predicate @handler, :active_connections?
assert @handler.retrieve_connection(@spec_name) assert @handler.retrieve_connection(@owner_name)
assert_predicate @handler, :active_connections? assert_predicate @handler, :active_connections?
@handler.clear_active_connections! @handler.clear_active_connections!
assert_not_predicate @handler, :active_connections? assert_not_predicate @handler, :active_connections?
end end
def test_retrieve_connection_pool def test_retrieve_connection_pool
assert_not_nil @handler.retrieve_connection_pool(@spec_name) assert_not_nil @handler.retrieve_connection_pool(@owner_name)
end end
def test_retrieve_connection_pool_with_invalid_id def test_retrieve_connection_pool_with_invalid_id
@ -236,8 +265,8 @@ module ActiveRecord
assert_equal klassB.connection_specification_name, klassA.connection_specification_name assert_equal klassB.connection_specification_name, klassA.connection_specification_name
assert_equal klassC.connection_specification_name, klassA.connection_specification_name assert_equal klassC.connection_specification_name, klassA.connection_specification_name
assert_equal "primary", klassA.connection_specification_name assert_equal "ActiveRecord::Base", klassA.connection_specification_name
assert_equal "primary", klassC.connection_specification_name assert_equal "ActiveRecord::Base", klassC.connection_specification_name
klassA.connection_specification_name = "readonly" klassA.connection_specification_name = "readonly"
assert_equal "readonly", klassB.connection_specification_name assert_equal "readonly", klassB.connection_specification_name
@ -246,7 +275,7 @@ module ActiveRecord
assert_equal "readonly", klassC.connection_specification_name assert_equal "readonly", klassC.connection_specification_name
ensure ensure
Object.send :remove_const, :ApplicationRecord Object.send :remove_const, :ApplicationRecord
ActiveRecord::Base.connection_specification_name = "primary" ActiveRecord::Base.connection_specification_name = "ActiveRecord::Base"
end end
def test_remove_connection_should_not_remove_parent def test_remove_connection_should_not_remove_parent
@ -362,7 +391,7 @@ module ActiveRecord
pid = fork { pid = fork {
rd.close rd.close
pool = @handler.retrieve_connection_pool(@spec_name) pool = @handler.retrieve_connection_pool(@owner_name)
wr.write Marshal.dump pool.schema_cache.size wr.write Marshal.dump pool.schema_cache.size
wr.close wr.close
exit! exit!

View file

@ -14,7 +14,7 @@ module ActiveRecord
@handlers = { writing: ConnectionHandler.new, reading: ConnectionHandler.new } @handlers = { writing: ConnectionHandler.new, reading: ConnectionHandler.new }
@rw_handler = @handlers[:writing] @rw_handler = @handlers[:writing]
@ro_handler = @handlers[:reading] @ro_handler = @handlers[:reading]
@spec_name = "primary" @owner_name = "ActiveRecord::Base"
@rw_pool = @handlers[:writing].establish_connection(ActiveRecord::Base.configurations["arunit"]) @rw_pool = @handlers[:writing].establish_connection(ActiveRecord::Base.configurations["arunit"])
@ro_pool = @handlers[:reading].establish_connection(ActiveRecord::Base.configurations["arunit"]) @ro_pool = @handlers[:reading].establish_connection(ActiveRecord::Base.configurations["arunit"])
end end
@ -81,11 +81,11 @@ module ActiveRecord
ActiveRecord::Base.connects_to(database: { writing: :default, reading: :readonly }) ActiveRecord::Base.connects_to(database: { writing: :default, reading: :readonly })
assert_not_nil pool = ActiveRecord::Base.connection_handlers[:writing].retrieve_connection_pool("primary") assert_not_nil pool = ActiveRecord::Base.connection_handlers[:writing].retrieve_connection_pool("ActiveRecord::Base")
assert_equal "db/primary.sqlite3", pool.db_config.database assert_equal "db/primary.sqlite3", pool.db_config.database
assert_equal "default", pool.db_config.spec_name assert_equal "default", pool.db_config.spec_name
assert_not_nil pool = ActiveRecord::Base.connection_handlers[:reading].retrieve_connection_pool("primary") assert_not_nil pool = ActiveRecord::Base.connection_handlers[:reading].retrieve_connection_pool("ActiveRecord::Base")
assert_equal "db/readonly.sqlite3", pool.db_config.database assert_equal "db/readonly.sqlite3", pool.db_config.database
assert_equal "readonly", pool.db_config.spec_name assert_equal "readonly", pool.db_config.spec_name
ensure ensure
@ -141,10 +141,10 @@ module ActiveRecord
ActiveRecord::Base.connects_to(database: { default: :primary, readonly: :readonly }) ActiveRecord::Base.connects_to(database: { default: :primary, readonly: :readonly })
assert_not_nil pool = ActiveRecord::Base.connection_handlers[:default].retrieve_connection_pool("primary") assert_not_nil pool = ActiveRecord::Base.connection_handlers[:default].retrieve_connection_pool("ActiveRecord::Base")
assert_equal "db/primary.sqlite3", pool.db_config.database assert_equal "db/primary.sqlite3", pool.db_config.database
assert_not_nil pool = ActiveRecord::Base.connection_handlers[:readonly].retrieve_connection_pool("primary") assert_not_nil pool = ActiveRecord::Base.connection_handlers[:readonly].retrieve_connection_pool("ActiveRecord::Base")
assert_equal "db/readonly.sqlite3", pool.db_config.database assert_equal "db/readonly.sqlite3", pool.db_config.database
ensure ensure
ActiveRecord::Base.configurations = @prev_configs ActiveRecord::Base.configurations = @prev_configs
@ -163,7 +163,7 @@ module ActiveRecord
handler = ActiveRecord::Base.connection_handler handler = ActiveRecord::Base.connection_handler
assert_equal handler, ActiveRecord::Base.connection_handlers[:writing] assert_equal handler, ActiveRecord::Base.connection_handlers[:writing]
assert_not_nil pool = handler.retrieve_connection_pool("primary") assert_not_nil pool = handler.retrieve_connection_pool("ActiveRecord::Base")
assert_equal({ adapter: "postgresql", database: "bar", host: "localhost" }, pool.db_config.configuration_hash) assert_equal({ adapter: "postgresql", database: "bar", host: "localhost" }, pool.db_config.configuration_hash)
ensure ensure
ActiveRecord::Base.establish_connection(:arunit) ActiveRecord::Base.establish_connection(:arunit)
@ -182,7 +182,7 @@ module ActiveRecord
handler = ActiveRecord::Base.connection_handler handler = ActiveRecord::Base.connection_handler
assert_equal handler, ActiveRecord::Base.connection_handlers[:writing] assert_equal handler, ActiveRecord::Base.connection_handlers[:writing]
assert_not_nil pool = handler.retrieve_connection_pool("primary") assert_not_nil pool = handler.retrieve_connection_pool("ActiveRecord::Base")
assert_equal(config, pool.db_config.configuration_hash) assert_equal(config, pool.db_config.configuration_hash)
ensure ensure
ActiveRecord::Base.establish_connection(:arunit) ActiveRecord::Base.establish_connection(:arunit)
@ -223,7 +223,7 @@ module ActiveRecord
handler = ActiveRecord::Base.connection_handler handler = ActiveRecord::Base.connection_handler
assert_equal handler, ActiveRecord::Base.connection_handlers[:writing] assert_equal handler, ActiveRecord::Base.connection_handlers[:writing]
assert_not_nil pool = handler.retrieve_connection_pool("primary") assert_not_nil pool = handler.retrieve_connection_pool("ActiveRecord::Base")
assert_equal(config["default_env"]["animals"], pool.db_config.configuration_hash) assert_equal(config["default_env"]["animals"], pool.db_config.configuration_hash)
ensure ensure
ActiveRecord::Base.configurations = @prev_configs ActiveRecord::Base.configurations = @prev_configs
@ -249,7 +249,7 @@ module ActiveRecord
handler = ActiveRecord::Base.connection_handler handler = ActiveRecord::Base.connection_handler
assert_equal handler, ActiveRecord::Base.connection_handlers[:writing] assert_equal handler, ActiveRecord::Base.connection_handlers[:writing]
assert_not_nil pool = handler.retrieve_connection_pool("primary") assert_not_nil pool = handler.retrieve_connection_pool("ActiveRecord::Base")
assert_equal(config["default_env"]["primary"], pool.db_config.configuration_hash) assert_equal(config["default_env"]["primary"], pool.db_config.configuration_hash)
ensure ensure
ActiveRecord::Base.configurations = @prev_configs ActiveRecord::Base.configurations = @prev_configs
@ -283,7 +283,7 @@ module ActiveRecord
ActiveRecord::Base.connects_to database: { writing: :development, reading: :development_readonly } ActiveRecord::Base.connects_to database: { writing: :development, reading: :development_readonly }
assert_not_nil pool = ActiveRecord::Base.connection_handlers[:reading].retrieve_connection_pool("primary") assert_not_nil pool = ActiveRecord::Base.connection_handlers[:reading].retrieve_connection_pool("ActiveRecord::Base")
assert_equal "db/readonly.sqlite3", pool.db_config.database assert_equal "db/readonly.sqlite3", pool.db_config.database
ensure ensure
ActiveRecord::Base.configurations = @prev_configs ActiveRecord::Base.configurations = @prev_configs
@ -301,8 +301,8 @@ module ActiveRecord
assert_equal( assert_equal(
[ [
ActiveRecord::Base.connection_handlers[:writing].retrieve_connection_pool("primary"), ActiveRecord::Base.connection_handlers[:writing].retrieve_connection_pool("ActiveRecord::Base"),
ActiveRecord::Base.connection_handlers[:reading].retrieve_connection_pool("primary") ActiveRecord::Base.connection_handlers[:reading].retrieve_connection_pool("ActiveRecord::Base")
], ],
result result
) )
@ -318,16 +318,16 @@ module ActiveRecord
end end
def test_retrieve_connection def test_retrieve_connection
assert @rw_handler.retrieve_connection(@spec_name) assert @rw_handler.retrieve_connection(@owner_name)
assert @ro_handler.retrieve_connection(@spec_name) assert @ro_handler.retrieve_connection(@owner_name)
end end
def test_active_connections? def test_active_connections?
assert_not_predicate @rw_handler, :active_connections? assert_not_predicate @rw_handler, :active_connections?
assert_not_predicate @ro_handler, :active_connections? assert_not_predicate @ro_handler, :active_connections?
assert @rw_handler.retrieve_connection(@spec_name) assert @rw_handler.retrieve_connection(@owner_name)
assert @ro_handler.retrieve_connection(@spec_name) assert @ro_handler.retrieve_connection(@owner_name)
assert_predicate @rw_handler, :active_connections? assert_predicate @rw_handler, :active_connections?
assert_predicate @ro_handler, :active_connections? assert_predicate @ro_handler, :active_connections?
@ -340,8 +340,8 @@ module ActiveRecord
end end
def test_retrieve_connection_pool def test_retrieve_connection_pool
assert_not_nil @rw_handler.retrieve_connection_pool(@spec_name) assert_not_nil @rw_handler.retrieve_connection_pool(@owner_name)
assert_not_nil @ro_handler.retrieve_connection_pool(@spec_name) assert_not_nil @ro_handler.retrieve_connection_pool(@owner_name)
end end
def test_retrieve_connection_pool_with_invalid_id def test_retrieve_connection_pool_with_invalid_id
@ -393,7 +393,7 @@ module ActiveRecord
end end
end end
assert_equal "No connection pool with 'primary' found for the 'reading' role.", error.message assert_equal "No connection pool for 'ActiveRecord::Base' found for the 'reading' role.", error.message
end end
def test_default_handlers_are_writing_and_reading def test_default_handlers_are_writing_and_reading

View file

@ -1406,7 +1406,7 @@ class MultipleDatabaseFixturesTest < ActiveRecord::TestCase
private private
def with_temporary_connection_pool def with_temporary_connection_pool
pool_config = ActiveRecord::Base.connection_handler.send(:owner_to_pool_manager).fetch("primary").get_pool_config(:default) pool_config = ActiveRecord::Base.connection_handler.send(:owner_to_pool_manager).fetch("ActiveRecord::Base").get_pool_config(:default)
new_pool = ActiveRecord::ConnectionAdapters::ConnectionPool.new(pool_config) new_pool = ActiveRecord::ConnectionAdapters::ConnectionPool.new(pool_config)
pool_config.stub(:pool, new_pool) do pool_config.stub(:pool, new_pool) do

View file

@ -27,7 +27,7 @@ class MultipleDbTest < ActiveRecord::TestCase
end end
def test_swapping_the_connection def test_swapping_the_connection
old_spec_name, Course.connection_specification_name = Course.connection_specification_name, "primary" old_spec_name, Course.connection_specification_name = Course.connection_specification_name, "ActiveRecord::Base"
assert_equal(Entrant.connection, Course.connection) assert_equal(Entrant.connection, Course.connection)
ensure ensure
Course.connection_specification_name = old_spec_name Course.connection_specification_name = old_spec_name

View file

@ -636,7 +636,7 @@ class QueryCacheTest < ActiveRecord::TestCase
private private
def with_temporary_connection_pool def with_temporary_connection_pool
pool_config = ActiveRecord::Base.connection_handler.send(:owner_to_pool_manager).fetch("primary").get_pool_config(:default) pool_config = ActiveRecord::Base.connection_handler.send(:owner_to_pool_manager).fetch("ActiveRecord::Base").get_pool_config(:default)
new_pool = ActiveRecord::ConnectionAdapters::ConnectionPool.new(pool_config) new_pool = ActiveRecord::ConnectionAdapters::ConnectionPool.new(pool_config)
pool_config.stub(:pool, new_pool) do pool_config.stub(:pool, new_pool) do

View file

@ -37,7 +37,7 @@ class TestUnconnectedAdapter < ActiveRecord::TestCase
TestRecord.find(1) TestRecord.find(1)
end end
assert_equal "No connection pool with 'primary' found.", error.message assert_equal "No connection pool for 'ActiveRecord::Base' found.", error.message
end end
def test_underlying_adapter_no_longer_active def test_underlying_adapter_no_longer_active