class Lhm::Migrator

Copies existing schema and applies changes using alter on the empty table. `run` returns a Migration which can be used for the remaining process.

Attributes

conditions[R]
connection[R]
name[R]
origin[R]
renames[R]
statements[R]

Public Class Methods

new(table, connection = nil) click to toggle source
# File lib/lhm/migrator.rb, line 18
def initialize(table, connection = nil)
  @connection = connection
  @origin = table
  @name = table.destination_name
  @statements = []
  @renames = {}
end

Public Instance Methods

add_column(name, definition) click to toggle source

Add a column to a table

@example

Lhm.change_table(:users) do |m|
  m.add_column(:comment, "VARCHAR(12) DEFAULT '0'")
end

@param [String] name Name of the column to add @param [String] definition Valid SQL column definition

# File lib/lhm/migrator.rb, line 55
def add_column(name, definition)
  ddl('alter table `%s` add column `%s` %s' % [@name, name, definition])
end
add_index(columns, index_name = nil) click to toggle source

Add an index to a table

@example

Lhm.change_table(:users) do |m|
  m.add_index(:comment)
  m.add_index([:username, :created_at])
  m.add_index("comment(10)")
end

@param [String, Symbol, Array<String, Symbol>] columns

A column name given as String or Symbol. An Array of Strings or Symbols
for compound indexes. It's possible to pass a length limit.

@param [String, Symbol] index_name

Optional name of the index to be created
# File lib/lhm/migrator.rb, line 125
def add_index(columns, index_name = nil)
  ddl(index_ddl(columns, false, index_name))
end
add_unique_index(columns, index_name = nil) click to toggle source

Add a unique index to a table

@example

Lhm.change_table(:users) do |m|
  m.add_unique_index(:comment)
  m.add_unique_index([:username, :created_at])
  m.add_unique_index("comment(10)")
end

@param [String, Symbol, Array<String, Symbol>] columns

A column name given as String or Symbol. An Array of Strings or Symbols
for compound indexes. It's possible to pass a length limit.

@param [String, Symbol] index_name

Optional name of the index to be created
# File lib/lhm/migrator.rb, line 144
def add_unique_index(columns, index_name = nil)
  ddl(index_ddl(columns, true, index_name))
end
change_column(name, definition) click to toggle source

Change an existing column to a new definition

@example

Lhm.change_table(:users) do |m|
  m.change_column(:comment, "VARCHAR(12) DEFAULT '0' NOT NULL")
end

@param [String] name Name of the column to change @param [String] definition Valid SQL column definition

# File lib/lhm/migrator.rb, line 69
def change_column(name, definition)
  ddl('alter table `%s` modify column `%s` %s' % [@name, name, definition])
end
ddl(statement) click to toggle source

Alter a table with a custom statement

@example

Lhm.change_table(:users) do |m|
  m.ddl("ALTER TABLE #{m.name} ADD COLUMN age INT(11)")
end

@param [String] statement SQL alter statement @note

Don't write the table name directly into the statement. Use the #name
getter instead, because the alter statement will be executed against a
temporary table.
# File lib/lhm/migrator.rb, line 41
def ddl(statement)
  statements << statement
end
filter(sql) click to toggle source

Filter the data that is copied into the new table by the provided SQL. This SQL will be inserted into the copy directly after the “from” statement - so be sure to use inner/outer join syntax and not cross joins.

@example Add a conditions filter to the migration.

Lhm.change_table(:sounds) do |m|
  m.filter("inner join users on users.`id` = sounds.`user_id` and sounds.`public` = 1")
end

@param [ String ] sql The sql filter.

@return [ String ] The sql filter.

# File lib/lhm/migrator.rb, line 182
def filter(sql)
  @conditions = sql
end
remove_column(name) click to toggle source

Remove a column from a table

@example

Lhm.change_table(:users) do |m|
  m.remove_column(:comment)
end

@param [String] name Name of the column to delete

# File lib/lhm/migrator.rb, line 106
def remove_column(name)
  ddl('alter table `%s` drop `%s`' % [@name, name])
end
remove_index(columns, index_name = nil) click to toggle source

Remove an index from a table

@example

Lhm.change_table(:users) do |m|
  m.remove_index(:comment)
  m.remove_index([:username, :created_at])
end

@param [String, Symbol, Array<String, Symbol>] columns

A column name given as String or Symbol. An Array of Strings or Symbols
for compound indexes.

@param [String, Symbol] index_name

Optional name of the index to be removed
# File lib/lhm/migrator.rb, line 162
def remove_index(columns, index_name = nil)
  columns = [columns].flatten.map(&:to_sym)
  from_origin = @origin.indices.find { |_, cols| cols.map(&:to_sym) == columns }
  index_name ||= from_origin[0] unless from_origin.nil?
  index_name ||= idx_name(@origin.name, columns)
  ddl('drop index `%s` on `%s`' % [index_name, @name])
end
rename_column(old, nu) click to toggle source

Rename an existing column.

@example

Lhm.change_table(:users) do |m|
  m.rename_column(:login, :username)
end

@param [String] old Name of the column to change @param [String] nu New name to use for the column

# File lib/lhm/migrator.rb, line 83
def rename_column(old, nu)
  col = @origin.columns[old.to_s]

  definition = col[:type]

  definition += ' NOT NULL' unless col[:is_nullable] == "YES"
  definition += " DEFAULT #{@connection.quote(col[:column_default])}" if col[:column_default]
  definition += " COMMENT #{@connection.quote(col[:comment])}" if col[:comment]
  definition += " COLLATE #{@connection.quote(col[:collate])}" if col[:collate]

  ddl('alter table `%s` change column `%s` `%s` %s' % [@name, old, nu, definition])
  @renames[old.to_s] = nu.to_s
end

Private Instance Methods

assert_valid_idx_name(index_name) click to toggle source
# File lib/lhm/migrator.rb, line 231
def assert_valid_idx_name(index_name)
  if index_name && !(index_name.is_a?(String) || index_name.is_a?(Symbol))
    raise ArgumentError, 'index_name must be a string or symbol'
  end
end
destination_create() click to toggle source
# File lib/lhm/migrator.rb, line 212
def destination_create
  original    = %{CREATE TABLE `#{ @origin.name }`}
  replacement = %{CREATE TABLE `#{ @origin.destination_name }`}
  stmt = @origin.ddl.gsub(original, replacement)
  @connection.execute(tagged(stmt))
end
destination_read() click to toggle source
# File lib/lhm/migrator.rb, line 219
def destination_read
  Table.parse(@origin.destination_name, connection)
end
execute() click to toggle source
# File lib/lhm/migrator.rb, line 204
def execute
  destination_create
  @statements.each do |stmt|
    @connection.execute(tagged(stmt))
  end
  Migration.new(@origin, destination_read, conditions, renames)
end
index_ddl(cols, unique = nil, index_name = nil) click to toggle source
# File lib/lhm/migrator.rb, line 223
def index_ddl(cols, unique = nil, index_name = nil)
  assert_valid_idx_name(index_name)
  type = unique ? 'unique index' : 'index'
  index_name ||= idx_name(@origin.name, cols)
  parts = [type, index_name, @name, idx_spec(cols)]
  'create %s `%s` on `%s` (%s)' % parts
end
validate() click to toggle source
# File lib/lhm/migrator.rb, line 188
def validate
  unless @connection.data_source_exists?(@origin.name)
    error("could not find origin table #{ @origin.name }")
  end

  unless @origin.satisfies_id_column_requirement?
    error('origin does not satisfy `id` key requirements')
  end

  dest = @origin.destination_name

  if @connection.data_source_exists?(dest)
    error("#{ dest } should not exist; not cleaned up from previous run?")
  end
end