環境
- Prisma:3.13.0
発生条件は <= 4.3.1(後述) - Provider:MySQL
概要
こんな感じで定義されたテーブルに対して、
model User {
id Int @id @default(autoincrement()) @db.UnsignedInt
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@map("users")
}
prisma.user.create({})
を実行すると以下のようにcreated_at
とupdated_at
がミリ秒単位で差異が生じる結果となる。
MySQL > select id,created_at,updated_at from users;
+----+-------------------------+-------------------------+
| id | created_at | updated_at |
+----+-------------------------+-------------------------+
| 1 | 2023-01-23 02:17:42.875 | 2023-01-23 02:17:42.894 |
+----+-------------------------+-------------------------+
created_at
とupdated_at
を比較するような実装はよくあるケースなので、
そういうケースでこの問題に直面すると結構頭を抱える問題。
メジャーなF/WのORM(railsのActiveRecordやLaravelのEloquent)と同じ仕様だと勝手に思い込んでいたのでかなり驚いたが、
これは3.13.0時点(厳密には <= 4.3.1)での仕様であり、GitHubリポジトリ上にIssueも既に上がっていた。
コントリビューターの方が丁寧にコメントしてくれている通り、@default(now())
はDBで書き込んでいるが、
@updatedAt
はPrismaクライアントから書き込んでいることでミリ秒単位の差異が生じている模様。
最終的にprisma-enginesのこちらのPRで対応され、無事バージョン4.4.0でリリースされた模様。
対応
ということで、Prismaのバージョンを上げるだけで期待する動作になるはずなので、
Prismaのバージョンを上げて再度検証してみる。
{
"dependencies": {
"@prisma/client": "^4.8.0",
"prisma": "^4.8.0"
}
}
prisma.user.create({})
を実行し、レコードを確認すると。
MySQL > select id,created_at,updated_at from users;
+----+-------------------------+-------------------------+
| id | created_at | updated_at |
+----+-------------------------+-------------------------+
| 1 | 2023-01-23 02:50:32.466 | 2023-01-23 02:50:32.466 |
+----+-------------------------+-------------------------+
created_at
とupdated_at
がミリ秒まで含め同じ値となっていることが確認できた。
まとめ
@default(now())
なカラムと@updatedAt
なカラムを定義し、
かつその差分を比較する必要があるケースでは必ずバージョン4.4.0以上のPrismaを使用しましょう。
ただ、Prisma4から$queryRaw
等に仕様変更が入っているので、
既存アプリケーションのPrismaバージョンアップは慎重に。
※こちらはまた別記事で書きます。
参考