Skip to content

Commit

Permalink
Merge pull request trilogy-libraries#55 from lorint/add_dbconsole_sup…
Browse files Browse the repository at this point in the history
…port

Fixes trilogy-libraries#53 - Implement dbconsole support
  • Loading branch information
bensheldon authored Jul 18, 2023
2 parents de1f8d0 + b1a9b23 commit c85a2b2
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 0 deletions.
60 changes: 60 additions & 0 deletions lib/active_record/connection_adapters/trilogy_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,38 @@ def translate_connect_error(config, error)
end
end

def dbconsole(config, options = {})
mysql_config = if ActiveRecord.version < ::Gem::Version.new('6.1.a')
config.config
else
config.configuration_hash
end

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",
ssl_mode: "--ssl-mode"
}.filter_map { |opt, arg| "#{arg}=#{mysql_config[opt]}" if mysql_config[opt] }

if mysql_config[:password] && options[:include_password]
args << "--password=#{mysql_config[:password]}"
elsif mysql_config[:password] && !mysql_config[:password].to_s.empty?
args << "-p"
end

args << mysql_config[:database]

find_cmd_and_exec(["mysql", "mysql5"], *args)
end

private
def initialize_type_map(m)
super if ActiveRecord.version >= ::Gem::Version.new('7.0.a')
Expand Down Expand Up @@ -207,6 +239,34 @@ def discard!
end
end

def self.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

private
def text_type?(type)
TYPE_MAP.lookup(type).is_a?(Type::String) || TYPE_MAP.lookup(type).is_a?(Type::Text)
Expand Down
43 changes: 43 additions & 0 deletions lib/trilogy_adapter/rails/dbconsole.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# frozen_string_literal: true

module TrilogyAdapter
module Rails
module DBConsole
class AdapterAdapter < SimpleDelegator
def adapter
"mysql"
end
end

def db_config
if super.adapter == "trilogy"
AdapterAdapter.new(super)
else
super
end
end
end
end
end

module Rails
class DBConsole
# require "rails/commands/dbconsole/dbconsole_command"
if ActiveRecord.version < ::Gem::Version.new('6.1.a')
alias _brick_start start
def start
ENV["RAILS_ENV"] ||= @options[:environment] || environment

if config["adapter"] == "trilogy"
begin
::ActiveRecord::ConnectionAdapters::TrilogyAdapter.dbconsole(config, @options)
rescue NotImplementedError
abort "Unknown command-line client for #{db_config.database}."
end
else
_brick_start
end
end
end
end
end
81 changes: 81 additions & 0 deletions test/lib/trilogy_adapter/dbconsole_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# frozen_string_literal: true

require "active_support/testing/method_call_assertions"

module ActiveRecord
class TrilogyTestCase < TestCase
def self.run(*args)
super
end
end

module ConnectionAdapters
class TrilogyDbConsoleTest < ActiveRecord::TrilogyTestCase
include ActiveSupport::Testing::MethodCallAssertions

def test_trilogy
config = make_db_config(adapter: "trilogy", database: "db")

assert_find_cmd_and_exec_called_with([%w[mysql mysql5], "db"]) do
TrilogyAdapter.dbconsole(config)
end
end

def test_mysql_full
config = make_db_config(
adapter: "trilogy",
database: "db",
host: "localhost",
port: 1234,
socket: "socket",
username: "user",
password: "qwerty",
encoding: "UTF-8",
sslca: "/path/to/ca-cert.pem",
sslcert: "/path/to/client-cert.pem",
sslcapath: "/path/to/cacerts",
sslcipher: "DHE-RSA-AES256-SHA",
sslkey: "/path/to/client-key.pem",
ssl_mode: "VERIFY_IDENTITY"
)

args = [
%w[mysql mysql5],
"--host=localhost",
"--port=1234",
"--socket=socket",
"--user=user",
"--default-character-set=UTF-8",
"--ssl-ca=/path/to/ca-cert.pem",
"--ssl-cert=/path/to/client-cert.pem",
"--ssl-capath=/path/to/cacerts",
"--ssl-cipher=DHE-RSA-AES256-SHA",
"--ssl-key=/path/to/client-key.pem",
"--ssl-mode=VERIFY_IDENTITY",
"-p", "db"
]

assert_find_cmd_and_exec_called_with(args) do
TrilogyAdapter.dbconsole(config)
end
end

def test_mysql_include_password
config = make_db_config(adapter: "trilogy", database: "db", username: "user", password: "qwerty")

assert_find_cmd_and_exec_called_with([%w[mysql mysql5], "--user=user", "--password=qwerty", "db"]) do
TrilogyAdapter.dbconsole(config, include_password: true)
end
end

private
def make_db_config(config)
ActiveRecord::DatabaseConfigurations::HashConfig.new("test", "primary", config)
end

def assert_find_cmd_and_exec_called_with(args, &block)
assert_called_with(TrilogyAdapter, :find_cmd_and_exec, args, &block)
end
end
end
end

0 comments on commit c85a2b2

Please sign in to comment.