web-dev-qa-db-ja.com

rename_columnはインデックスを処理しますか?

たとえば、次のようなものがあるとします。

add_column :users, :single, :boolean
add_index :users, :single

その後、私たちは

rename_column :users, :single, :married

ActiveRecordやデータベースはインデックスの名前変更も処理しますか、それとも手動でインデックスを削除して再度追加する必要がありますか?

63
randomguy

PostgreSQLの場合、_rename_column_は単純な_ALTER TABLE ... RENAME COLUMN ..._として実装され、インデックスを保持します。

MySQLのバージョン(どちらも)は_ALTER TABLE ... CHANGE ..._を実行し、インデックスも保持します。

SQLiteバージョンは、テーブル全体(インデックス付き)をコピーし、古いテーブルを削除してから、コピーを元のテーブル名にコピーして戻します。コピーは、インデックスのコピー中に列の名前変更を処理するように見えます。

_def copy_table(from, to, options = {})
  #...
  copy_table_indexes(from, to, options[:rename] || {})
_

そして_copy_table_indexes_の中:

_columns = index.columns.map {|c| rename[c] || c }.select do |column|
  to_column_names.include?(column)
end
_

そのため、_rename_column_を実行すると、標準ドライバーはインデックスを保持し、SQLiteドライバーはそのために何らかの努力をします。

APIドキュメントは特定の動作を指定していませんが、他のドライバーが他のことを行う場合があります。ドキュメントがインデックスについて何かを言うのに最も近いのはこれが_active_record/migration.rb_にあることです:

rename_column(table_name, column_name, new_column_name):列の名前を変更しますが、タイプと内容は保持します。

どのドライバーもインデックスを保持すると思いますが、保証はありません。ドライバーの作成者は、インデックスを保持しないのは間違いなく愚かでしょう。

これは決定的または信頼できる回答ではありませんが、標準のPostgreSQL、MySQL(いずれか)、またはSQLiteドライバーを使用する場合は、インデックスを保持する必要があります。


インデックス自体が列の名前変更後も存続する場合でも、インデックスnameが変更される保証はありません。関係する列ではなく、インデックス名を気にする何か(手動で削除するなど)を行わない限り、これは問題になりません。

上記の動作 Rails 4)で変更

  • Rails 4.0では、列またはテーブルの名前が変更されると、関連するインデックスも名前が変更されます。インデックスの名前を変更する移行がある場合、インデックスは不要です。

したがって、テーブルまたは列の名前を変更すると、ActiveRecordは新しいテーブルまたは列の名前と一致するようにインデックスの名前を自動的に変更します。 sequielo に感謝します。

96
mu is too short