-
Notifications
You must be signed in to change notification settings - Fork 21.4k
/
dbconsole_command.rb
187 lines (148 loc) · 5.79 KB
/
dbconsole_command.rb
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# frozen_string_literal: true
require "active_support/core_ext/string/filters"
require "active_support/deprecation"
require "rails/command/environment_argument"
module Rails
class DBConsole
def self.start(*args)
new(*args).start
end
def initialize(options = {})
@options = options
end
def start
ENV["RAILS_ENV"] ||= @options[:environment] || environment
config = db_config.configuration_hash
case db_config.adapter
when /^(jdbc)?mysql/
args = {
host: "--host",
port: "--port",
socket: "--socket",
username: "--user",
encoding: "--default-character-set",
sslca: "--ssl-ca",
sslcert: "--ssl-cert",
sslcapath: "--ssl-capath",
sslcipher: "--ssl-cipher",
sslkey: "--ssl-key"
}.filter_map { |opt, arg| "#{arg}=#{config[opt]}" if config[opt] }
if config[:password] && @options[:include_password]
args << "--password=#{config[:password]}"
elsif config[:password] && !config[:password].to_s.empty?
args << "-p"
end
args << db_config.database
find_cmd_and_exec(["mysql", "mysql5"], *args)
when /^postgres|^postgis/
ENV["PGUSER"] = config[:username] if config[:username]
ENV["PGHOST"] = config[:host] if config[:host]
ENV["PGPORT"] = config[:port].to_s if config[:port]
ENV["PGPASSWORD"] = config[:password].to_s if config[:password] && @options[:include_password]
ENV["PGSSLMODE"] = config[:sslmode].to_s if config[:sslmode]
ENV["PGSSLCERT"] = config[:sslcert].to_s if config[:sslcert]
ENV["PGSSLKEY"] = config[:sslkey].to_s if config[:sslkey]
ENV["PGSSLROOTCERT"] = config[:sslrootcert].to_s if config[:sslrootcert]
find_cmd_and_exec("psql", db_config.database)
when "sqlite3"
args = []
args << "-#{@options[:mode]}" if @options[:mode]
args << "-header" if @options[:header]
args << File.expand_path(db_config.database, Rails.respond_to?(:root) ? Rails.root : nil)
find_cmd_and_exec("sqlite3", *args)
when "oracle", "oracle_enhanced"
logon = ""
if config[:username]
logon = config[:username].dup
logon << "/#{config[:password]}" if config[:password] && @options[:include_password]
logon << "@#{db_config.database}" if db_config.database
end
find_cmd_and_exec("sqlplus", logon)
when "sqlserver"
args = []
args += ["-d", "#{db_config.database}"] if db_config.database
args += ["-U", "#{config[:username]}"] if config[:username]
args += ["-P", "#{config[:password]}"] if config[:password]
if config[:host]
host_arg = +"tcp:#{config[:host]}"
host_arg << ",#{config[:port]}" if config[:port]
args += ["-S", host_arg]
end
find_cmd_and_exec("sqlcmd", *args)
else
abort "Unknown command-line client for #{db_config.database}."
end
end
def db_config
return @db_config if defined?(@db_config)
# If the user provided a database, use that. Otherwise find
# the first config in the database.yml
if database
@db_config = configurations.configs_for(env_name: environment, name: database, include_hidden: true)
else
@db_config = configurations.find_db_config(environment)
end
unless @db_config
missing_db = database ? "'#{database}' database is not" : "No databases are"
raise ActiveRecord::AdapterNotSpecified,
"#{missing_db} configured for '#{environment}'. Available configuration: #{configurations.inspect}"
end
@db_config
end
def environment
Rails.respond_to?(:env) ? Rails.env : Rails::Command.environment
end
def database
@options[:database]
end
private
def configurations # :doc:
require APP_PATH
ActiveRecord::Base.configurations = Rails.application.config.database_configuration
ActiveRecord::Base.configurations
end
def find_cmd_and_exec(commands, *args) # :doc:
commands = Array(commands)
dirs_on_path = ENV["PATH"].to_s.split(File::PATH_SEPARATOR)
unless (ext = RbConfig::CONFIG["EXEEXT"]).empty?
commands = commands.map { |cmd| "#{cmd}#{ext}" }
end
full_path_command = nil
found = commands.detect do |cmd|
dirs_on_path.detect do |path|
full_path_command = File.join(path, cmd)
begin
stat = File.stat(full_path_command)
rescue SystemCallError
else
stat.file? && stat.executable?
end
end
end
if found
exec full_path_command, *args
else
abort("Couldn't find database client: #{commands.join(', ')}. Check your $PATH and try again.")
end
end
end
module Command
class DbconsoleCommand < Base # :nodoc:
include EnvironmentArgument
class_option :include_password, aliases: "-p", type: :boolean,
desc: "Automatically provide the password from database.yml"
class_option :mode, enum: %w( html list line column ), type: :string,
desc: "Automatically put the sqlite3 database in the specified mode (html, list, line, column)."
class_option :header, type: :boolean
class_option :database, aliases: "--db", type: :string,
desc: "Specifies the database to use."
def perform
extract_environment_option_from_argument
# RAILS_ENV needs to be set before config/application is required.
ENV["RAILS_ENV"] = options[:environment]
require_application_and_environment!
Rails::DBConsole.start(options)
end
end
end
end