From d8dfcacd44a051b2c8bf0e940472b074e2c5dfb7 Mon Sep 17 00:00:00 2001 From: kennyj Date: Wed, 20 Jun 2012 01:28:44 +0900 Subject: Refactor db:structure:dump task. --- .../lib/active_record/railties/databases.rake | 16 ++-------- .../lib/active_record/tasks/database_tasks.rb | 6 ++++ .../active_record/tasks/mysql_database_tasks.rb | 5 +++ .../tasks/postgresql_database_tasks.rb | 22 +++++++++++++ .../active_record/tasks/sqlite_database_tasks.rb | 5 +++ activerecord/test/cases/database_tasks_test.rb | 36 +++++++++++++++++++++- activerecord/test/cases/mysql_rake_test.rb | 24 +++++++++++++++ activerecord/test/cases/postgresql_rake_test.rb | 25 +++++++++++++++ activerecord/test/cases/sqlite_rake_test.rb | 22 +++++++++++++ 9 files changed, 147 insertions(+), 14 deletions(-) diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index d513dca1f5..b8205a99a8 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -275,21 +275,11 @@ db_namespace = namespace :db do abcs = ActiveRecord::Base.configurations filename = ENV['DB_STRUCTURE'] || File.join(Rails.root, "db", "structure.sql") case abcs[Rails.env]['adapter'] - when /mysql/, 'oci', 'oracle' + when /mysql/, /postgresql/, /sqlite/ + ActiveRecord::Tasks::DatabaseTasks.structure_dump(abcs[Rails.env], filename) + when 'oci', 'oracle' ActiveRecord::Base.establish_connection(abcs[Rails.env]) File.open(filename, "w:utf-8") { |f| f << ActiveRecord::Base.connection.structure_dump } - when /postgresql/ - set_psql_env(abcs[Rails.env]) - search_path = abcs[Rails.env]['schema_search_path'] - unless search_path.blank? - search_path = search_path.split(",").map{|search_path_part| "--schema=#{Shellwords.escape(search_path_part.strip)}" }.join(" ") - end - `pg_dump -i -s -x -O -f #{Shellwords.escape(filename)} #{search_path} #{Shellwords.escape(abcs[Rails.env]['database'])}` - raise 'Error dumping database' if $?.exitstatus == 1 - File.open(filename, "a") { |f| f << "SET search_path TO #{ActiveRecord::Base.connection.schema_search_path};\n\n" } - when /sqlite/ - dbfile = abcs[Rails.env]['database'] - `sqlite3 #{dbfile} .schema > #{filename}` when 'sqlserver' `smoscript -s #{abcs[Rails.env]['host']} -d #{abcs[Rails.env]['database']} -u #{abcs[Rails.env]['username']} -p #{abcs[Rails.env]['password']} -f #{filename} -A -U` when "firebird" diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index 5101871cc0..d53fe307c2 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -60,6 +60,12 @@ module ActiveRecord class_for_adapter(configuration['adapter']).new(configuration).purge end + def structure_dump(*arguments) + configuration = arguments.first + filename = arguments.delete_at 1 + class_for_adapter(configuration['adapter']).new(*arguments).structure_dump(filename) + end + private def class_for_adapter(adapter) diff --git a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb index 361437fdc7..052ab60e81 100644 --- a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb @@ -44,6 +44,11 @@ module ActiveRecord connection.charset end + def structure_dump(filename) + establish_connection configuration + File.open(filename, "w:utf-8") { |f| f << ActiveRecord::Base.connection.structure_dump } + end + private def configuration diff --git a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb index 8d4249fd79..dabc69b9cd 100644 --- a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb @@ -1,3 +1,5 @@ +require 'shellwords' + module ActiveRecord module Tasks # :nodoc: class PostgreSQLDatabaseTasks # :nodoc: @@ -33,6 +35,19 @@ module ActiveRecord create true end + def structure_dump(filename) + set_psql_env + search_path = configuration['schema_search_path'] + unless search_path.blank? + search_path = search_path.split(",").map{|search_path_part| "--schema=#{Shellwords.escape(search_path_part.strip)}" }.join(" ") + end + + command = "pg_dump -i -s -x -O -f #{Shellwords.escape(filename)} #{search_path} #{Shellwords.escape(configuration['database'])}" + raise 'Error dumping database' unless Kernel.system(command) + + File.open(filename, "a") { |f| f << "SET search_path TO #{ActiveRecord::Base.connection.schema_search_path};\n\n" } + end + private def configuration @@ -49,6 +64,13 @@ module ActiveRecord 'schema_search_path' => 'public' ) end + + def set_psql_env + ENV['PGHOST'] = configuration['host'] if configuration['host'] + ENV['PGPORT'] = configuration['port'].to_s if configuration['port'] + ENV['PGPASSWORD'] = configuration['password'].to_s if configuration['password'] + ENV['PGUSER'] = configuration['username'].to_s if configuration['username'] + end end end end diff --git a/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb b/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb index d9332eaf1b..68f0c304a8 100644 --- a/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb @@ -31,6 +31,11 @@ module ActiveRecord connection.encoding end + def structure_dump(filename) + dbfile = configuration['database'] + `sqlite3 #{dbfile} .schema > #{filename}` + end + private def configuration diff --git a/activerecord/test/cases/database_tasks_test.rb b/activerecord/test/cases/database_tasks_test.rb index a5329073ed..41267c2df3 100644 --- a/activerecord/test/cases/database_tasks_test.rb +++ b/activerecord/test/cases/database_tasks_test.rb @@ -303,7 +303,7 @@ module ActiveRecord returns @postgresql_tasks ActiveRecord::Tasks::SQLiteDatabaseTasks.stubs(:new).returns @sqlite_tasks end - + def test_mysql_charset @mysql_tasks.expects(:charset) @@ -328,4 +328,38 @@ module ActiveRecord ActiveRecord::Tasks::DatabaseTasks.charset 'adapter' => 'sqlite3' end end + + class DatabaseTasksStructureDumpTest < ActiveRecord::TestCase + def setup + @mysql_tasks, @postgresql_tasks, @sqlite_tasks = stub, stub, stub + ActiveRecord::Tasks::MySQLDatabaseTasks.stubs(:new).returns @mysql_tasks + ActiveRecord::Tasks::PostgreSQLDatabaseTasks.stubs(:new). + returns @postgresql_tasks + ActiveRecord::Tasks::SQLiteDatabaseTasks.stubs(:new).returns @sqlite_tasks + end + + def test_mysql_structure_dump + @mysql_tasks.expects(:structure_dump).with("awesome-file.sql") + + ActiveRecord::Tasks::DatabaseTasks.structure_dump({'adapter' => 'mysql'}, "awesome-file.sql") + end + + def test_mysql2_structure_dump + @mysql_tasks.expects(:structure_dump).with("awesome-file.sql") + + ActiveRecord::Tasks::DatabaseTasks.structure_dump({'adapter' => 'mysql2'}, "awesome-file.sql") + end + + def test_postgresql_structure_dump + @postgresql_tasks.expects(:structure_dump).with("awesome-file.sql") + + ActiveRecord::Tasks::DatabaseTasks.structure_dump({'adapter' => 'postgresql'}, "awesome-file.sql") + end + + def test_sqlite_structure_dump + @sqlite_tasks.expects(:structure_dump).with("awesome-file.sql") + + ActiveRecord::Tasks::DatabaseTasks.structure_dump({'adapter' => 'sqlite3'}, "awesome-file.sql") + end + end end diff --git a/activerecord/test/cases/mysql_rake_test.rb b/activerecord/test/cases/mysql_rake_test.rb index 39d0ae428c..8255fe3aa5 100644 --- a/activerecord/test/cases/mysql_rake_test.rb +++ b/activerecord/test/cases/mysql_rake_test.rb @@ -194,4 +194,28 @@ module ActiveRecord ActiveRecord::Tasks::DatabaseTasks.charset @configuration end end + + 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) + + ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename) + assert File.exists?(filename) + ensure + FileUtils.rm(filename) + end + end end diff --git a/activerecord/test/cases/postgresql_rake_test.rb b/activerecord/test/cases/postgresql_rake_test.rb index a9e0d913fa..b055762a24 100644 --- a/activerecord/test/cases/postgresql_rake_test.rb +++ b/activerecord/test/cases/postgresql_rake_test.rb @@ -150,4 +150,29 @@ module ActiveRecord ActiveRecord::Tasks::DatabaseTasks.charset @configuration end end + + class PostgreSQLStructureDumpTest < ActiveRecord::TestCase + def setup + @connection = stub(:structure_dump => true) + @configuration = { + 'adapter' => 'postgresql', + 'database' => 'my-app-db' + } + + ActiveRecord::Base.stubs(:connection).returns(@connection) + ActiveRecord::Base.stubs(:establish_connection).returns(true) + Kernel.stubs(:system) + end + + def test_structure_dump + filename = "awesome-file.sql" + Kernel.expects(:system).with("pg_dump -i -s -x -O -f #{filename} my-app-db").returns(true) + @connection.expects(:schema_search_path).returns("foo") + + ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename) + assert File.exists?(filename) + ensure + FileUtils.rm(filename) + end + end end diff --git a/activerecord/test/cases/sqlite_rake_test.rb b/activerecord/test/cases/sqlite_rake_test.rb index cfca937a24..69fb129326 100644 --- a/activerecord/test/cases/sqlite_rake_test.rb +++ b/activerecord/test/cases/sqlite_rake_test.rb @@ -123,4 +123,26 @@ module ActiveRecord ActiveRecord::Tasks::DatabaseTasks.charset @configuration, '/rails/root' end end + + class SqliteStructureDumpTest < ActiveRecord::TestCase + def setup + @database = "db_create.sqlite3" + @configuration = { + 'adapter' => 'sqlite3', + 'database' => @database + } + end + + def test_structure_dump + dbfile = @database + filename = "awesome-file.sql" + + ActiveRecord::Tasks::DatabaseTasks.structure_dump @configuration, filename, '/rails/root' + assert File.exists?(dbfile) + assert File.exists?(filename) + ensure + FileUtils.rm(filename) + FileUtils.rm(dbfile) + end + end end -- cgit v1.2.3