aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorYves Senn <yves.senn@gmail.com>2013-11-26 09:58:24 +0100
committerYves Senn <yves.senn@gmail.com>2013-11-26 10:03:55 +0100
commit6eba8d27e6feecca88303df6500ef6b376344e29 (patch)
treed84607e6b13721a4acd035a088a185b232bda0f3 /activerecord
parente4c0a225ae029af91d26735d8085a09d6d64859e (diff)
downloadrails-6eba8d27e6feecca88303df6500ef6b376344e29.tar.gz
rails-6eba8d27e6feecca88303df6500ef6b376344e29.tar.bz2
rails-6eba8d27e6feecca88303df6500ef6b376344e29.zip
`rename_index`: add the new index before removing the old one.
This prevents the following error when a MySQL index on a foreign key column is renamed: ``` ActiveRecord::StatementInvalid: Mysql2::Error: Cannot drop index 'index_engines_on_car_id': needed in a foreign key constraint: DROP INDEX `index_engines_on_car_id` ON `engines` ``` refs: #13038.
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG.md8
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb4
-rw-r--r--activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb25
3 files changed, 29 insertions, 8 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index bce288aefb..fc40bd88be 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,9 +1,17 @@
+* `rename_index` adds the new index before removing the old one. This allows
+ to rename indexes on columns with a foreign key and prevents the following error:
+
+ `Cannot drop index 'index_engines_on_car_id': needed in a foreign key constraint`
+
+ *Cody Cutrer*, *Yves Senn*
+
* Raise `ActiveRecord::RecordNotDestroyed` when a replaced child marked with `dependent: destroy` fails to be destroyed.
Fix #12812
*Brian Thomas Storti*
+
* Fix validation on uniqueness of empty association.
*Evgeny Li*
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
index 4b425494d0..6268ae4875 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -558,8 +558,8 @@ module ActiveRecord
# this is a naive implementation; some DBs may support this more efficiently (Postgres, for instance)
old_index_def = indexes(table_name).detect { |i| i.name == old_name }
return unless old_index_def
- remove_index(table_name, :name => old_name)
- add_index(table_name, old_index_def.columns, :name => new_name, :unique => old_index_def.unique)
+ add_index(table_name, old_index_def.columns, name: new_name, unique: old_index_def.unique)
+ remove_index(table_name, name: old_name)
end
def index_name(table_name, options) #:nodoc:
diff --git a/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb b/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb
index 9ecd901eac..ec73ec35aa 100644
--- a/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb
@@ -4,22 +4,35 @@ module ActiveRecord
module ConnectionAdapters
class Mysql2Adapter
class SchemaMigrationsTest < ActiveRecord::TestCase
- def test_initializes_schema_migrations_for_encoding_utf8mb4
- conn = ActiveRecord::Base.connection
+ def test_renaming_index_on_foreign_key
+ connection.add_index "engines", "car_id"
+ connection.execute "ALTER TABLE engines ADD CONSTRAINT fk_engines_cars FOREIGN KEY (car_id) REFERENCES cars(id)"
+
+ connection.rename_index("engines", "index_engines_on_car_id", "idx_renamed")
+ assert_equal ["idx_renamed"], connection.indexes("engines").map(&:name)
+ ensure
+ connection.execute "ALTER TABLE engines DROP FOREIGN KEY fk_engines_cars"
+ end
+ def test_initializes_schema_migrations_for_encoding_utf8mb4
smtn = ActiveRecord::Migrator.schema_migrations_table_name
- conn.drop_table(smtn) if conn.table_exists?(smtn)
+ connection.drop_table(smtn) if connection.table_exists?(smtn)
- config = conn.instance_variable_get(:@config)
+ config = connection.instance_variable_get(:@config)
original_encoding = config[:encoding]
config[:encoding] = 'utf8mb4'
- conn.initialize_schema_migrations_table
+ connection.initialize_schema_migrations_table
- assert conn.column_exists?(smtn, :version, :string, limit: Mysql2Adapter::MAX_INDEX_LENGTH_FOR_UTF8MB4)
+ assert connection.column_exists?(smtn, :version, :string, limit: Mysql2Adapter::MAX_INDEX_LENGTH_FOR_UTF8MB4)
ensure
config[:encoding] = original_encoding
end
+
+ private
+ def connection
+ @connection ||= ActiveRecord::Base.connection
+ end
end
end
end