diff options
Diffstat (limited to 'activerecord/lib')
5 files changed, 110 insertions, 37 deletions
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index c6dc7db2e8..3b37b001f7 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -141,6 +141,8 @@ module ActiveRecord extend ActiveSupport::Autoload autoload :DatabaseTasks + autoload :SQLiteDatabaseTasks, 'active_record/tasks/sqlite_database_tasks' + autoload :MySQLDatabaseTasks, 'active_record/tasks/mysql_database_tasks' end autoload :TestCase diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index b44d479fb6..662c84bfda 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -59,36 +59,7 @@ db_namespace = namespace :db do rescue case config['adapter'] when /mysql/ - if config['adapter'] =~ /jdbc/ - #FIXME After Jdbcmysql gives this class - require 'active_record/railties/jdbcmysql_error' - error_class = ArJdbcMySQL::Error - else - error_class = config['adapter'] =~ /mysql2/ ? Mysql2::Error : Mysql::Error - end - access_denied_error = 1045 - begin - ActiveRecord::Base.establish_connection(config.merge('database' => nil)) - ActiveRecord::Base.connection.create_database(config['database'], mysql_creation_options(config)) - ActiveRecord::Base.establish_connection(config) - rescue error_class => sqlerr - if sqlerr.errno == access_denied_error - print "#{sqlerr.error}. \nPlease provide the root password for your mysql installation\n>" - root_password = $stdin.gets.strip - grant_statement = "GRANT ALL PRIVILEGES ON #{config['database']}.* " \ - "TO '#{config['username']}'@'localhost' " \ - "IDENTIFIED BY '#{config['password']}' WITH GRANT OPTION;" - ActiveRecord::Base.establish_connection(config.merge( - 'database' => nil, 'username' => 'root', 'password' => root_password)) - ActiveRecord::Base.connection.create_database(config['database'], mysql_creation_options(config)) - ActiveRecord::Base.connection.execute grant_statement - ActiveRecord::Base.establish_connection(config) - else - $stderr.puts sqlerr.error - $stderr.puts "Couldn't create database for #{config.inspect}, charset: #{config['charset'] || @charset}, collation: #{config['collation'] || @collation}" - $stderr.puts "(if you set the charset manually, make sure you have a matching collation)" if config['charset'] - end - end + ActiveRecord::Tasks::DatabaseTasks.create config when /postgresql/ @encoding = config['encoding'] || ENV['CHARSET'] || 'utf8' begin diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index a72ec0175b..d0d3ea12dd 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -1,14 +1,19 @@ class ActiveRecord::Tasks::DatabaseTasks - def self.create(configuration) - if File.exist?(configuration['database']) - $stderr.puts "#{configuration['database']} already exists" - return - end + TASKS_PATTERNS = { + /mysql/ => ActiveRecord::Tasks::MySQLDatabaseTasks, + # /postgresql/ => ActiveRecord::Tasks::PostgreSQLTasker, + /sqlite/ => ActiveRecord::Tasks::SQLiteDatabaseTasks + } - ActiveRecord::Base.establish_connection(configuration) - ActiveRecord::Base.connection + def self.create(configuration) + class_for_adapter(configuration['adapter']).new(configuration).create rescue Exception => e $stderr.puts e, *(e.backtrace) $stderr.puts "Couldn't create database for #{configuration.inspect}" end + + def self.class_for_adapter(adapter) + key = TASKS_PATTERNS.keys.detect { |key| adapter[key] } + TASKS_PATTERNS[key] + end end diff --git a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb new file mode 100644 index 0000000000..16d606d6fb --- /dev/null +++ b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb @@ -0,0 +1,76 @@ +class ActiveRecord::Tasks::MySQLDatabaseTasks + DEFAULT_CHARSET = ENV['CHARSET'] || 'utf8' + DEFAULT_COLLATION = ENV['COLLATION'] || 'utf8_unicode_ci' + ACCESS_DENIED_ERROR = 1045 + + delegate :connection, :establish_connection, :to => ActiveRecord::Base + + def initialize(configuration) + @configuration = configuration + end + + def create + establish_connection configuration_without_database + connection.create_database configuration['database'], creation_options + establish_connection configuration + rescue error_class => error + raise error unless error.errno == ACCESS_DENIED_ERROR + + $stdout.print error.error + establish_connection root_configuration_without_database + connection.create_database configuration['database'], creation_options + connection.execute grant_statement.gsub(/\s+/, ' ').strip + establish_connection configuration + 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'] + end + + private + + attr_reader :configuration + + def configuration_without_database + configuration.merge('database' => nil) + end + + def creation_options + { + :charset => (configuration['charset'] || DEFAULT_CHARSET), + :collation => (configuration['collation'] || DEFAULT_COLLATION) + } + end + + def error_class + case configuration['adapter'] + when /jdbc/ + require 'active_record/railties/jdbcmysql_error' + error_class = ArJdbcMySQL::Error + when /mysql2/ + Mysql2::Error + else + Mysql::Error + end + end + + def grant_statement + <<-SQL +GRANT ALL PRIVILEGES ON #{configuration['database']}.* + TO '#{configuration['username']}'@'localhost' +IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION; + SQL + 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 +end diff --git a/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb b/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb new file mode 100644 index 0000000000..882a4f98a9 --- /dev/null +++ b/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb @@ -0,0 +1,19 @@ +class ActiveRecord::Tasks::SQLiteDatabaseTasks + def initialize(configuration) + @configuration = configuration + end + + def create + if File.exist?(configuration['database']) + $stderr.puts "#{configuration['database']} already exists" + return + end + + ActiveRecord::Base.establish_connection(configuration) + ActiveRecord::Base.connection + end + + private + + attr_reader :configuration +end |