add_index and remove_index Now Quiet on Duplicate Index

UPDATE: added support for remove_index :users, :name=>:index_name

Mysql::Error: Duplicate key name ‘index_xxx’: CREATE INDEX `index_xxx` ON `users` (`xxx`) ?
Mysql::Error: Can’t DROP ‘index_xxx’; check that column/key exists: DROP INDEX `index_xxx` ON users ?
nevermore!

class TestAddRemoveIndex < ActiveRecord::Migration
  def self.up
    add_index :users, [:a, :b], :quiet=>true
    add_index :users, [:a, :b], :quiet=>true
  end

  def self.down
    remove_index :users, [:a, :b], :quiet=>true
    remove_index :users, [:a, :b], :quiet=>true
  end
end

These patches allow you to add indices in a migration that will only be created if they do not already exist, or to remove indices only if they already exist through :quiet=>true.

module ActiveRecord::ConnectionAdapters::SchemaStatements

  def add_index_with_quiet(table_name, column_names, options = {})
    quiet = options.delete(:quiet)
    add_index_without_quiet table_name, column_names, options
  rescue
    raise unless quiet and $!.message =~ /^Mysql::Error: Duplicate key name/i
    puts "Failed to create index #{table_name} #{column_names.inspect} #{options.inspect}"
  end
  alias_method_chain :add_index, :quiet

  def remove_index_with_quiet(table_name, *args)
    options = args.extract_options!
    quiet = options.delete(:quiet)
    if args.empty?
      remove_index_without_quiet table_name, options
    else
      remove_index_without_quiet table_name, *args
    end
  rescue
  rescue
    raise unless quiet and $!.message =~ /^Mysql::Error: Can't DROP/i
    puts "Failed to drop index #{table_name} #{(args[1]||options[:name]).inspect}"
  end
  alias_method_chain :remove_index, :quiet

end

One thought on “add_index and remove_index Now Quiet on Duplicate Index

Leave a comment