diff options
Diffstat (limited to 'activerecord/lib/active_record/tasks')
4 files changed, 207 insertions, 187 deletions
diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index e3e665e149..1423e6008f 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -1,4 +1,4 @@ -require 'active_support/core_ext/string/filters' +require "active_support/core_ext/string/filters" module ActiveRecord module Tasks # :nodoc: @@ -35,15 +35,25 @@ module ActiveRecord # # DatabaseTasks.create_current('production') 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 attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader attr_accessor :database_configuration - LOCAL_HOSTS = ['127.0.0.1', 'localhost'] + LOCAL_HOSTS = ["127.0.0.1", "localhost"] def check_protected_environments! - unless ENV['DISABLE_DATABASE_ENVIRONMENT_CHECK'] + unless ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"] current = ActiveRecord::Migrator.current_environment stored = ActiveRecord::Migrator.last_stored_environment @@ -72,15 +82,15 @@ module ActiveRecord end def migrations_paths - @migrations_paths ||= Rails.application.paths['db/migrate'].to_a + @migrations_paths ||= Rails.application.paths["db/migrate"].to_a end def fixtures_path - @fixtures_path ||= if ENV['FIXTURES_PATH'] - File.join(root, ENV['FIXTURES_PATH']) - else - File.join(root, 'test', 'fixtures') - end + @fixtures_path ||= if ENV["FIXTURES_PATH"] + File.join(root, ENV["FIXTURES_PATH"]) + else + File.join(root, "test", "fixtures") + end end def root @@ -96,7 +106,7 @@ module ActiveRecord end def current_config(options = {}) - options.reverse_merge! :env => env + options.reverse_merge! env: env if options.has_key?(:config) @current_config = options[:config] else @@ -106,7 +116,7 @@ module ActiveRecord def create(*arguments) configuration = arguments.first - class_for_adapter(configuration['adapter']).new(*arguments).create + class_for_adapter(configuration["adapter"]).new(*arguments).create $stdout.puts "Created database '#{configuration['database']}'" rescue DatabaseAlreadyExists $stderr.puts "Database '#{configuration['database']}' already exists" @@ -133,7 +143,7 @@ module ActiveRecord def drop(*arguments) configuration = arguments.first - class_for_adapter(configuration['adapter']).new(*arguments).drop + class_for_adapter(configuration["adapter"]).new(*arguments).drop $stdout.puts "Dropped database '#{configuration['database']}'" rescue ActiveRecord::NoDatabaseError $stderr.puts "Database '#{configuration['database']}' does not exist" @@ -156,7 +166,7 @@ module ActiveRecord def migrate verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil - scope = ENV['SCOPE'] + scope = ENV["SCOPE"] verbose_was, Migration.verbose = Migration.verbose, verbose Migrator.migrate(migrations_paths, version) do |migration| scope.blank? || scope == migration.scope @@ -172,7 +182,7 @@ module ActiveRecord def charset(*arguments) configuration = arguments.first - class_for_adapter(configuration['adapter']).new(*arguments).charset + class_for_adapter(configuration["adapter"]).new(*arguments).charset end def collation_current(environment = env) @@ -181,11 +191,11 @@ module ActiveRecord def collation(*arguments) configuration = arguments.first - class_for_adapter(configuration['adapter']).new(*arguments).collation + class_for_adapter(configuration["adapter"]).new(*arguments).collation end def purge(configuration) - class_for_adapter(configuration['adapter']).new(configuration).purge + class_for_adapter(configuration["adapter"]).new(configuration).purge end def purge_all @@ -204,13 +214,13 @@ module ActiveRecord def structure_dump(*arguments) configuration = arguments.first 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 def structure_load(*arguments) configuration = arguments.first 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 def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc: @@ -231,14 +241,6 @@ module ActiveRecord ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.current_environment end - def load_schema_for(*args) - ActiveSupport::Deprecation.warn(<<-MSG.squish) - This method was renamed to `#load_schema` and will be removed in the future. - Use `#load_schema` instead. - MSG - load_schema(*args) - end - def schema_file(format = ActiveRecord::Base.schema_format) case format when :ruby @@ -273,41 +275,51 @@ module ActiveRecord end end + # Dumps the schema cache in YAML format for the connection into the file + # + # ==== Examples: + # ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.connection, "tmp/schema_dump.yaml") + def dump_schema_cache(conn, filename) + conn.schema_cache.clear! + conn.data_sources.each { |table| conn.schema_cache.add(table) } + open(filename, "wb") { |f| f.write(YAML.dump(conn.schema_cache)) } + end + private - def class_for_adapter(adapter) - key = @tasks.keys.detect { |pattern| adapter[pattern] } - unless key - raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter" + def class_for_adapter(adapter) + key = @tasks.keys.detect { |pattern| adapter[pattern] } + unless key + raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter" + end + @tasks[key] end - @tasks[key] - end - def each_current_configuration(environment) - environments = [environment] - environments << 'test' if environment == 'development' + def each_current_configuration(environment) + environments = [environment] + environments << "test" if environment == "development" - configurations = ActiveRecord::Base.configurations.values_at(*environments) - configurations.compact.each do |configuration| - yield configuration unless configuration['database'].blank? + configurations = ActiveRecord::Base.configurations.values_at(*environments) + configurations.compact.each do |configuration| + yield configuration unless configuration["database"].blank? + end end - end - def each_local_configuration - ActiveRecord::Base.configurations.each_value do |configuration| - next unless configuration['database'] + def each_local_configuration + ActiveRecord::Base.configurations.each_value do |configuration| + next unless configuration["database"] - if local_database?(configuration) - yield configuration - else - $stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host." + if local_database?(configuration) + yield configuration + else + $stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host." + end end end - end - def local_database?(configuration) - configuration['host'].blank? || LOCAL_HOSTS.include?(configuration['host']) - end + def local_database?(configuration) + configuration["host"].blank? || LOCAL_HOSTS.include?(configuration["host"]) + end end end end diff --git a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb index b1a0ad0115..920830b9cf 100644 --- a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb @@ -11,10 +11,10 @@ module ActiveRecord def create establish_connection configuration_without_database - connection.create_database configuration['database'], creation_options + connection.create_database configuration["database"], creation_options establish_connection configuration rescue ActiveRecord::StatementInvalid => error - if /database exists/ === error.message + if error.message.include?("database exists") raise DatabaseAlreadyExists else raise @@ -23,26 +23,26 @@ module ActiveRecord if error.respond_to?(:errno) && error.errno == ACCESS_DENIED_ERROR $stdout.print error.message establish_connection root_configuration_without_database - connection.create_database configuration['database'], creation_options - if configuration['username'] != 'root' - connection.execute grant_statement.gsub(/\s+/, ' ').strip + connection.create_database configuration["database"], creation_options + if configuration["username"] != "root" + connection.execute grant_statement.gsub(/\s+/, " ").strip end establish_connection configuration else $stderr.puts error.inspect $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['encoding'] + $stderr.puts "(If you set the charset manually, make sure you have a matching collation)" if configuration["encoding"] end end def drop establish_connection configuration - connection.drop_database configuration['database'] + connection.drop_database configuration["database"] end def purge establish_connection configuration - connection.recreate_database configuration['database'], creation_options + connection.recreate_database configuration["database"], creation_options end def charset @@ -53,100 +53,102 @@ module ActiveRecord connection.collation end - def structure_dump(filename) + def structure_dump(filename, extra_flags) args = prepare_command_options args.concat(["--result-file", "#{filename}"]) args.concat(["--no-data"]) args.concat(["--routines"]) args.concat(["--skip-comments"]) + args.concat(Array(extra_flags)) if extra_flags args.concat(["#{configuration['database']}"]) - run_cmd('mysqldump', args, 'dumping') + run_cmd("mysqldump", args, "dumping") end - def structure_load(filename) + def structure_load(filename, extra_flags) 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(Array(extra_flags)) if extra_flags - run_cmd('mysql', args, 'loading') + run_cmd("mysql", args, "loading") end private - def configuration - @configuration - end + def configuration + @configuration + end - def configuration_without_database - configuration.merge('database' => nil) - end + def configuration_without_database + configuration.merge("database" => nil) + end - def creation_options - Hash.new.tap do |options| - options[:charset] = configuration['encoding'] if configuration.include? 'encoding' - options[:collation] = configuration['collation'] if configuration.include? 'collation' + def creation_options + Hash.new.tap do |options| + options[:charset] = configuration["encoding"] if configuration.include? "encoding" + options[:collation] = configuration["collation"] if configuration.include? "collation" + end end - end - def error_class - if configuration['adapter'] =~ /jdbc/ - require 'active_record/railties/jdbcmysql_error' - ArJdbcMySQL::Error - elsif defined?(Mysql2) - Mysql2::Error - else - StandardError + def error_class + if configuration["adapter"].include?("jdbc") + require "active_record/railties/jdbcmysql_error" + ArJdbcMySQL::Error + elsif defined?(Mysql2) + Mysql2::Error + else + StandardError + end end - end - def grant_statement - <<-SQL + def grant_statement + <<-SQL GRANT ALL PRIVILEGES ON #{configuration['database']}.* TO '#{configuration['username']}'@'localhost' IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION; - SQL - end + SQL + end - def root_configuration_without_database - configuration_without_database.merge( - 'username' => 'root', - 'password' => root_password - ) - end + def root_configuration_without_database + configuration_without_database.merge( + "username" => "root", + "password" => root_password + ) + end - def root_password - $stdout.print "Please provide the root password for your MySQL installation\n>" - $stdin.gets.strip - end + def root_password + $stdout.print "Please provide the root password for your MySQL installation\n>" + $stdin.gets.strip + end - def prepare_command_options - args = { - 'host' => '--host', - 'port' => '--port', - 'socket' => '--socket', - 'username' => '--user', - 'password' => '--password', - 'encoding' => '--default-character-set', - 'sslca' => '--ssl-ca', - 'sslcert' => '--ssl-cert', - 'sslcapath' => '--ssl-capath', - 'sslcipher' => '--ssl-cipher', - 'sslkey' => '--ssl-key' - }.map { |opt, arg| "#{arg}=#{configuration[opt]}" if configuration[opt] }.compact - - args - end + def prepare_command_options + args = { + "host" => "--host", + "port" => "--port", + "socket" => "--socket", + "username" => "--user", + "password" => "--password", + "encoding" => "--default-character-set", + "sslca" => "--ssl-ca", + "sslcert" => "--ssl-cert", + "sslcapath" => "--ssl-capath", + "sslcipher" => "--ssl-cipher", + "sslkey" => "--ssl-key" + }.map { |opt, arg| "#{arg}=#{configuration[opt]}" if configuration[opt] }.compact + + args + end - def run_cmd(cmd, args, action) - fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args) - end + def run_cmd(cmd, args, action) + fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args) + end - def run_cmd_error(cmd, args, action) - msg = "failed to execute: `#{cmd}`\n" - msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n" - msg - end + def run_cmd_error(cmd, args, action) + msg = "failed to execute: `#{cmd}`\n" + msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n" + msg + end end end end diff --git a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb index b19ab57ee4..5155ced0e2 100644 --- a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb @@ -1,8 +1,8 @@ module ActiveRecord module Tasks # :nodoc: class PostgreSQLDatabaseTasks # :nodoc: - DEFAULT_ENCODING = ENV['CHARSET'] || 'utf8' - ON_ERROR_STOP_1 = 'ON_ERROR_STOP=1'.freeze + DEFAULT_ENCODING = ENV["CHARSET"] || "utf8" + ON_ERROR_STOP_1 = "ON_ERROR_STOP=1".freeze delegate :connection, :establish_connection, :clear_active_connections!, to: ActiveRecord::Base @@ -13,11 +13,11 @@ module ActiveRecord def create(master_established = false) establish_master_connection unless master_established - connection.create_database configuration['database'], - configuration.merge('encoding' => encoding) + connection.create_database configuration["database"], + configuration.merge("encoding" => encoding) establish_connection configuration rescue ActiveRecord::StatementInvalid => error - if /database .* already exists/ === error.message + if /database .* already exists/.match?(error.message) raise DatabaseAlreadyExists else raise @@ -26,7 +26,7 @@ module ActiveRecord def drop establish_master_connection - connection.drop_database configuration['database'] + connection.drop_database configuration["database"] end def charset @@ -43,69 +43,73 @@ module ActiveRecord create true end - def structure_dump(filename) + def structure_dump(filename, extra_flags) set_psql_env - search_path = case ActiveRecord::Base.dump_schemas - when :schema_search_path - configuration['schema_search_path'] - when :all - nil - when String - ActiveRecord::Base.dump_schemas - end + search_path = \ + case ActiveRecord::Base.dump_schemas + when :schema_search_path + configuration["schema_search_path"] + when :all + nil + when String + ActiveRecord::Base.dump_schemas + 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? - args += search_path.split(',').map do |part| + args += search_path.split(",").map do |part| "--schema=#{part.strip}" end end - args << configuration['database'] - run_cmd('pg_dump', args, 'dumping') + args << configuration["database"] + run_cmd("pg_dump", args, "dumping") File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" } end - def structure_load(filename) + def structure_load(filename, extra_flags) set_psql_env - args = [ '-v', ON_ERROR_STOP_1, '-q', '-f', filename, configuration['database'] ] - run_cmd('psql', args, 'loading' ) + 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") end private - def configuration - @configuration - end + def configuration + @configuration + end - def encoding - configuration['encoding'] || DEFAULT_ENCODING - end + def encoding + configuration["encoding"] || DEFAULT_ENCODING + end - def establish_master_connection - establish_connection configuration.merge( - 'database' => 'postgres', - 'schema_search_path' => 'public' - ) - end + def establish_master_connection + establish_connection configuration.merge( + "database" => "postgres", + "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 + 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 - def run_cmd(cmd, args, action) - fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args) - end + def run_cmd(cmd, args, action) + fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args) + end - def run_cmd_error(cmd, args, action) - msg = "failed to execute:\n" - msg << "#{cmd} #{args.join(' ')}\n\n" - msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n" - msg - end + def run_cmd_error(cmd, args, action) + msg = "failed to execute:\n" + msg << "#{cmd} #{args.join(' ')}\n\n" + msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n" + msg + 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 9ec3c8a94a..1f756c2979 100644 --- a/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb @@ -8,20 +8,20 @@ module ActiveRecord end def create - raise DatabaseAlreadyExists if File.exist?(configuration['database']) + raise DatabaseAlreadyExists if File.exist?(configuration["database"]) establish_connection configuration connection end def drop - require 'pathname' - path = Pathname.new configuration['database'] + require "pathname" + path = Pathname.new configuration["database"] file = path.absolute? ? path.to_s : File.join(root, path) FileUtils.rm(file) rescue Errno::ENOENT => error - raise NoDatabaseError.new(error.message, error) + raise NoDatabaseError.new(error.message) end def purge @@ -35,25 +35,27 @@ module ActiveRecord connection.encoding end - def structure_dump(filename) - dbfile = configuration['database'] - `sqlite3 #{dbfile} .schema > #{filename}` + def structure_dump(filename, extra_flags) + dbfile = configuration["database"] + flags = extra_flags.join(" ") if extra_flags + `sqlite3 #{flags} #{dbfile} .schema > #{filename}` end - def structure_load(filename) - dbfile = configuration['database'] - `sqlite3 #{dbfile} < "#{filename}"` + def structure_load(filename, extra_flags) + dbfile = configuration["database"] + flags = extra_flags.join(" ") if extra_flags + `sqlite3 #{flags} #{dbfile} < "#{filename}"` end private - def configuration - @configuration - end + def configuration + @configuration + end - def root - @root - end + def root + @root + end end end end |