Merge pull request #24965 from arthurnn/arthurnn/conn_api

Change some establish_connection logic
This commit is contained in:
Arthur Nogueira Neves 2016-05-29 12:48:36 -04:00
commit ff63bb8231
7 changed files with 43 additions and 37 deletions

@ -837,7 +837,11 @@ def connection_pool_list
end
alias :connection_pools :connection_pool_list
def establish_connection(spec)
def establish_connection(config)
resolver = ConnectionSpecification::Resolver.new(Base.configurations)
spec = resolver.spec(config)
remove_connection(spec.name)
owner_to_pool[spec.name] = ConnectionAdapters::ConnectionPool.new(spec)
end
@ -871,9 +875,9 @@ def clear_all_connections!
# for (not necessarily the current class).
def retrieve_connection(spec_name) #:nodoc:
pool = retrieve_connection_pool(spec_name)
raise ConnectionNotEstablished, "No connection pool with id #{spec_name} found." unless pool
raise ConnectionNotEstablished, "No connection pool with id '#{spec_name}' found." unless pool
conn = pool.connection
raise ConnectionNotEstablished, "No connection for #{spec_name} in connection pool" unless conn
raise ConnectionNotEstablished, "No connection for '#{spec_name}' in connection pool" unless conn
conn
end
@ -907,7 +911,7 @@ def retrieve_connection_pool(spec_name)
# A connection was established in an ancestor process that must have
# subsequently forked. We can't reuse the connection, but we can copy
# the specification and establish a new connection with it.
establish_connection(ancestor_pool.spec).tap do |pool|
establish_connection(ancestor_pool.spec.to_hash).tap do |pool|
pool.schema_cache = ancestor_pool.schema_cache if ancestor_pool.schema_cache
end
else

@ -13,6 +13,10 @@ def initialize_dup(original)
@config = original.config.dup
end
def to_hash
@config.merge(name: @name)
end
# Expands a connection string into a hash.
class ConnectionUrlResolver # :nodoc:
@ -164,7 +168,7 @@ def resolve_all
# spec.config
# # => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" }
#
def spec(config, name = nil)
def spec(config)
spec = resolve(config).symbolize_keys
raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
@ -180,13 +184,11 @@ def spec(config, name = nil)
adapter_method = "#{spec[:adapter]}_connection"
name ||=
if config.is_a?(Symbol)
config.to_s
else
"primary"
end
ConnectionSpecification.new(name, spec, adapter_method)
unless ActiveRecord::Base.respond_to?(adapter_method)
raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
end
ConnectionSpecification.new(spec.delete(:name) || "primary", spec, adapter_method)
end
private
@ -231,7 +233,7 @@ def resolve_connection(spec)
#
def resolve_symbol_connection(spec)
if config = configurations[spec.to_s]
resolve_connection(config)
resolve_connection(config).merge("name" => spec.to_s)
else
raise(AdapterNotSpecified, "'#{spec}' database is not configured. Available: #{configurations.keys.inspect}")
end

@ -44,21 +44,18 @@ module ConnectionHandling
#
# The exceptions AdapterNotSpecified, AdapterNotFound and +ArgumentError+
# may be returned on an error.
def establish_connection(spec = nil)
def establish_connection(config = nil)
raise "Anonymous class is not allowed." unless name
spec ||= DEFAULT_ENV.call.to_sym
resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new configurations
# TODO: uses name on establish_connection, for backwards compatibility
spec = resolver.spec(spec, self == Base ? "primary" : name)
config ||= DEFAULT_ENV.call.to_sym
spec_name = self == Base ? "primary" : name
self.connection_specification_name = spec_name
unless respond_to?(spec.adapter_method)
raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
end
resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new(Base.configurations)
spec = resolver.resolve(config).symbolize_keys
spec[:name] = spec_name
remove_connection(spec.name)
self.connection_specification_name = spec.name
connection_handler.establish_connection spec
connection_handler.establish_connection(spec)
end
class MergeAndResolveDefaultUrlConfig # :nodoc:

@ -120,7 +120,7 @@ def create_all
old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name)
each_local_configuration { |configuration| create configuration }
if old_pool
ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec)
ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec.to_hash)
end
end

@ -5,16 +5,15 @@ module ConnectionAdapters
class ConnectionHandlerTest < ActiveRecord::TestCase
def setup
@handler = ConnectionHandler.new
resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new Base.configurations
@spec_name = "primary"
@pool = @handler.establish_connection(resolver.spec(:arunit, @spec_name))
@pool = @handler.establish_connection(ActiveRecord::Base.configurations['arunit'])
end
def test_establish_connection_uses_spec_name
config = {"readonly" => {"adapter" => 'sqlite3'}}
resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new(config)
spec = resolver.spec(:readonly)
@handler.establish_connection(spec)
@handler.establish_connection(spec.to_hash)
assert_not_nil @handler.retrieve_connection_pool('readonly')
ensure

@ -27,7 +27,7 @@ def test_resolver_with_database_uri_and_current_env_symbol_key
ENV['DATABASE_URL'] = "postgres://localhost/foo"
config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
actual = resolve_spec(:default_env, config)
expected = { "adapter"=>"postgresql", "database"=>"foo", "host"=>"localhost" }
expected = { "adapter"=>"postgresql", "database"=>"foo", "host"=>"localhost", "name"=>"default_env" }
assert_equal expected, actual
end
@ -37,7 +37,7 @@ def test_resolver_with_database_uri_and_current_env_symbol_key_and_rails_env
config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
actual = resolve_spec(:foo, config)
expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost" }
expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost","name"=>"foo" }
assert_equal expected, actual
end
@ -47,7 +47,7 @@ def test_resolver_with_database_uri_and_current_env_symbol_key_and_rack_env
config = { "not_production" => { "adapter" => "not_postgres", "database" => "not_foo" } }
actual = resolve_spec(:foo, config)
expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost" }
expected = { "adapter" => "postgresql", "database" => "foo", "host" => "localhost","name"=>"foo" }
assert_equal expected, actual
end
@ -55,7 +55,7 @@ def test_resolver_with_database_uri_and_known_key
ENV['DATABASE_URL'] = "postgres://localhost/foo"
config = { "production" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" } }
actual = resolve_spec(:production, config)
expected = { "adapter"=>"not_postgres", "database"=>"not_foo", "host"=>"localhost" }
expected = { "adapter"=>"not_postgres", "database"=>"not_foo", "host"=>"localhost", "name"=>"production" }
assert_equal expected, actual
end
@ -93,7 +93,7 @@ def test_url_with_hyphenated_scheme
ENV['DATABASE_URL'] = "ibm-db://localhost/foo"
config = { "default_env" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" } }
actual = resolve_spec(:default_env, config)
expected = { "adapter"=>"ibm_db", "database"=>"foo", "host"=>"localhost" }
expected = { "adapter"=>"ibm_db", "database"=>"foo", "host"=>"localhost", "name"=>"default_env" }
assert_equal expected, actual
end

@ -28,7 +28,8 @@ def test_url_from_environment
assert_equal({
"adapter" => "abstract",
"host" => "foo",
"encoding" => "utf8" }, spec)
"encoding" => "utf8",
"name" => "production"}, spec)
end
def test_url_sub_key
@ -36,7 +37,8 @@ def test_url_sub_key
assert_equal({
"adapter" => "abstract",
"host" => "foo",
"encoding" => "utf8" }, spec)
"encoding" => "utf8",
"name" => "production"}, spec)
end
def test_url_sub_key_merges_correctly
@ -46,7 +48,8 @@ def test_url_sub_key_merges_correctly
"adapter" => "abstract",
"host" => "foo",
"encoding" => "utf8",
"pool" => "3" }, spec)
"pool" => "3",
"name" => "production"}, spec)
end
def test_url_host_no_db
@ -113,7 +116,8 @@ def test_url_sub_key_for_sqlite3
assert_equal({
"adapter" => "sqlite3",
"database" => "foo",
"encoding" => "utf8" }, spec)
"encoding" => "utf8",
"name" => "production"}, spec)
end
def test_spec_name_on_key_lookup