前々回書いたPGliteの続きです。PrismaのドキュメントDatabase driversによるとPGliteはCommunity-maintained database driver adaptersとしてアダプターが用意されているようなので試してみました。
RailsプログラマーのためのPrisma入門のコードを動かしてみよう
以前書いたRailsプログラマーのためのPrisma入門(1)、(2)、(3)で使ったコードをPGliteで動かしてみました。
まず最初に、Prismaはブラウザー上では動かないようなので、PGliteもNode.js上で動かします。
pglite-adapter-prismaに書かれている手順で RailsプログラマーのためのPrisma入門(1) のコードをPGliteで動かしてみました。結論から言うと動きました。
ハマった事 (1)
しかし、簡単ではありませんでした。まずpglite-adapter-prismaに
The adapter only supports Prisma Client. Prisma migration and introspection are not supported, though I want to make a cli tool to help with that in the future.
と書かれています。DeepLで翻訳すると
このアダプターはPrismaクライアントのみをサポートしています。Prismaマイグレーションとイントロスペクションはサポートしていません。 将来的にはそれを手助けするcliツールを作りたいと思っている。
という事で、マイグレーションは諦めCREATE TABLEを行うプログラムを書きました。
import { PGlite } from '@electric-sql/pglite';
const db = new PGlite('./pg_data');
(async () => {
await db.exec(`
CREATE TABLE "cats" (
"id" SERIAL NOT NULL,
"name" VARCHAR(255) NOT NULL,
"reference_image_id" VARCHAR(255),
"temperament" VARCHAR(255),
"description" TEXT,
"country_id" INTEGER,
CONSTRAINT "cats_pkey" PRIMARY KEY ("id"));
CREATE TABLE "countries" (
"id" SERIAL NOT NULL,
"name" VARCHAR(255) NOT NULL,
"country_code" VARCHAR(2) NOT NULL,
CONSTRAINT "countries_pkey" PRIMARY KEY ("id"));
ALTER TABLE "cats" ADD CONSTRAINT "cats_country_id_fkey" FOREIGN KEY ("country_id")
REFERENCES "countries"("id") ON DELETE SET NULL ON UPDATE CASCADE;
`);
})();
ハマった事 (2)
これはPrismaを使っていれば常識なのかもしれませんが、schema.prisma
のgenerator client
を変更したので
npx prisma generate
を実行して@prisma/client
を再生成しないといけません。
最初これを忘れていて、コードがエラーになっていました。
schema.prisma ファイル
enerator client {
provider = "prisma-client-js"
previewFeatures = ["driverAdapters", "relationJoins"]
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Cat {
id Int @id @default(autoincrement())
name String @db.VarChar(255)
countryId Int? @map("country_id")
referenceImageId String? @db.VarChar(255) @map("reference_image_id")
temperament String? @db.VarChar(255)
description String? @db.Text
country Country? @relation(fields: [countryId], references: [id])
@@map("cats")
}
model Country {
id Int @id @default(autoincrement())
name String @db.VarChar(255)
countryCode String @db.VarChar(2) @map("country_code")
cats Cat[]
@@map("countries")
}
変更点 (3)
pglite-adapter-prismaにあるようにPrismaClient
の初期化のコードを変えないといけません。
import { PrismaClient } from '@prisma/client';
import { CountriesData } from './seeds/countries';
import { CatsData } from './seeds/cats';
const prisma = new PrismaClient();
↓ 変更
import { PGlite } from '@electric-sql/pglite';
import { PrismaPGlite } from 'pglite-prisma-adapter';
import { PrismaClient } from '@prisma/client';
import dotenv from 'dotenv';
import { CountriesData } from './seeds/countries';
import { CatsData } from './seeds/cats';
dotenv.config();
const connectionString = `${process.env.DATABASE_URL}`;
const client = new PGlite(connectionString);
const adapter = new PrismaPGlite(client);
const prisma = new PrismaClient({ adapter });
やはりpsqlコマンドが欲しい〜
前回はブラウザーで動かしているのでPGlite REPL React Componentが使えましたが、今回はnode.js上で動かしているので使えません。
結局、超手抜きのpsql風のプログラムを書いてしまいました。
import { PGlite, Results } from '@electric-sql/pglite';
const db = new PGlite('./pg_data');
const lastArg = process.argv[process.argv.length - 1];
const beforeLastArg = process.argv[process.argv.length - 2];
(async () => {
if (lastArg == 'd') {
const sql = "SELECT table_name FROM information_schema.tables WHERE table_type
= 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')";
const result:Results = await db.query(sql);
console.log(result.rows);
} else if (beforeLastArg == 'd') {
const sql = `SELECT column_name, data_type, character_maximum_length, column_default,
is_nullable FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '${lastArg}'`;
const result:Results = await db.query(sql);
console.log(result.rows);
} else {
const result = await db.query(lastArg);
console.log('rows:',result.rows,);
console.log('affectedRows:', result.affectedRows);
}
})();
コマンドラインで指定したSQL文が実行できます、まだd
でテーブルの一覧、d テーブル名
でテーブル定義が表示されるようにしまいした。結果のフォーマッティングやエラー処理はありません。😅
まとめ
という事で現状ではPGlite + Prismaは実用的ではないと思います。 ただしPrisma(ORM)を使わなければ実用的だと思います。
マイグレーションが使えるようになり、psql
的なツールが出たら使ってみたいです。