Merge pull request #41207 from Aguardientico/ar-structure-load-dump-configurable

Support hash config for `structure_dump_flags` and `structure_load_flags` flags
This commit is contained in:
Eileen M. Uchitelle 2021-01-22 16:02:02 -05:00 committed by GitHub
commit c9e4af5c9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 137 additions and 2 deletions

View File

@ -1,3 +1,27 @@
* Support hash config for `structure_dump_flags` and `structure_load_flags` flags
Now that Active Record supports multiple databases configuration
we need a way to pass specific flags for dump/load databases since
the options are not the same for different adapters.
We can use in the original way:
```ruby
ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = ['--no-defaults', '--skip-add-drop-table']
#or
ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = '--no-defaults --skip-add-drop-table'
```
And also use it passing a hash, with one or more keys, where the key
is the adapter
```ruby
ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = {
mysql2: ['--no-defaults', '--skip-add-drop-table'],
postgres: '--no-tablespaces'
}
```
*Gustavo Gonzalez*
* Connection specification now passes the "url" key as a configuration for the * Connection specification now passes the "url" key as a configuration for the
adapter if the "url" protocol is "jdbc", "http", or "https". Previously only adapter if the "url" protocol is "jdbc", "http", or "https". Previously only
urls with the "jdbc" prefix were passed to the Active Record Adapter, others urls with the "jdbc" prefix were passed to the Active Record Adapter, others

View File

@ -39,11 +39,18 @@ module ActiveRecord
## ##
# :singleton-method: # :singleton-method:
# Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:schema:dump # Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:schema:dump
# It can be used as a string/array (the typical case) or a hash (when you use multiple adapters)
# Example:
# ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = {
# mysql2: ['--no-defaults', '--skip-add-drop-table'],
# postgres: '--no-tablespaces'
# }
mattr_accessor :structure_dump_flags, instance_accessor: false mattr_accessor :structure_dump_flags, instance_accessor: false
## ##
# :singleton-method: # :singleton-method:
# Extra flags passed to database CLI tool when calling db:schema:load # Extra flags passed to database CLI tool when calling db:schema:load
# It can be used as a string/array (the typical case) or a hash (when you use multiple adapters)
mattr_accessor :structure_load_flags, instance_accessor: false mattr_accessor :structure_load_flags, instance_accessor: false
extend self extend self
@ -338,13 +345,15 @@ module ActiveRecord
def structure_dump(configuration, *arguments) def structure_dump(configuration, *arguments)
db_config = resolve_configuration(configuration) db_config = resolve_configuration(configuration)
filename = arguments.delete_at(0) filename = arguments.delete_at(0)
database_adapter_for(db_config, *arguments).structure_dump(filename, structure_dump_flags) flags = structure_dump_flags_for(db_config.adapter)
database_adapter_for(db_config, *arguments).structure_dump(filename, flags)
end end
def structure_load(configuration, *arguments) def structure_load(configuration, *arguments)
db_config = resolve_configuration(configuration) db_config = resolve_configuration(configuration)
filename = arguments.delete_at(0) filename = arguments.delete_at(0)
database_adapter_for(db_config, *arguments).structure_load(filename, structure_load_flags) flags = structure_load_flags_for(db_config.adapter)
database_adapter_for(db_config, *arguments).structure_load(filename, flags)
end end
def load_schema(db_config, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc: def load_schema(db_config, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
@ -566,6 +575,22 @@ module ActiveRecord
def schema_sha1(file) def schema_sha1(file)
Digest::SHA1.hexdigest(File.read(file)) Digest::SHA1.hexdigest(File.read(file))
end end
def structure_dump_flags_for(adapter)
if structure_dump_flags.is_a?(Hash)
structure_dump_flags[adapter.to_sym]
else
structure_dump_flags
end
end
def structure_load_flags_for(adapter)
if structure_load_flags.is_a?(Hash)
structure_load_flags[adapter.to_sym]
else
structure_load_flags
end
end
end end
end end
end end

View File

@ -318,6 +318,28 @@ if current_adapter?(:Mysql2Adapter)
end end
end end
def test_structure_dump_with_hash_extra_flags_for_a_different_driver
filename = "awesome-file.sql"
expected_command = ["mysqldump", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db"]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_dump_flags({ postgresql: ["--noop"] }) do
ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename)
end
end
end
def test_structure_dump_with_hash_extra_flags_for_the_correct_driver
filename = "awesome-file.sql"
expected_command = ["mysqldump", "--noop", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db"]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_dump_flags({ mysql2: ["--noop"] }) do
ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename)
end
end
end
def test_structure_dump_with_ignore_tables def test_structure_dump_with_ignore_tables
filename = "awesome-file.sql" filename = "awesome-file.sql"
ActiveRecord::SchemaDumper.stub(:ignore_tables, ["foo", "bar"]) do ActiveRecord::SchemaDumper.stub(:ignore_tables, ["foo", "bar"]) do
@ -404,6 +426,28 @@ if current_adapter?(:Mysql2Adapter)
end end
end end
def test_structure_load_with_hash_extra_flags_for_a_different_driver
filename = "awesome-file.sql"
expected_command = ["mysql", "--execute", %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}, "--database", "test-db"]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_load_flags({ postgresql: ["--noop"] }) do
ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
end
end
end
def test_structure_load_with_hash_extra_flags_for_the_correct_driver
filename = "awesome-file.sql"
expected_command = ["mysql", "--noop", "--execute", %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}, "--database", "test-db"]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_load_flags({ mysql2: ["--noop"] }) do
ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
end
end
end
private private
def with_structure_load_flags(flags) def with_structure_load_flags(flags)
old = ActiveRecord::Tasks::DatabaseTasks.structure_load_flags old = ActiveRecord::Tasks::DatabaseTasks.structure_load_flags

View File

@ -387,6 +387,26 @@ if current_adapter?(:PostgreSQLAdapter)
end end
end end
def test_structure_dump_with_hash_extra_flags_for_a_different_driver
expected_command = ["pg_dump", "--schema-only", "--no-privileges", "--no-owner", "--file", @filename, "my-app-db"]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_dump_flags({ mysql2: ["--noop"] }) do
ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename)
end
end
end
def test_structure_dump_with_hash_extra_flags_for_the_correct_driver
expected_command = ["pg_dump", "--schema-only", "--no-privileges", "--no-owner", "--file", @filename, "--noop", "my-app-db"]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_dump_flags({ postgresql: ["--noop"] }) do
ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename)
end
end
end
def test_structure_dump_with_ignore_tables def test_structure_dump_with_ignore_tables
assert_called( assert_called(
ActiveRecord::SchemaDumper, ActiveRecord::SchemaDumper,
@ -509,6 +529,28 @@ if current_adapter?(:PostgreSQLAdapter)
end end
end end
def test_structure_load_with_hash_extra_flags_for_a_different_driver
filename = "awesome-file.sql"
expected_command = ["psql", "--set", "ON_ERROR_STOP=1", "--quiet", "--no-psqlrc", "--file", filename, @configuration["database"]]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_load_flags({ mysql2: ["--noop"] }) do
ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
end
end
end
def test_structure_load_with_hash_extra_flags_for_the_correct_driver
filename = "awesome-file.sql"
expected_command = ["psql", "--set", "ON_ERROR_STOP=1", "--quiet", "--no-psqlrc", "--file", filename, "--noop", @configuration["database"]]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_load_flags({ postgresql: ["--noop"] }) do
ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
end
end
end
def test_structure_load_accepts_path_with_spaces def test_structure_load_accepts_path_with_spaces
filename = "awesome file.sql" filename = "awesome file.sql"
assert_called_with( assert_called_with(