13
3

More than 1 year has passed since last update.

Prismaで新規レコード作成時に@default(now())なカラムと@updatedAtなカラムに差異が生じる問題

Last updated at Posted at 2023-01-23

環境

  • Prisma:3.13.0
    発生条件は <= 4.3.1(後述)
  • Provider:MySQL

概要

こんな感じで定義されたテーブルに対して、

schema.prisma
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_atupdated_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_atupdated_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のバージョンを上げて再度検証してみる。

package.json
{
  "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_atupdated_atがミリ秒まで含め同じ値となっていることが確認できた。

まとめ

@default(now())なカラムと@updatedAtなカラムを定義し、
かつその差分を比較する必要があるケースでは必ずバージョン4.4.0以上のPrismaを使用しましょう。

ただ、Prisma4から$queryRaw等に仕様変更が入っているので、
既存アプリケーションのPrismaバージョンアップは慎重に。
※こちらはまた別記事で書きます。

参考

関連

Prisma4にアップグレードした際に$queryRawを使用している箇所でTypeError: Cannot mix BigInt and other types, use explicit conversionsが発生する問題

13
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
3