Open4

Remix+CloudflareでWebサイトを作る 23

saneatsusaneatsu

【2024-04-07】Prismaでデータが入っている既存のテーブルにカラムを追加する

We need to reset the SQLite database All data will be lost.

https://www.prisma.io/docs/orm/prisma-migrate/workflows/customizing-migrations

まずは既存のDBの定義とPrismaのモデルと同期する。

schema.prisma
- includeRelationFromFields = true
+ includeRelationFromFields = "true"

"true"という文字列なんか嫌だな...。

--create-onlyオプションをつけてマイグレーションファイルの作成だけをして適用はしないようにする。

$ npx prisma migrate dev --create-only --name your-migration-name
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": SQLite database "dev.db" at "file:./dev.db"

- Drift detected: Your database schema is not in sync with your migration history.
✖ We need to reset the SQLite database "dev.db" at "file:./dev.db"
Do you want to continue? All data will be lost. … no

All data will be lost. ....???
--create-onlyするだけでなぜ消えるのか。

Prisma migrationを導入しようとすると、最初のタイミングでmigration用の管理テーブルが作られる。そして手動で定義していたものについてはその時点で既存のテーブルは一度削除されてしまうという仕様のようだ。テーブルが削除されるのでもちろんデータも消える。開発環境とは言えそれなりの量のデータが入っていること、本番適用時にデータが全部消えてしまうのは論外なこともあり色々と調べたり試したりしたものの良い解決策は見つからなかった。

--create-onlyをつけて実行すると実行日時のフォルダとともにマイグレーションファイルができあがり、マイグレーションの管理テーブルだけが作成された状態でマイグレーションファイルの内容は反映されていない状態となる。大事なことなので2回言うが、DB上は全部のテーブルが削除された上でマイグレーションの管理テーブルのみが存在しているという状態になる。

これに関してはどうしようもないので既存のものに導入する場合、かつデータも残したい場合は事前にバックアップするなり、テーブル単位でエクスポートしておくことは必須といえる。

ref: 既存のデータベースでPrisma migrateする。しかもPostGISを使う - Sweet Escape

ALTER TABLE tableName ADD COLUMN columnName BOOLEAN DEFAULT FALSE;

こんな感じでカラムだけ追加するSQL作成してほしいんだけどどこらへんがネックなんだろうか。

Refs

time-travelでバックアップ

マイグレーションファイル適当に作って中身のSQL書き換えようかなとも思ったけど、Prismaの思想に反するのもなんか良くない気もする。

ということで「バックアップ取って→マイグレーション→データ入れ直す」の一連の流れをちゃんとわかっておこう。

Backups (Legacy) · Cloudflare D1 docs

wrangler d1 backup コマンドでバックアップできるっぽいけど、開発環境でのバックアップコマンドはなさそう。

Commands - Wrangler · Cloudflare Workers docs

wrangerコマンドのページを見ても--local的なオプションがないのでなさそう。

Cloudflare Workers から D1 を操作する

今はwrangler d1 time-travelの方か。そうでした。

結論

Development

カラムを追加するとDBのデータはすべて消えてしまうので諦める。

Staging/Production

以下でなんとかなりそうだけど全然スマートじゃない気がする。

bookmark取得
→テーブル初期化
$ npm exec -- zx prisma/d1-migration.mjs --env=stagingでスキーマ更新
→restore

schema.prisma に変更があった場合だけこの処理やってくれるGitHub Actionsとかあったら便利かな?

saneatsusaneatsu

UserテーブルにOptionalなカラムであるtestを追加した場合はAlterだけ

-- AlterTable
ALTER TABLE "User" ADD COLUMN "test" TEXT;

UserテーブルにRequiredなカラムであるhogeを追加した場合は、tempとなるテーブルを作成してデータを移し替えて元のテーブルを削除して、tempとなるテーブルをリネームしている。

/*
  Warnings:

  - Added the required column `hoge` to the `User` table without a default value. This is not possible if the table is not empty.

*/
-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_User" (
    "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    "name" TEXT,
    "test" TEXT,
    "hoge" TEXT NOT NULL,
    "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" DATETIME NOT NULL
);
INSERT INTO "new_User" ("createdAt", "email", "iconUrl", "id", "isArchived", "name", "role", "test", "updatedAt") SELECT "createdAt", "email", "iconUrl", "id", "isArchived", "name", "role", "test", "updatedAt" FROM "User";
DROP TABLE "User";
ALTER TABLE "new_User" RENAME TO "User";
CREATE UNIQUE INDEX "User_id_key" ON "User"("id");
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;
saneatsusaneatsu

【2024-04-10】Service Bindingのためにmonorepo構成にする

背景

https://zenn.dev/chimame/articles/f86db24897be6a

こちらを参考にmonorepo構成にしてみている。

https://zenn.dev/moutend/articles/f9409d43724da5
Service Binding自体についてこっちの記事も良かった。

エラー

Remix側とPrismaのWorkerがうまく連携できていないっぽい。

WARNING: Tried to access method or property 'fetchIdByEmail' on a Service Binding or Durable Object stub. Are you trying to use RPC? If so, please enable the 'rpc' compat flag or update your compat date to 2024-04-03 or later (see https://developers.cloudflare.com/workers/configuration/compatibility-dates/ ). If you are not trying to use RPC, please note that in the future, this property (and all other property names) will appear to be present as an RPC method.

https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/rpc/

指示通りにしても治らず。

wrangler.toml
compatibility_date = "2024-04-03"