Waka blog.

Prismaを使用してCloudflare D1のmigration

はじめに

Prismaを使用sてCloudflare D1のDB migration実行を試す。

Cloudflare D1とは

Cloudflareが提供するSQLiteをベースとした分散型DB。

Cloudflare Workersとシームレスに統合されるよう設計されている。今回実装するコードも最終的にCloudflare Workersにデプロイする。

進め方

Cloudflareの公式ドキュメントを参考にしつつ、以下の順に進める

  1. Honoアプリの作成
  2. Prismaセットアップ
  3. データベース作成
  4. マイグレーション
  5. データ投入

1. Honoアプリの作成

HonoはJavascriptのwebフレームワーク。Cloudflare Workersのテンプレートが標準で実装されており、コードもシンプルになるので今回はこちらを使用します。

以下のコマンドでHonoアプリを作成

$ npm create hono honp-prisma-d1-example

どのテンプレを使用するか聞かれるので、 `cloudflare-workersを選択

$ npm create hono honp-prisma-d1-example
create-hono version 0.12.0
✔ Using target directory … honp-prisma-d1-example
? Which template do you want to use?
  aws-lambda
  bun
  cloudflare-pages
❯ cloudflare-workers
  deno
  fastly
  lambda-edge

依存関係のインストールを行い完了。

2. Prismaセットアップ

Prismaのinstall

$ npm install prisma --save-dev

Prisma ClientとCloudflare D1用のアダプターinstall

$ npm install @prisma/client
$ npm install @prisma/adapter-d1

install完了後、prisma initを実行。schema.prismaファイルが生成される。

$ npx prisma init --datasource-provider sqlite

ドライバアダプタ機能を有効にするため、生成されたschema.prismaファイルに以下の1行を追加する。

generator client {
  provider        = "prisma-client-js"
+ previewFeatures = ["driverAdapters"]
}

これでPrismaのセットアップは完了。

3. データベース作成

wranglerを使用してデータベースを作成する。

wranglerとは

Cloudflare Workersの開発を支援するコマンドラインツール。

Workersプロジェクトの作成やリモートへのデプロイ等をコマンドラインから行える。

今回はD1へのDB作成、migration実行をwranglerを使用して行う。

閑話休題。

以下のコマンドでDBを作成。

$ npx wrangler d1 create hono-prisma-demo-db

コマンドの実行が完了するとターミナルに以下のような内容が出力される。

✅ Successfully created DB 'hono-prisma-demo-db' in region EEUR
Created your database using D1's new storage backend. The new storage backend is not yet recommended for production workloads, but backs up your data via
point-in-time restore.

[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "prisma-demo-db"
database_id = "__YOUR_D1_DATABASE_ID__"

[[d1_databases]] 以降を自身の環境の wrangler.toml にコピペする。

※database_idはCloudflareのダッシュボードからも確認可能

以上でDB作成は完了。

4. マイグレーション

wranglerでmigration用のファイル作成と実行を行い、migration sqlの生成はprismaで実施する。

以下のコマンドでmigration用のsqlファイルを作成。

$ npx wrangler d1 migrations create hono-prisma-demo-db create_user_table

prisma-demo-db は先ほど作成したDB名、 create_user_table はマイグレーションファイル名。

上記コマンド実行後、以下のファイルが作成される。

migrations/
└── 0001_create_user_table.sql

次に、 schema.prisma ファイルにモデルを追加する。

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
}

その後、以下のコマンドを実行することで、sqlファイルにUserテーブルを作成するためのsqlが追加される。

$ npx prisma migrate diff --from-empty --to-schema-datamodel ./prisma/schema.prisma --script > migrations/0001_create_user_table.sql

prisma migrate diff はPrismaスキーマとDBの差分を埋めるためのsqlを生成するためのコマンド。

今回は初回なので、 --from-empty オプションでDBが空であることを前提にsqlを生成している。

コマンド実行後、以下のようなsqlが 0001_create_user_table.sql に追加されている。

-- CreateTable
CREATE TABLE "User" (
    "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    "email" TEXT NOT NULL,
    "name" TEXT
);

-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");

最後に、migrationファイルの内容をDBに適用する。

# ローカル環境
$ npx wrangler d1 migrations apply hono-prisma-demo-db --local

# リモート環境
$ npx wrangler d1 migrations apply hono-prisma-demo-db --remote

既存DBを変更したい場合

改めてmigration用のsqlファイルを作成。

$ npx wrangler d1 migrations create hono-prisma-demo-db add_table

schema.prisma を編集する。今回は以下のmodelを追加。

model Company {
  id    Int     @id @default(autoincrement())
  name  String
  address String 
}

prism migrate diff でsqlを生成

$ npx prisma migrate diff --from-local-d1 --to-schema-datamodel ./prisma/schema.prisma --script > migrations/0002_add_table.sql

今回は既存DBとの差分を元にsqlを作成するため、 --from-local-d1 を指定。

また、出力先も新しく作成した 0002_add_table.sql とする。

コマンド実行後、以下のようなsqlが生成される。

-- CreateTable
CREATE TABLE "Company" (
    "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    "name" TEXT NOT NULL,
    "address" TEXT NOT NULL
);

先ほどと同様、 npx wrangler d1 migrations apply〜 でDBに反映できる。

5. データ投入

wrangleを使用してinsert文を実行できる。

# ローカル環境
$ npx wrangler d1 execute hono-prisma-demo-db --command "INSERT INTO  \"User\" (\"email\", \"name\") VALUES
('[email protected]', 'Jane Doe (Local)');" --local

# リモート環境
$ npx wrangler d1 execute hono-prisma-demo-db --command "INSERT INTO  \"User\" (\"email\", \"name\") VALUES
('[email protected]', 'Jane Doe (Remote)');" --remote

select文も実行でき、insertしたデータを確認可能。

$ npx wrangler d1 execute hono-prisma-demo-db --command "SELECT * FROM "User" WHERE "name" like '%Doe%';" --local

 ⛅️ wrangler 3.72.0
-------------------

🌀 Executing on local database hono-prisma-demo-db (__YOUR_D1_DATABASE_ID__) from .wrangler/state/v3/d1:
🌀 To execute on your remote database, add a --remote flag to your wrangler command.
┌────┬────────────────┬──────────────────┐
│ id │ email          │ name             │
├────┼────────────────┼──────────────────┤
│ 1  │ [email protected] │ Jane Doe (Local) │
└────┴────────────────┴──────────────────┘

以上で、D1へのDB作成〜migration〜データ投入・確認までを実施できた。

今回は以上とする。次はseedデータの投入を試してみたいと思う。

今回作業したリポジトリは以下に公開しています。

https://github.com/waka-apps/hono-prisma-d1-example