12
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ZOZOAdvent Calendar 2023

Day 13

PlanetScale外部キー制約対応したからPrismaのrelationMode = "prisma"記述不要になったってこと?

Posted at

この記事はZOZO Advent Calendar 2023 シリーズ9の13日目の記事です。

はじめに

最近よく名前を聞くような気がするPlanetScaleですが、みなさん使っていますでしょうか?
自分は先日行われた開発合宿で初めて使用し、開発体験の良さに思わず感動してしまいました。
その時作成したアプリの記事も書いていますのでよければご覧ください!

PlanetScaleは元々、外部キー制約をサポートしておらず、それが理由で触るのを避けてきた人も多いのではないでしょうか?
しかしつい先日、ついに外部キー制約がサポートされました!
現在ベータ版ではあるもののフリープランでも試すことはできるので、今回はPrismaを使って試してみようと思います!

※外部キー制約そのものについては詳しく触れません🙇‍♂️

PlanetScaleとは

PlanetScaleはサーバレスなMySQLプラットフォームです。
DBのブランチ機能があったり、ダウンタイムなしのマイグレーション、productionにデプロイ後30分以内であればスキーマの変更をrevertできるなどの特徴があります。

PlanetScaleで外部キー制約がサポートされた背景

上記でも述べたように、PlanetScaleでは元々、外部キー制約をサポートしておりませんでした。
内部で使用されているVitessが外部キー制約をサポートしていなかったことなどが理由です。

以下の記事に外部キー制約をサポートしていなかった理由についてわかりやすくまとまっておりましたのでぜひご参考にしてみてください。

しかし、2023年11月Vitessv18にて外部キー制約がサポートされたことにより、同年12月よりPlanetScaleでも外部キー制約がサポートされました。

実際に確かめてみる

PlanetScaleとPrismaの準備

アカウントを作成しログインしたら、以下のような画面になるので"Create a new database"からデータベースを作成します。

スクリーンショット 2023-12-13 3.41.58.png

詳しい手順は今回は省略しますが、画面に沿っていくだけで簡単にデータベースを作成できます。
途中使用するフレームワークが選択できるので今回はPrismaを選択します。

スクリーンショット 2023-12-13 1.48.21.png

そうすると、画面にPrisma用の設定手順が出てきます。

スクリーンショット 2023-12-13 1.50.48.png

その下あたりにenvファイルに記述情報が出てくるので、ご自身の.envファイルにコピペしてください。
(今回自分は自分で作った超最小構成なRemixのテンプレートを使用しています。)

.env
DATABASE_URL='mysql://XXXXXXXXXXXXXXXX

これでPrismaPlanetScaleの連携は完了です。

現在はベータ版なのでそのままだと外部キー制約は使えない

現在はベータ版なのでそのままだと外部キー制約は使えません。
実際に試してみます。

prisma/scheme.prisma
datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model User {
  id    Int      @id @default(autoincrement())
  name  String
  posts Post[]
}

model Post {
  id      Int      @id @default(autoincrement())
  title   String
  content String
  userId  Int
  user    User     @relation(fields: [userId], references: [id])
}

以上のようなスキーマを用意して、データベースにプッシュしてみます。

npx prisma db push

すると、「外部キー制約サポートしてないよ」というエラーが出ます。

Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": MySQL database "foreign-key-test" at "aws.connect.psdb.cloud"
Error: VT10001: foreign key constraints are not allowed
   0: sql_schema_connector::apply_migration::migration_step
           with step=AddForeignKey { foreign_key_id: ForeignKeyId(0) }
             at schema-engine/connectors/sql-schema-connector/src/apply_migration.rs:21
   1: sql_schema_connector::apply_migration::apply_migration
             at schema-engine/connectors/sql-schema-connector/src/apply_migration.rs:10
   2: schema_core::state::SchemaPush
             at schema-engine/core/src/state.rs:436

そのため今までは、外部キー制約を作成せずにエミュレートするモードを使う必要がありました。

prisma/schema.prisma
datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
+ relationMode = "prisma"
 }

この一文を追加することでデータベースにプッシュすることは可能になります。

現在はベータ版の機能を利用して外部キー制約が使えるか試してみる

少し長くなってしまいましたが、ここからが本題です!
まずはベータ版の機能を利用できるように設定する必要があります。
詳しくは公式ドキュメントに書いてありますが、ここでも簡単に説明します。

PlanetScaleの管理画面から
"Settings" → "Beta features"と進み "Foreign key constraints"をEnrollします。

スクリーンショット 2023-12-13 2.28.10.png

これだけで利用できるようになったので、実際に先ほどエラーが出てしまったスキーマをデータベースにプッシュしてみます。

prisma/scheme.prisma
datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model User {
  id    Int      @id @default(autoincrement())
  name  String
  posts Post[]
}

model Post {
  id      Int      @id @default(autoincrement())
  title   String
  content String
  userId  Int
  user    User     @relation(fields: [userId], references: [id])
}
npx prisma db push

すると問題なくプッシュが成功し、relationMode = "prisma"の記述も必要なくなったのが確認できました!

Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": MySQL database "foreign-key-test" at "aws.connect.psdb.cloud"

🚀  Your database is now in sync with your Prisma schema. Done in 612ms

Running generate... (Use --skip-generate to skip the generators)

changed 43 packages, and audited 867 packages in 2s

250 packages are looking for funding
  run `npm fund` for details

1 moderate severity vulnerability

To address all issues, run:
  npm audit fix

Run `npm audit` for details.

✔ Generated Prisma Client (v5.7.0) to ./node_modules/@prisma/client in 51ms

一応Prisma Studioで確認してみても、問題なくテーブルが作成できていました。

スクリーンショット 2023-12-13 2.30.06.png

まとめ

今回は実際にPlanetScaleでの外部キー制約のサポートを確認してみました!
ドキュメント等読んでる中で、アプリケーションによっては外部キー制約を推奨しない場合などもあるようで、その辺の知識ももっとつけないとなと痛感しました。。。

PlanetScaleを利用した開発体験はかなりいいので、外部キー制約をサポートしたことでより人気が出ると思っております。
今後も色々試してみて、新たな気づきや発見がありましたら発信していこうと思います!

興味が湧きましたら、みなさまも是非触ってみてはいかがでしょうか?!

おわりに

内容について誤り等ございましたらご指摘いただけますと大変幸いでございます。
何卒よろしくお願いいたします。

最後まで読んでいただきましてありがとうございました!

12
1
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
12
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?