lib/departure/cli_generator.rb in departure-1.0.1 vs lib/departure/cli_generator.rb in departure-2.0.0
- old
+ new
@@ -1,51 +1,38 @@
+require 'departure/dsn'
+require 'departure/option'
require 'departure/alter_argument'
+require 'departure/connection_details'
+require 'departure/user_options'
module Departure
- # Represents the 'DSN' argument of Percona's pt-online-schema-change
- # See https://www.percona.com/doc/percona-toolkit/2.0/pt-online-schema-change.html#dsn-options
- class DSN
-
- # Constructor
- #
- # @param database [String, Symbol]
- # @param table_name [String, Symbol]
- def initialize(database, table_name)
- @database = database
- @table_name = table_name
- end
-
- # Returns the pt-online-schema-change DSN string. See
- # https://www.percona.com/doc/percona-toolkit/2.0/pt-online-schema-change.html#dsn-options
- def to_s
- "D=#{database},t=#{table_name}"
- end
-
- private
-
- attr_reader :table_name, :database
- end
-
# Generates the equivalent Percona's pt-online-schema-change command to the
# given SQL statement
- class CliGenerator # Command
- BASE_COMMAND = 'pt-online-schema-change'
- BASE_OPTIONS = %w(
- --execute
- --statistics
- --recursion-method=none
- --alter-foreign-keys-method=auto
- )
+ #
+ # --no-check-alter is used to allow running CHANGE COLUMN statements. For
+ # more details, check: www.percona.com/doc/percona-toolkit/2.2/pt-online-schema-change.html#cmdoption-pt-online-schema-change--[no]check-alter
+ #
+ class CliGenerator
+ COMMAND_NAME = 'pt-online-schema-change'.freeze
+ DEFAULT_OPTIONS = Set.new(
+ [
+ Option.new('execute'),
+ Option.new('statistics'),
+ Option.new('alter-foreign-keys-method', 'auto'),
+ Option.new('no-check-alter')
+ ]
+ ).freeze
- # Constructor
+ # TODO: Better doc.
#
+ # Constructor. Specify any arguments to pass to pt-online-schema-change
+ # passing the PERCONA_ARGS env var when executing the migration
+ #
# @param connection_data [Hash]
- def initialize(connection_data)
- @connection_data = connection_data
- init_base_command
- add_connection_details
+ def initialize(connection_details)
+ @connection_details = connection_details
end
# Generates the percona command. Fills all the connection credentials from
# the current AR connection, but that can be amended via ENV-vars:
# PERCONA_DB_HOST, PERCONA_DB_USER, PERCONA_DB_PASSWORD, PERCONA_DB_NAME
@@ -55,13 +42,13 @@
# @param table_name [String]
# @param statement [String] MySQL statement
# @return [String]
def generate(table_name, statement)
alter_argument = AlterArgument.new(statement)
- dsn = DSN.new(database, table_name)
+ dsn = DSN.new(connection_details.database, table_name)
- "#{self} #{dsn} #{alter_argument}"
+ "#{command} #{all_options} #{dsn} #{alter_argument}"
end
# Generates the percona command for a raw MySQL statement. Fills all the
# connection credentials from the current AR connection, but that can
# amended via ENV-vars: PERCONA_DB_HOST, PERCONA_DB_USER,
@@ -70,65 +57,29 @@
#
# @param statement [String] MySQL statement
# @return [String]
def parse_statement(statement)
alter_argument = AlterArgument.new(statement)
- dsn = DSN.new(database, alter_argument.table_name)
+ dsn = DSN.new(connection_details.database, alter_argument.table_name)
- "#{self} #{dsn} #{alter_argument}"
+ "#{command} #{all_options} #{dsn} #{alter_argument}"
end
private
- attr_reader :connection_data
+ attr_reader :connection_details
- # Sets up the command with its options
- def init_base_command
- @command = [BASE_COMMAND, BASE_OPTIONS.join(' ')]
+ def command
+ "#{COMMAND_NAME} #{connection_details}"
end
- # Adds the host, user and password, if present, to the command
- def add_connection_details
- @command.push("-h #{host}")
- @command.push("-u #{user}")
- @command.push("-p #{password}") if password.present?
- end
-
- # Returns the command as a string that can be executed in a shell
+ # Returns all the arguments to execute pt-online-schema-change with
#
# @return [String]
- def to_s
- @command.join(' ')
- end
-
- # Returns the database host name, defaulting to localhost. If PERCONA_DB_HOST
- # is passed its value will be used instead
- #
- # @return [String]
- def host
- ENV['PERCONA_DB_HOST'] || connection_data[:host] || 'localhost'
- end
-
- # Returns the database user. If PERCONA_DB_USER is passed its value will be
- # used instead
- #
- # @return [String]
- def user
- ENV['PERCONA_DB_USER'] || connection_data[:username]
- end
-
- # Returns the database user's password. If PERCONA_DB_PASSWORD is passed its
- # value will be used instead
- #
- # @return [String]
- def password
- ENV['PERCONA_DB_PASSWORD'] || connection_data[:password]
- end
-
- # TODO: Doesn't the abstract adapter already handle this somehow?
- # Returns the database name. If PERCONA_DB_NAME is passed its value will be
- # used instead
- def database
- ENV['PERCONA_DB_NAME'] || connection_data[:database]
+ def all_options
+ env_variable_options = UserOptions.new
+ global_configuration_options = UserOptions.new(Departure.configuration.global_percona_args)
+ options = env_variable_options.merge(global_configuration_options).merge(DEFAULT_OPTIONS)
+ options.to_a.join(' ')
end
end
end