LoginSignup
0
0

【Rails】rename_tableでテーブル名を変更したらインデックスのエラーが出る

Last updated at Posted at 2023-12-17

発生した問題

rename_tableでテーブル名を変更する際に、インデックス名が長すぎるというエラーが発生しました。
元々のインデックスは64文字以内になってるし、テーブル名変更するだけなのになんで?と思ったので調べてみました。

Index name 'xxx...' on table 'table_name' is too long; the limit is 64 characters

環境

  • Rails 7.0.5
  • MySQL 8.0

原因

rename_tableで、テーブル名の変更とともにインデックス名の変更の処理もされていたためでした。
変更後のインデックス名が64文字を超えていたためエラーが出たようです。

rename_tableの挙動

rename_tableのコードを見てみます。

def rename_table(table_name, new_name)
  schema_cache.clear_data_source_cache!(table_name.to_s)
  schema_cache.clear_data_source_cache!(new_name.to_s)
  execute "RENAME TABLE #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}"
  rename_table_indexes(table_name, new_name)
end

テーブル名変更のSQL実行後に、rename_table_indexesが実行されています。
rename_table_indexesも見てみましょう。

def rename_table_indexes(table_name, new_name)
  indexes(new_name).each do |index|
    generated_index_name = index_name(table_name, column: index.columns)
    if generated_index_name == index.name
      rename_index new_name, generated_index_name, index_name(new_name, column: index.columns)
    end
  end
end

詳細を見ればわかりますが、generated_index_nameはRailsがインデックスをはる際にテーブル名とカラム名から自動生成するインデックスの名前です。
つまり、既存のインデックス名がRailsが自動生成したインデックス名なら、新しいテーブル名でインデックス名を生成し直しています。

要するに

新しいテーブル名が旧テーブル名より長くなったりするとそれによって変更されるインデックス名も長くなり、インデックス名の文字数上限(ここでは64文字)を超えてしまう場合に今回のエラーが出ていたようです。

回避策

インデックス名を明示的に指定して、Railsが生成するインデックス名と被らないようにしましょう。

rename_index :target_table, :old_index_name, :new_index_name
rename_table :target_table, :new_table

参考

raname_tableのソースコード

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0