つい先日dbdocsに入門したという記事を書きましたが、dbdocsではDBマイグレーションの管理などはできないので、ちょっとそこが不満でした。

今回はPrismaに入門して、dbdocsと組み合わせることでGUIでも

Prismaとは

DBクライアント、DBマイグレーション、GUI出力といった機能が一体となったツールです。

Node.jsとTypeScriptを使用しています。

Prisma | Simplify working and interacting with databases

DBクライアントやDBマイグレーションのプレイグラウンドも用意してあります。親切。

Prisma Playground | Learn the Prisma ORM in your browser

とりあえずマイグレーションを体験してみる

QuickStartに沿ってやっていきましょう。

TypeScriptのプロジェクトは既に作成した前提で、関連するモジュールを追加していきます。

npm install prisma --save-dev

次にprismaの初期化処理を行います。

あんまり凝った構成にすると疲れるので、とりあえずSQLiteを使います。

npx prisma init --datasource-provider sqlite

すると、プロジェクトにprisma/schema.prismaというファイルが作成されます。

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

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

datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

このファイルに以下のモデルを追加していきます。

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

model Post {
  id        Int     @id @default(autoincrement())
  title     String
  content   String?
  published Boolean @default(false)
  author    User    @relation(fields: [authorId], references: [id])
  authorId  Int
}

ではこのモデルを使用してDBマイグレーションファイルを作成します。

npx prisma migrate dev --name init

このコマンドを実行すると、SQLiteのデータベースファイルとマイグレーションファイルが作成されます。

prismaディレクトリ配下にいろいろ作られる

この状態でdbファイルをSQLiteで開こうとしてみましたが、怒られてしまいました。

% sqlite prisma/dev.db
Unable to open database "prisma/dev.db": database disk image is malformed
% sqlite prisma/dev.db
Unable to open database "prisma/dev.db": file is encrypted or is not a database

2回実行してみましたが、何故か別のエラーが出ています。なぜ?

よく確認すると、SQLiteの使用バージョンが2.x.xだったことが分かりました。

% sqlite               
SQLite version 2.8.17
Enter ".help" for instructions

sqlite3で実行したらテーブルを読み込むことができました。

%sqlite3 prisma/dev.db
SQLite version 3.37.2 2022-01-06 13:25:41
Enter ".help" for usage hints.
sqlite> .tables # テーブル一覧を表示
Post                User                _prisma_migrations

しっかりマイグレーションができていますね。

クライアントを使ってみる

次に、ユーザーを作成するスクリプトを実装します。

適当なTypeScriptファイルを作成し、チュートリアルにある通りの実装をします。(index.tsというファイルを作成しました)

import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

async function main() {
    const user = await prisma.user.create({
        data: {
          name: 'Alice',
          email: 'alice@prisma.io',
        },
      })
      console.log(user)
}

main()
  .then(async () => {
    await prisma.$disconnect()
  })
  .catch(async (e) => {
    console.error(e)
    await prisma.$disconnect()
    process.exit(1)
  })

これを実行してみます。

% npx ts-node index.ts
{ id: 1, email: 'alice@prisma.io', name: 'Alice' }

作成されたようです。

実際にsqliteからも確認してみます。

sqlite> select * from User;
1|alice@prisma.io|Alice

作成されています!

クライアントを使うとかなり楽にモデルを扱えるみたいですね。

dbmlを出力してdbdocsと連携する

では本題です。

こうしてできたスキーマをDBMLとして出力してみます。

これをするためにはまず、prisma-dbml-generatorをインストールしておく必要があります。

DBML generator for Prisma

以下のコマンドでインストールします。

npm install -D prisma-dbml-generator

続けて、以下のgeneratorセクションをschema.prismaに追加します。

generator dbml {
  provider   = "prisma-dbml-generator"
  // output     = "../dbml" // 出力先フォルダ名
  // outputName = "database.dbml" // 出力するファイル名
}

最後に以下のコマンドを実行して、dbmlファイルを作成します。

npx prisma generate

コマンドを実行すると、新たにdbmlというディレクトリが作成され、そこにDBMLが格納されています。

中身は以下のようになっています。

//// ------------------------------------------------------
//// THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY)
//// ------------------------------------------------------

Table User {
  id Int [pk, increment]
  email String [unique, not null]
  name String
  posts Post [not null]
}

Table Post {
  id Int [pk, increment]
  title String [not null]
  content String
  published Boolean [not null, default: false]
  author User [not null]
  authorId Int [not null]
}

Ref: Post.authorId > User.id

きちんと作成されていますね。

あとはこれをdbdocsコマンドでビルドします。

(ログインを忘れずに!)

dbdocs build prisma/dbml/schema.dbml --project=prisma_to_dbml

無事にビルドできたので見てみます。

テーブルスキーマ
リレーションシップ

ちゃんと作成されています。

感想

dbdocsと連携ができました。

Prisma標準のGUIツールもあるんですが、ER図を描画できてしかも場所を記憶してくれるので、この辺はdbdocsのほうが使いやすそうだな…と個人的には思いました。

しかしまだ詳しく調べたきれているわけじゃないので、PrismaでER図出力だったらこっちのほうが使いやすいよ!みたいなのがあればコメントお願いします!