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

Merge pull request #27437 from kirs/structure-load-dump-flags

Make ActiveRecord structure load/dump configurable
This commit is contained in:
Kasper Timm Hansen 2016-12-29 20:23:35 +01:00 committed by GitHub
commit 261e94b8ee
7 changed files with 109 additions and 15 deletions

View file

@ -35,6 +35,16 @@ module ActiveRecord
# #
# DatabaseTasks.create_current('production') # DatabaseTasks.create_current('production')
module DatabaseTasks module DatabaseTasks
##
# :singleton-method:
# Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:structure:dump
mattr_accessor :structure_dump_flags, instance_accessor: false
##
# :singleton-method:
# Extra flags passed to database CLI tool when calling db:structure:load
mattr_accessor :structure_load_flags, instance_accessor: false
extend self extend self
attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
@ -204,13 +214,13 @@ module ActiveRecord
def structure_dump(*arguments) def structure_dump(*arguments)
configuration = arguments.first configuration = arguments.first
filename = arguments.delete_at 1 filename = arguments.delete_at 1
class_for_adapter(configuration["adapter"]).new(*arguments).structure_dump(filename) class_for_adapter(configuration["adapter"]).new(*arguments).structure_dump(filename, structure_dump_flags)
end end
def structure_load(*arguments) def structure_load(*arguments)
configuration = arguments.first configuration = arguments.first
filename = arguments.delete_at 1 filename = arguments.delete_at 1
class_for_adapter(configuration["adapter"]).new(*arguments).structure_load(filename) class_for_adapter(configuration["adapter"]).new(*arguments).structure_load(filename, structure_load_flags)
end end
def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc: def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:

View file

@ -53,21 +53,23 @@ module ActiveRecord
connection.collation connection.collation
end end
def structure_dump(filename) def structure_dump(filename, extra_flags)
args = prepare_command_options args = prepare_command_options
args.concat(["--result-file", "#{filename}"]) args.concat(["--result-file", "#{filename}"])
args.concat(["--no-data"]) args.concat(["--no-data"])
args.concat(["--routines"]) args.concat(["--routines"])
args.concat(["--skip-comments"]) args.concat(["--skip-comments"])
args.concat(Array(extra_flags)) if extra_flags
args.concat(["#{configuration['database']}"]) args.concat(["#{configuration['database']}"])
run_cmd("mysqldump", args, "dumping") run_cmd("mysqldump", args, "dumping")
end end
def structure_load(filename) def structure_load(filename, extra_flags)
args = prepare_command_options args = prepare_command_options
args.concat(["--execute", %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}]) args.concat(["--execute", %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}])
args.concat(["--database", "#{configuration['database']}"]) args.concat(["--database", "#{configuration['database']}"])
args.concat(Array(extra_flags)) if extra_flags
run_cmd("mysql", args, "loading") run_cmd("mysql", args, "loading")
end end

View file

@ -43,7 +43,7 @@ module ActiveRecord
create true create true
end end
def structure_dump(filename) def structure_dump(filename, extra_flags)
set_psql_env set_psql_env
search_path = \ search_path = \
@ -57,6 +57,7 @@ module ActiveRecord
end end
args = ["-s", "-x", "-O", "-f", filename] args = ["-s", "-x", "-O", "-f", filename]
args.concat(Array(extra_flags)) if extra_flags
unless search_path.blank? unless search_path.blank?
args += search_path.split(",").map do |part| args += search_path.split(",").map do |part|
"--schema=#{part.strip}" "--schema=#{part.strip}"
@ -67,9 +68,11 @@ module ActiveRecord
File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" } File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" }
end end
def structure_load(filename) def structure_load(filename, extra_flags)
set_psql_env set_psql_env
args = [ "-v", ON_ERROR_STOP_1, "-q", "-f", filename, configuration["database"] ] args = ["-v", ON_ERROR_STOP_1, "-q", "-f", filename]
args.concat(Array(extra_flags)) if extra_flags
args << configuration["database"]
run_cmd("psql", args, "loading") run_cmd("psql", args, "loading")
end end

View file

@ -35,14 +35,16 @@ module ActiveRecord
connection.encoding connection.encoding
end end
def structure_dump(filename) def structure_dump(filename, extra_flags)
dbfile = configuration["database"] dbfile = configuration["database"]
`sqlite3 #{dbfile} .schema > #{filename}` flags = extra_flags.try!(:join, " ")
`sqlite3 #{flags} #{dbfile} .schema > #{filename}`
end end
def structure_load(filename) def structure_load(filename, extra_flags)
dbfile = configuration["database"] dbfile = configuration["database"]
`sqlite3 #{dbfile} < "#{filename}"` flags = extra_flags.try!(:join, " ")
`sqlite3 #{flags} #{dbfile} < "#{filename}"`
end end
private private

View file

@ -61,7 +61,7 @@ module ActiveRecord
instance = klazz.new instance = klazz.new
klazz.stubs(:new).returns instance klazz.stubs(:new).returns instance
instance.expects(:structure_dump).with("awesome-file.sql") instance.expects(:structure_dump).with("awesome-file.sql", nil)
ActiveRecord::Tasks::DatabaseTasks.register_task(/foo/, klazz) ActiveRecord::Tasks::DatabaseTasks.register_task(/foo/, klazz)
ActiveRecord::Tasks::DatabaseTasks.structure_dump({ "adapter" => :foo }, "awesome-file.sql") ActiveRecord::Tasks::DatabaseTasks.structure_dump({ "adapter" => :foo }, "awesome-file.sql")
@ -411,7 +411,7 @@ module ActiveRecord
ADAPTERS_TASKS.each do |k, v| ADAPTERS_TASKS.each do |k, v|
define_method("test_#{k}_structure_dump") do define_method("test_#{k}_structure_dump") do
eval("@#{v}").expects(:structure_dump).with("awesome-file.sql") eval("@#{v}").expects(:structure_dump).with("awesome-file.sql", nil)
ActiveRecord::Tasks::DatabaseTasks.structure_dump({ "adapter" => k }, "awesome-file.sql") ActiveRecord::Tasks::DatabaseTasks.structure_dump({ "adapter" => k }, "awesome-file.sql")
end end
end end
@ -422,7 +422,7 @@ module ActiveRecord
ADAPTERS_TASKS.each do |k, v| ADAPTERS_TASKS.each do |k, v|
define_method("test_#{k}_structure_load") do define_method("test_#{k}_structure_load") do
eval("@#{v}").expects(:structure_load).with("awesome-file.sql") eval("@#{v}").expects(:structure_load).with("awesome-file.sql", nil)
ActiveRecord::Tasks::DatabaseTasks.structure_load({ "adapter" => k }, "awesome-file.sql") ActiveRecord::Tasks::DatabaseTasks.structure_load({ "adapter" => k }, "awesome-file.sql")
end end
end end

View file

@ -294,6 +294,17 @@ if current_adapter?(:Mysql2Adapter)
ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename) ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename)
end end
def test_structure_dump_with_extra_flags
filename = "awesome-file.sql"
expected_command = ["mysqldump", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "--noop", "test-db"]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_dump_flags(["--noop"]) do
ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename)
end
end
end
def test_warn_when_external_structure_dump_command_execution_fails def test_warn_when_external_structure_dump_command_execution_fails
filename = "awesome-file.sql" filename = "awesome-file.sql"
Kernel.expects(:system) Kernel.expects(:system)
@ -323,6 +334,15 @@ if current_adapter?(:Mysql2Adapter)
@configuration.merge("sslca" => "ca.crt"), @configuration.merge("sslca" => "ca.crt"),
filename) filename)
end end
private
def with_structure_dump_flags(flags)
old = ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags
ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = flags
yield
ensure
ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = old
end
end end
class MySQLStructureLoadTest < ActiveRecord::TestCase class MySQLStructureLoadTest < ActiveRecord::TestCase
@ -340,6 +360,26 @@ if current_adapter?(:Mysql2Adapter)
ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename) ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
end end
def test_structure_load
filename = "awesome-file.sql"
expected_command = ["mysql", "--execute", %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}, "--database", "test-db", "--noop"]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_load_flags(["--noop"]) do
ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
end
end
end
private
def with_structure_load_flags(flags)
old = ActiveRecord::Tasks::DatabaseTasks.structure_load_flags
ActiveRecord::Tasks::DatabaseTasks.structure_load_flags = flags
yield
ensure
ActiveRecord::Tasks::DatabaseTasks.structure_load_flags = old
end
end end
end end
end end

View file

@ -236,6 +236,16 @@ if current_adapter?(:PostgreSQLAdapter)
ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename) ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename)
end end
def test_structure_dump_with_extra_flags
expected_command = ["pg_dump", "-s", "-x", "-O", "-f", @filename, "--noop", "my-app-db"]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_dump_flags(["--noop"]) do
ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename)
end
end
end
def test_structure_dump_with_schema_search_path def test_structure_dump_with_schema_search_path
@configuration["schema_search_path"] = "foo,bar" @configuration["schema_search_path"] = "foo,bar"
@ -263,7 +273,6 @@ if current_adapter?(:PostgreSQLAdapter)
end end
private private
def with_dump_schemas(value, &block) def with_dump_schemas(value, &block)
old_dump_schemas = ActiveRecord::Base.dump_schemas old_dump_schemas = ActiveRecord::Base.dump_schemas
ActiveRecord::Base.dump_schemas = value ActiveRecord::Base.dump_schemas = value
@ -271,6 +280,14 @@ if current_adapter?(:PostgreSQLAdapter)
ensure ensure
ActiveRecord::Base.dump_schemas = old_dump_schemas ActiveRecord::Base.dump_schemas = old_dump_schemas
end end
def with_structure_dump_flags(flags)
old = ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags
ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = flags
yield
ensure
ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = old
end
end end
class PostgreSQLStructureLoadTest < ActiveRecord::TestCase class PostgreSQLStructureLoadTest < ActiveRecord::TestCase
@ -293,12 +310,32 @@ if current_adapter?(:PostgreSQLAdapter)
ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename) ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
end end
def test_structure_load_with_extra_flags
filename = "awesome-file.sql"
expected_command = ["psql", "-v", "ON_ERROR_STOP=1", "-q", "-f", filename, "--noop", @configuration["database"]]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_load_flags(["--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"
Kernel.expects(:system).with("psql", "-v", "ON_ERROR_STOP=1", "-q", "-f", filename, @configuration["database"]).returns(true) Kernel.expects(:system).with("psql", "-v", "ON_ERROR_STOP=1", "-q", "-f", filename, @configuration["database"]).returns(true)
ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename) ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
end end
private
def with_structure_load_flags(flags)
old = ActiveRecord::Tasks::DatabaseTasks.structure_load_flags
ActiveRecord::Tasks::DatabaseTasks.structure_load_flags = flags
yield
ensure
ActiveRecord::Tasks::DatabaseTasks.structure_load_flags = old
end
end end
end end
end end