aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/tasks/mysql_database_tasks.rb
blob: 16d606d6fb9f83b2525ae0d2aea43dbe9eaa8647 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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