この記事はZOZO Advent Calendar 2023 シリーズ9の13日目の記事です。
はじめに
最近よく名前を聞くような気がするPlanetScale
ですが、みなさん使っていますでしょうか?
自分は先日行われた開発合宿で初めて使用し、開発体験の良さに思わず感動してしまいました。
その時作成したアプリの記事も書いていますのでよければご覧ください!
PlanetScale
は元々、外部キー制約をサポートしておらず、それが理由で触るのを避けてきた人も多いのではないでしょうか?
しかしつい先日、ついに外部キー制約がサポートされました!
現在ベータ版ではあるもののフリープランでも試すことはできるので、今回はPrisma
を使って試してみようと思います!
※外部キー制約そのものについては詳しく触れません🙇♂️
PlanetScaleとは
PlanetScale
はサーバレスなMySQLプラットフォームです。
DBのブランチ機能があったり、ダウンタイムなしのマイグレーション、productionにデプロイ後30分以内であればスキーマの変更をrevertできるなどの特徴があります。
PlanetScaleで外部キー制約がサポートされた背景
上記でも述べたように、PlanetScale
では元々、外部キー制約をサポートしておりませんでした。
内部で使用されているVitessが外部キー制約をサポートしていなかったことなどが理由です。
以下の記事に外部キー制約をサポートしていなかった理由についてわかりやすくまとまっておりましたのでぜひご参考にしてみてください。
しかし、2023年11月Vitess
v18にて外部キー制約がサポートされたことにより、同年12月よりPlanetScale
でも外部キー制約がサポートされました。
実際に確かめてみる
PlanetScaleとPrismaの準備
アカウントを作成しログインしたら、以下のような画面になるので"Create a new database"からデータベースを作成します。
詳しい手順は今回は省略しますが、画面に沿っていくだけで簡単にデータベースを作成できます。
途中使用するフレームワークが選択できるので今回はPrisma
を選択します。
そうすると、画面にPrisma
用の設定手順が出てきます。
その下あたりにenvファイルに記述情報が出てくるので、ご自身の.envファイルにコピペしてください。
(今回自分は自分で作った超最小構成なRemixのテンプレートを使用しています。)
DATABASE_URL='mysql://XXXXXXXXXXXXXXXX
これでPrisma
とPlanetScale
の連携は完了です。
現在はベータ版なのでそのままだと外部キー制約は使えない
現在はベータ版なのでそのままだと外部キー制約は使えません。
実際に試してみます。
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
そのため今までは、外部キー制約を作成せずにエミュレートするモードを使う必要がありました。
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
+ relationMode = "prisma"
}
この一文を追加することでデータベースにプッシュすることは可能になります。
現在はベータ版の機能を利用して外部キー制約が使えるか試してみる
少し長くなってしまいましたが、ここからが本題です!
まずはベータ版の機能を利用できるように設定する必要があります。
詳しくは公式ドキュメントに書いてありますが、ここでも簡単に説明します。
PlanetScale
の管理画面から
"Settings" → "Beta features"と進み "Foreign key constraints"をEnrollします。
これだけで利用できるようになったので、実際に先ほどエラーが出てしまったスキーマをデータベースにプッシュしてみます。
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
で確認してみても、問題なくテーブルが作成できていました。
まとめ
今回は実際にPlanetScale
での外部キー制約のサポートを確認してみました!
ドキュメント等読んでる中で、アプリケーションによっては外部キー制約を推奨しない場合などもあるようで、その辺の知識ももっとつけないとなと痛感しました。。。
PlanetScale
を利用した開発体験はかなりいいので、外部キー制約をサポートしたことでより人気が出ると思っております。
今後も色々試してみて、新たな気づきや発見がありましたら発信していこうと思います!
興味が湧きましたら、みなさまも是非触ってみてはいかがでしょうか?!
おわりに
内容について誤り等ございましたらご指摘いただけますと大変幸いでございます。
何卒よろしくお願いいたします。
最後まで読んでいただきましてありがとうございました!