この記事のタイトルにあることの理由は MySQL :: MySQL 8.0 リファレンスマニュアル :: 13.1.9.2 ALTER TABLE および生成されるカラム を読んだら分かります。
生成カラムの式を変えてsqldefでマイグレーションを反映したら、DROP COLUMNしてADD COLUMNするDDLが実行されたことで、表題の件に気づいた。
ものすごく単純化すると、たとえば以下のようなDDLが実行されることがある。
ALTER TABLE `users` DROP COLUMN `id_mod`; ALTER TABLE `users` ADD COLUMN `id_mod` int GENERATED ALWAYS AS (id % 5) VIRTUAL AFTER `id`;
参照しているカラムをDROPされると、稼動中のアプリケーションでエラーが発生してしまう。これは都合がよくない。以下のように生成カラムに対してもCHANGE COLUMNで安全にカラム定義を変更できるはず。
ALTER TABLE `users` CHANGE COLUMN `id_mod` `id_mod` int GENERATED ALWAYS AS (id % 5) VIRTUAL;
ということで、以下のissueを起票した。
ところで (個別のDBMSの実装にもよると思うけど) sqldefが何故このようなDDLを出力するのか。この記事を書いた時点ではちゃんと実装は追っていないけど、MySQLのドキュメントを読みにいったらだいたい分かった。
生成カラムの定義は常にin-placeに変更 (MODIFYやCHANGE COLUMN) できるわけではなく、条件によっては一度DROP COLUMNを経由する必要がある。今回適用したいマイグレーションはこの条件に当てはまらない。DROP COLUMNしてADD COLUMNするのは (一部のケースを除いて) 常に可能である。
「CHANGE COLUMNできるスキーマ変更かどうか」がうまく (sqldefの枠組みの中で) 判定できる方法が分かったらPRを出したいですね。