MySQL のインデックス有効化/無効化でインデックス名をクォート

rails/rails

Rails の MySQL アダプタで enable_indexdisable_index がインデックス名を正しくクォートするようになり、予約語や特殊文字を含むインデックスでもマイグレーションが失敗しなくなります。

背景

このセクションでは、インデックス名が未クォートで生成されたことがもたらした問題点を示します。MySQL / MariaDB では、予約語(例: order)やハイフン等の特殊文字を含む識別子はバッククオートで囲む必要があり、未クォートのまま ALTER INDEX を実行すると構文エラーが発生します。実際に ALTER TABLEtestingsALTER INDEX order VISIBLE と生成された SQL がエラーとなり、マイグレーションのデプロイ時に障害が報告されていました。

技術的な変更

このセクションでは、コードベースに加えられた具体的な修正内容を解説します。abstract_mysql_adapter.rbenable_indexdisable_index メソッドで、インデックス名を quote_column_name で囲むよう変更され、生成される SQL がバッククオートで安全にエスケープされるようになりました。

変更前(enable_index):

ALTER TABLE #{quote_table_name(table_name)} ALTER INDEX #{index_name} #{mariadb? ? "NOT IGNORED" : "VISIBLE"}

変更後(enable_index):

ALTER TABLE #{quote_table_name(table_name)} ALTER INDEX #{quote_column_name(index_name)} #{mariadb? ? "NOT IGNORED" : "VISIBLE"}

同様に disable_index でもインデックス名が quote_column_name でクォートされるよう修正され、ALTER INDEX 文が安全に実行できるようになりました。

変更前(disable_index):

ALTER TABLE #{quote_table_name(table_name)} ALTER INDEX #{index_name} #{mariadb? ? "IGNORED" : "INVISIBLE"}

変更後(disable_index):

ALTER TABLE #{quote_table_name(table_name)} ALTER INDEX #{quote_column_name(index_name)} #{mariadb? ? "IGNORED" : "INVISIBLE"}

テストスイートにも test_disable_and_enable_index_with_reserved_word_name が追加され、予約語 order を名前に持つインデックスの無効化・有効化が期待通りに動作することを検証しています。

この変更は API のシグネチャを変更せず、既存の呼び出し側に影響を与えません。enable_index(table, name) と従来通り呼び出すだけで、内部で安全にクォートされた SQL が実行されます。

設計判断

このセクションでは、採択された実装方針とその背景を説明します。インデックス名のエスケープに新規ヘルパーを導入せず、quote_column_name を再利用することで、コードベース全体で一貫したクォートロジックを保ちました。

既存の quote_column_name はテーブル名・カラム名のエスケープに広く利用されており、追加の抽象化層を設けないことで保守コストを最小化しています。これにより、他のインデックス操作(例: rename_index)と同様の振る舞いが保証されました。

結果として、インデックス名の取り扱いが安全になると同時に、既存コードとの後方互換性が維持され、開発者は追加の変更なしに新機能を利用できるようになりました。

まとめ

enable_indexdisable_index がインデックス名を正しくクォートするようになったことで、予約語や特殊文字を含むインデックスでもマイグレーションが安定します。このシンプルな修正は既存インターフェースをそのまま活かしつつ、SQL 構文エラーの根本原因を除去し、Rails の MySQL アダプタの信頼性を向上させました。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
773fe7e7

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
リトライ後承認
Review Count:
3回 (改善を経て承認)
Reviewed by:
gpt-oss-120b for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文、背景、技術的変更、設計判断(任意)、まとめの5セクションが揃っており、総論→各論→結論の構成が明確です。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

コードブロックは正しいファイル名付きシンタックスハイライト形式 (```ruby:ファイルパス) で記述され、PRリンクは [#57984](URL) の形式で正しくマークダウン化されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

内容はRails の MySQL アダプタに関する実装変更を説明しており、エンジニア向けの専門的レベルです。初心者向けの過度な説明はありません。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションは総論パラグラフ、具体的なコード例・解説、結論パラグラフで構成され、段落はトピックセンテンスで始まり1段落1トピック、長さも適切です。空行で区切られています。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事中のコードブロックは提供されたDiffと完全に一致しており、ファイル名・変更前後の内容とも合致しています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`enable_index`、`disable_index`、`quote_column_name` などの用語は PR 記述と一致し、誤用はありません。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

インデックス名をクォートすることで構文エラーが回避できるという説明は PR の目的と合致しており、技術的に正確です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

全ての主張は PR 内容(コード変更、テスト追加)で裏付けられており、推測や捏造はありません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号 #57984 が正しく記載されており、その他数値や固有名詞の誤りは見られません。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事タイトルは PR タイトル「Quote the index name in MySQL enable_index/disable_index」の意味を日本語で適切に表現しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

LTS やリリース日程などの外部情報は含まれておらず、PR に基づく内容だけが記述されています。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

時間に関する表現はなく、PR の記述と矛盾する箇所もありません。