diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 6f7b2cb108beb058f41e24d832154104405d8a16..e94db776a591f6dd071f6cb82693bec36aab56a8 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,10 @@ ## Rails 4.0.0 (unreleased) ## +* Use native `mysqldump` command instead of `structure_dump` method + when dumping the database structure to a sql file. Fixes #5547. + + *kennyj* + * Attribute predicate methods, such as `article.title?`, will now raise `ActiveModel::MissingAttributeError` if the attribute being queried for truthiness was not read from the database, instead of just returning false. diff --git a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb index 85d08402f97378485f9208183d97229001c839cf..2340f949b74e08a83cac649b8b7732c13e9612b2 100644 --- a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb @@ -27,7 +27,7 @@ def create rescue error_class => error $stderr.puts error.error $stderr.puts "Couldn't create database for #{configuration.inspect}, #{creation_options.inspect}" - $stderr.puts "(If you set the charset manually, make sure you have a matching collation)" if configuration['charset'] + $stderr.puts "(If you set the charset manually, make sure you have a matching collation)" if configuration['encoding'] end def drop @@ -49,19 +49,17 @@ def collation end def structure_dump(filename) - establish_connection configuration - File.open(filename, "w:utf-8") { |f| f << ActiveRecord::Base.connection.structure_dump } + args = prepare_command_options('mysqldump') + args.concat(["--result-file", "#{filename}"]) + args.concat(["--no-data"]) + args.concat(["#{configuration['database']}"]) + Kernel.system(*args) end def structure_load(filename) - args = ['mysql'] - args.concat(['--user', configuration['username']]) if configuration['username'] - args << "--password=#{configuration['password']}" if configuration['password'] - args.concat(['--default-character-set', configuration['charset']]) if configuration['charset'] - configuration.slice('host', 'port', 'socket', 'database').each do |k, v| - args.concat([ "--#{k}", v ]) if v - end + args = prepare_command_options('mysql') args.concat(['--execute', %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}]) + args.concat(["--database", "#{configuration['database']}"]) Kernel.system(*args) end @@ -77,7 +75,7 @@ def configuration_without_database def creation_options { - charset: (configuration['charset'] || DEFAULT_CHARSET), + charset: (configuration['encoding'] || DEFAULT_CHARSET), collation: (configuration['collation'] || DEFAULT_COLLATION) } end @@ -113,6 +111,18 @@ def root_password $stdout.print "Please provide the root password for your mysql installation\n>" $stdin.gets.strip end + + def prepare_command_options(command) + args = [command] + args.concat(['--user', configuration['username']]) if configuration['username'] + args << "--password=#{configuration['password']}" if configuration['password'] + args.concat(['--default-character-set', configuration['encoding']]) if configuration['encoding'] + configuration.slice('host', 'port', 'socket').each do |k, v| + args.concat([ "--#{k}", v ]) if v + end + args + end + end end end diff --git a/activerecord/test/cases/tasks/mysql_rake_test.rb b/activerecord/test/cases/tasks/mysql_rake_test.rb index be591da8d6369ddba67638c49f3ad807189eecf2..46b97a1274fd61eb43abee66cf912ca0d2c39cf2 100644 --- a/activerecord/test/cases/tasks/mysql_rake_test.rb +++ b/activerecord/test/cases/tasks/mysql_rake_test.rb @@ -32,7 +32,7 @@ def test_creates_database_with_given_options with('my-app-db', {:charset => 'latin', :collation => 'latin_ci'}) ActiveRecord::Tasks::DatabaseTasks.create @configuration.merge( - 'charset' => 'latin', 'collation' => 'latin_ci' + 'encoding' => 'latin', 'collation' => 'latin_ci' ) end @@ -176,7 +176,7 @@ def test_recreates_database_with_the_given_options with('test-db', {:charset => 'latin', :collation => 'latin_ci'}) ActiveRecord::Tasks::DatabaseTasks.purge @configuration.merge( - 'charset' => 'latin', 'collation' => 'latin_ci' + 'encoding' => 'latin', 'collation' => 'latin_ci' ) end end @@ -219,44 +219,31 @@ def test_db_retrieves_collation class MySQLStructureDumpTest < ActiveRecord::TestCase def setup - @connection = stub(:structure_dump => true) @configuration = { 'adapter' => 'mysql', 'database' => 'test-db' } - - ActiveRecord::Base.stubs(:connection).returns(@connection) - ActiveRecord::Base.stubs(:establish_connection).returns(true) end def test_structure_dump filename = "awesome-file.sql" - ActiveRecord::Base.expects(:establish_connection).with(@configuration) - @connection.expects(:structure_dump) + Kernel.expects(:system).with("mysqldump", "--result-file", filename, "--no-data", "test-db") ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename) - assert File.exists?(filename) - ensure - FileUtils.rm(filename) end end class MySQLStructureLoadTest < ActiveRecord::TestCase def setup - @connection = stub @configuration = { 'adapter' => 'mysql', 'database' => 'test-db' } - - ActiveRecord::Base.stubs(:connection).returns(@connection) - ActiveRecord::Base.stubs(:establish_connection).returns(true) - Kernel.stubs(:system) end def test_structure_load filename = "awesome-file.sql" - Kernel.expects(:system).with('mysql', '--database', 'test-db', '--execute', %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}) + Kernel.expects(:system).with('mysql', '--execute', %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}, "--database", "test-db") ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename) end