Skip to content

Commit

Permalink
Merge pull request #37168 from eugeneius/remove_index_column_names_wi…
Browse files Browse the repository at this point in the history
…th_options

Accept columns passed with options in remove_index
  • Loading branch information
kaspth committed Sep 10, 2019
2 parents ae2cbf4 + 0cc13d3 commit da54c73
Show file tree
Hide file tree
Showing 12 changed files with 86 additions and 36 deletions.
17 changes: 17 additions & 0 deletions activerecord/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
* Allow column names to be passed to `remove_index` positionally along with other options.

Passing other options can be necessary to make `remove_index` correctly reversible.

Before:

add_index :reports, :report_id # => works
add_index :reports, :report_id, unique: true # => works
remove_index :reports, :report_id # => works
remove_index :reports, :report_id, unique: true # => ArgumentError

After:

remove_index :reports, :report_id, unique: true # => works

*Eugene Kenny*

* Allow bulk `ALTER` statements to drop and recreate indexes with the same name.

*Eugene Kenny*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -631,10 +631,11 @@ def remove(*column_names)
# t.remove_index(:branch_id)
# t.remove_index(column: [:branch_id, :party_id])
# t.remove_index(name: :by_branch_party)
# t.remove_index(:branch_id, name: :by_branch_party)
#
# See {connection.remove_index}[rdoc-ref:SchemaStatements#remove_index]
def remove_index(options = {})
@base.remove_index(name, options)
def remove_index(column_name = nil, options = {})
@base.remove_index(name, column_name, options)
end

# Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,10 @@ def add_index(table_name, column_name, options = {})
#
# remove_index :accounts, name: :by_branch_party
#
# Removes the index on +branch_id+ named +by_branch_party+ in the +accounts+ table.
#
# remove_index :accounts, :branch_id, name: :by_branch_party
#
# Removes the index named +by_branch_party+ in the +accounts+ table +concurrently+.
#
# remove_index :accounts, name: :by_branch_party, algorithm: :concurrently
Expand All @@ -816,8 +820,8 @@ def add_index(table_name, column_name, options = {})
# Concurrently removing an index is not supported in a transaction.
#
# For more information see the {"Transactional Migrations" section}[rdoc-ref:Migration].
def remove_index(table_name, options = {})
index_name = index_name_for_remove(table_name, options)
def remove_index(table_name, column_name = nil, options = {})
index_name = index_name_for_remove(table_name, column_name, options)
execute "DROP INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)}"
end

Expand Down Expand Up @@ -1265,17 +1269,18 @@ def quoted_columns_for_index(column_names, **options)
add_options_for_index_columns(quoted_columns, **options).values
end

def index_name_for_remove(table_name, options = {})
return options[:name] if can_remove_index_by_name?(options)
def index_name_for_remove(table_name, column_name, options)
if column_name.is_a?(Hash)
options = column_name.dup
column_name = options.delete(:column)
end

return options[:name] if can_remove_index_by_name?(column_name, options)

checks = []

if options.is_a?(Hash)
checks << lambda { |i| i.name == options[:name].to_s } if options.key?(:name)
column_names = index_column_names(options[:column])
else
column_names = index_column_names(options)
end
checks << lambda { |i| i.name == options[:name].to_s } if options.key?(:name)
column_names = index_column_names(column_name)

if column_names.present?
checks << lambda { |i| index_name(table_name, i.columns) == index_name(table_name, column_names) }
Expand Down Expand Up @@ -1406,8 +1411,8 @@ def extract_new_default_value(default_or_changes)
end
alias :extract_new_comment_value :extract_new_default_value

def can_remove_index_by_name?(options)
options.is_a?(Hash) && options.key?(:name) && options.except(:name, :algorithm).empty?
def can_remove_index_by_name?(column_name, options)
column_name.nil? && options.key?(:name) && options.except(:name, :algorithm).empty?
end

def bulk_change_table(table_name, operations)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -668,8 +668,8 @@ def add_index_for_alter(table_name, column_name, options = {})
"ADD #{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})#{index_algorithm}"
end

def remove_index_for_alter(table_name, options = {})
index_name = index_name_for_remove(table_name, options)
def remove_index_for_alter(table_name, column_name = nil, options = {})
index_name = index_name_for_remove(table_name, column_name, options)
"DROP INDEX #{quote_column_name(index_name)}"
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -448,10 +448,15 @@ def add_index(table_name, column_name, options = {}) #:nodoc:
end
end

def remove_index(table_name, options = {}) #:nodoc:
def remove_index(table_name, column_name = nil, options = {}) #:nodoc:
table = Utils.extract_schema_qualified_name(table_name.to_s)

if options.is_a?(Hash) && options.key?(:name)
if column_name.is_a?(Hash)
options = column_name.dup
column_name = options.delete(:column)
end

if options.key?(:name)
provided_index = Utils.extract_schema_qualified_name(options[:name].to_s)

options[:name] = provided_index.identifier
Expand All @@ -462,9 +467,9 @@ def remove_index(table_name, options = {}) #:nodoc:
end
end

index_to_remove = PostgreSQL::Name.new(table.schema, index_name_for_remove(table.to_s, options))
index_to_remove = PostgreSQL::Name.new(table.schema, index_name_for_remove(table.to_s, column_name, options))
algorithm =
if options.is_a?(Hash) && options.key?(:algorithm)
if options.key?(:algorithm)
index_algorithms.fetch(options[:algorithm]) do
raise ArgumentError.new("Algorithm must be one of the following: #{index_algorithms.keys.map(&:inspect).join(', ')}")
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,8 @@ def primary_keys(table_name) # :nodoc:
pks.sort_by { |f| f["pk"] }.map { |f| f["name"] }
end

def remove_index(table_name, options = {}) #:nodoc:
index_name = index_name_for_remove(table_name, options)
def remove_index(table_name, column_name, options = {}) #:nodoc:
index_name = index_name_for_remove(table_name, column_name, options)
exec_query "DROP INDEX #{quote_column_name(index_name)}"
end

Expand Down
21 changes: 12 additions & 9 deletions activerecord/lib/active_record/migration/command_recorder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -187,16 +187,19 @@ def invert_add_index(args)
end

def invert_remove_index(args)
table, options_or_column = *args
if (options = options_or_column).is_a?(Hash)
unless options[:column]
raise ActiveRecord::IrreversibleMigration, "remove_index is only reversible if given a :column option."
end
options = options.dup
[:add_index, [table, options.delete(:column), options]]
elsif (column = options_or_column).present?
[:add_index, [table, column]]
table, columns, options = *args
options ||= {}

if columns.is_a?(Hash)
options = columns.dup
columns = options.delete(:column)
end

unless columns
raise ActiveRecord::IrreversibleMigration, "remove_index is only reversible if given a :column option."
end

[:add_index, [table, columns, options]]
end

alias :invert_add_belongs_to :invert_add_reference
Expand Down
11 changes: 11 additions & 0 deletions activerecord/test/cases/adapter_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,17 @@ def test_remove_index_when_name_and_wrong_column_name_specified
@connection.remove_index(:accounts, name: index_name)
end

def test_remove_index_when_name_and_wrong_column_name_specified_positional_argument
index_name = "accounts_idx"

@connection.add_index :accounts, :firm_id, name: index_name
assert_raises ArgumentError do
@connection.remove_index :accounts, :wrong_column_name, name: index_name
end
ensure
@connection.remove_index(:accounts, name: index_name)
end

def test_current_database
if @connection.respond_to?(:current_database)
assert_equal ARTest.connection_config["arunit"]["database"], @connection.current_database
Expand Down
4 changes: 2 additions & 2 deletions activerecord/test/cases/migration/change_table_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,8 @@ def test_remove_drops_multiple_columns

def test_remove_index_removes_index_with_options
with_change_table do |t|
@connection.expect :remove_index, nil, [:delete_me, { unique: true }]
t.remove_index unique: true
@connection.expect :remove_index, nil, [:delete_me, :bar, { unique: true }]
t.remove_index :bar, unique: true
end
end

Expand Down
7 changes: 6 additions & 1 deletion activerecord/test/cases/migration/command_recorder_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,12 @@ def test_invert_add_index_with_algorithm_option

def test_invert_remove_index
add = @recorder.inverse_of :remove_index, [:table, :one]
assert_equal [:add_index, [:table, :one]], add
assert_equal [:add_index, [:table, :one, {}]], add
end

def test_invert_remove_index_with_positional_column
add = @recorder.inverse_of :remove_index, [:table, [:one, :two], { options: true }]
assert_equal [:add_index, [:table, [:one, :two], options: true]], add
end

def test_invert_remove_index_with_column
Expand Down
3 changes: 3 additions & 0 deletions activerecord/test/cases/migration/index_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ def test_add_index
connection.add_index("testings", ["last_name", "first_name"], length: { last_name: 10, first_name: 20 })
connection.remove_index("testings", ["last_name", "first_name"])

connection.add_index("testings", "key", unique: true)
connection.remove_index("testings", "key", unique: true)

connection.add_index("testings", ["key"], name: "key_idx", unique: true)
connection.remove_index("testings", name: "key_idx", unique: true)

Expand Down
4 changes: 2 additions & 2 deletions activerecord/test/cases/migration_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,7 @@ def test_drop_index_from_table_named_values

assert_nothing_raised do
connection.add_index :values, :value
connection.remove_index :values, column: :value
connection.remove_index :values, :value
end
ensure
connection.drop_table :values rescue nil
Expand All @@ -786,7 +786,7 @@ def test_drop_index_by_name

assert_nothing_raised do
connection.add_index :values, :value, name: "a_different_name"
connection.remove_index :values, column: :value, name: "a_different_name"
connection.remove_index :values, :value, name: "a_different_name"
end
ensure
connection.drop_table :values rescue nil
Expand Down

0 comments on commit da54c73

Please sign in to comment.