diff options
Diffstat (limited to 'activerecord')
5 files changed, 88 insertions, 25 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index acd3d395c5..38ac8bdfeb 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,20 @@ +* (Temporarily) deprecate SQLite database URLs containing an + authority. + + The current "correct" spellings for in-memory, relative, and + absolute URLs, respectively, are: + + sqlite3::memory: + sqlite3:relative/path + sqlite3:/full/path + + The previous spelling (`sqlite3:///relative/path`) continues to work + as it did in Rails 4.0, but with a deprecation warning: in the next + release, that spelling will instead be interpreted as an absolute + path. + + *Matthew Draper* + * Enable support for materialized views on PostgreSQL >= 9.3. *Dave Lee* diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb index 9a133168f8..5ede946836 100644 --- a/activerecord/lib/active_record/connection_adapters/connection_specification.rb +++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb @@ -35,7 +35,13 @@ module ActiveRecord @uri = URI.parse(url) @adapter = @uri.scheme @adapter = "postgresql" if @adapter == "postgres" - @query = @uri.query || '' + + if @uri.opaque + @uri.opaque, @query = @uri.opaque.split('?', 2) + else + @query = @uri.query + end + @authority = url =~ %r{\A[^:]*://} end # Converts the given URL to a full connection hash. @@ -65,30 +71,51 @@ module ActiveRecord # "localhost" # # => {} def query_hash - Hash[@query.split("&").map { |pair| pair.split("=") }] + Hash[(@query || '').split("&").map { |pair| pair.split("=") }] end def raw_config - query_hash.merge({ - "adapter" => @adapter, - "username" => uri.user, - "password" => uri.password, - "port" => uri.port, - "database" => database, - "host" => uri.host }) + if uri.opaque + query_hash.merge({ + "adapter" => @adapter, + "database" => uri.opaque }) + else + query_hash.merge({ + "adapter" => @adapter, + "username" => uri.user, + "password" => uri.password, + "port" => uri.port, + "database" => database_from_path, + "host" => uri.host }) + end end # Returns name of the database. - # Sqlite3 expects this to be a full path or `:memory:`. - def database - if @adapter == 'sqlite3' - if '/:memory:' == uri.path - ':memory:' - else - uri.path - end + # Sqlite3's handling of a leading slash is in transition as of + # Rails 4.1. + def database_from_path + if @authority && @adapter == 'sqlite3' + # 'sqlite3:///foo' is relative, for backwards compatibility. + + database_name = uri.path.sub(%r{^/}, "") + + msg = "Paths in SQLite3 database URLs of the form `sqlite3:///path` will be treated as absolute in Rails 4.2. " \ + "Please switch to `sqlite3:#{database_name}`." + ActiveSupport::Deprecation.warn(msg) + + database_name + + elsif @adapter == 'sqlite3' + # 'sqlite3:/foo' is absolute, because that makes sense. The + # corresponding relative version, 'sqlite3:foo', is handled + # elsewhere, as an "opaque". + + uri.path else - uri.path.sub(%r{^/},"") + # Only SQLite uses a filename as the "database" name; for + # anything else, a leading slash would be silly. + + uri.path.sub(%r{^/}, "") end end end diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb index c2a255451e..14aad61ce2 100644 --- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb @@ -31,7 +31,7 @@ module ActiveRecord def test_connect_with_url original_connection = ActiveRecord::Base.remove_connection tf = Tempfile.open 'whatever' - url = "sqlite3://#{tf.path}" + url = "sqlite3:#{tf.path}" ActiveRecord::Base.establish_connection(url) assert ActiveRecord::Base.connection ensure @@ -42,7 +42,7 @@ module ActiveRecord def test_connect_memory_with_url original_connection = ActiveRecord::Base.remove_connection - url = "sqlite3:///:memory:" + url = "sqlite3::memory:" ActiveRecord::Base.establish_connection(url) assert ActiveRecord::Base.connection ensure diff --git a/activerecord/test/cases/connection_specification/resolver_test.rb b/activerecord/test/cases/connection_specification/resolver_test.rb index fdd1914cba..a4fe87049a 100644 --- a/activerecord/test/cases/connection_specification/resolver_test.rb +++ b/activerecord/test/cases/connection_specification/resolver_test.rb @@ -82,15 +82,34 @@ module ActiveRecord assert_equal password, spec["password"] end - def test_url_host_db_for_sqlite3 - spec = resolve 'sqlite3://foo:bar@dburl:9000/foo_test' + def test_url_with_authority_for_sqlite3 + spec = assert_deprecated { resolve 'sqlite3:///foo_test' } + assert_equal('foo_test', spec["database"]) + end + + def test_url_absolute_path_for_sqlite3 + spec = resolve 'sqlite3:/foo_test' assert_equal('/foo_test', spec["database"]) end - def test_url_host_memory_db_for_sqlite3 - spec = resolve 'sqlite3://foo:bar@dburl:9000/:memory:' + def test_url_relative_path_for_sqlite3 + spec = resolve 'sqlite3:foo_test' + assert_equal('foo_test', spec["database"]) + end + + def test_url_memory_db_for_sqlite3 + spec = resolve 'sqlite3::memory:' assert_equal(':memory:', spec["database"]) end + + def test_url_sub_key_for_sqlite3 + spec = resolve :production, 'production' => {"url" => 'sqlite3:foo?encoding=utf8'} + assert_equal({ + "adapter" => "sqlite3", + "database" => "foo", + "encoding" => "utf8" }, spec) + end + end end end diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index 1147418815..cf0235b8c5 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -254,7 +254,7 @@ class FixturesTest < ActiveRecord::TestCase def test_fixtures_are_set_up_with_database_env_variable db_url_tmp = ENV['DATABASE_URL'] - ENV['DATABASE_URL'] = "sqlite3:///:memory:" + ENV['DATABASE_URL'] = "sqlite3::memory:" ActiveRecord::Base.stubs(:configurations).returns({}) test_case = Class.new(ActiveRecord::TestCase) do fixtures :accounts |