🐛
[Prisma] スキーマの default value を削除するときは バグに気をつけろ [MySQL]
はじめに
Issue 作りました。
環境
- MySQL 8 系
- Prisma 5.22.0 ~ 6.3.1 (20250210 現在の最新)
発生
status String? @default("hoge")
👆 default 値を持っている + Nullable なものを
status String?
default 値だけ無くして migration するとバグる。
事象
上記フィールドに undefined を渡して create すると Prisma が勝手に「Nullable ではない」と Violation を出すようになる。
Null constraint violation on the fields: (`status`)
もちろん、プロパティ自体を指定せずに create しても同じ。
しかし、なぜか null を明示的に渡すと成功する。不思議。
ちなみに Debug log を見たところ、DB へのクエリは発行されていないので、完全に Prisma 側のドジっ子である。
原因
DDL で見ていく。
- `limit_kw` decimal(10,6) DEFAULT "hoge",
+ `limit_kw` decimal(10,6) DEFAULT NULL,
本来は上記のようになるべき。の様子。
prisma db push
をすると上記の形になって、当該バグは起きない。
- `limit_kw` decimal(10,6) DEFAULT "hoge",
+ `limit_kw` decimal(10,6),
上記が事象発生状態。
「default を削除した = DEFAUT を DROP する」という組み分けしか出来ていない様子。
本来は DEFAULT NULL が残るべき。
いや、残らなくても MySQL としては Null を許容するのだけども、Prisma は明示的に求めている様子。
ALTER TABLE `task` ALTER COLUMN `status` DROP DEFAULT;
ワークアラウンド
1. nullを明示的に渡す。
前述したやり方。
await prisma.task.create({
data: {
title: 'Task 1',
status: null,
},
});
でも、そう 美しくない。
もしまた デフォルト値を適用することになったらどうする?
メンテナンス性が下がっているのは明白。
2. migration を適用しなおす
DEFAULT NULL
を復活させるやり方。
status String
👆 一回 Nullable じゃなくしてから prisma migrate dev
そのあと、
status String?
Nullable にして、また prisma migrate dev
する。
そうすると migration.sql が2つできるので、1つ目を完全に消す。
これで DDL が意図したものになるため、成功するようになる。
Discussion