スキーマダンプ時のカラム名アルファベット順ソートをリバート
schema.rb のカラム出力順をアルファベット順に並び替える変更(#53281)がリバートされました。db:prepare で不正なテーブル構造が生成される問題が判明したためです。
背景
#53281 は、複数の開発者が同一テーブルへのマイグレーションを並行して作成した場合に発生するスキーマの非決定的な差分を解消するために、schema.rb のカラム出力をアルファベット順にソートする変更でした。異なる環境でマイグレーションを適用した際にカラムの物理的な並び順が異なることで、意味のないスキーマの差分やコンフリクトが発生するという問題に対処するものでした。
しかし #55414 のコメント(参照)での調査により、アルファベット順ソートはより深刻な問題を引き起こすことが判明しました。db:prepare を使った際に、schema.rb のカラム順がデータベースの実際のカラム順と異なることで、本番環境に不正なテーブル構造が生成されるという問題です。
カラムの並び順には意味があります。MySQLの AFTER / BEFORE オプションのように、一部のデータベースではカラムの物理的な並び順が機能やパフォーマンスに影響を与えます。スキーマを決定的にする目的でカラム順を変えることは、別の正確性の問題を生む判断であると結論づけられました。
技術的な変更
変更は activerecord/lib/active_record/schema_dumper.rb の1行の修正と、対応するテストの削除で構成されます。
変更前:
columns.sort_by(&:name).each do |column|
変更後:
columns.each do |column|
sort_by(&:name) の除去により、カラムはデータベースから取得した元の順序のまま出力されます。合わせて、カラムのアルファベット順を検証していたテスト test_table_columns_sorted も削除されました。
CHANGELOGには「アルファベットソートが db:prepare 使用時に不正な本番テーブルを生成する」旨の記載が追加されており、リバートの理由が明示されています。
設計判断
スキーマの正確性をdiff品質よりも優先するという判断が下されました。
元の #53281 が解決しようとしていた問題(並行マイグレーションによる非決定的なスキーマ差分)は実際に存在しますが、PRの議論では、その解決策として採用されたアルファベット順ソートが「正しい解決策ではない(not the appropriate solution)」と結論づけられました。関連PR #55414 では sort_table_columns というオプトイン設定の追加案も検討されていましたが、根本的なアプローチ自体の問題が優先され、まずリバートが選択されています。
スキーマファイルの役割はデータベースの現在の状態を正確に表現することにあります。diff品質の改善は望ましい目標ですが、schema.rb から db:prepare で再構築したデータベースが元のデータベースと異なる構造になることは、その役割に反します。
まとめ
このリバートは、スキーマダンプの「決定論的な美しさ」よりも「正確な再現性」を優先した判断です。並行マイグレーションによるスキーマ差分の問題は依然として残りますが、それを解消する手段としてカラム順の並び替えは適切ではないという結論であり、別のアプローチでの解決が今後の課題となります。