Open11

Drizzle ORMのメモ

kenjkenj

Drizzleに入門したのでメモしていく

kenjkenj

drizzle.config.tsはこんな感じ

import { defineConfig } from 'drizzle-kit';

const databaseUrl =
  process.env.DATABASE_URL ||
  'postgresql://postgres:postgres@127.0.0.1:54322/postgres';
export default defineConfig({
  schema: './app/backend/db/schemas/**',
  out: './app/backend/db/migrations',
  dialect: 'postgresql',
  dbCredentials: {
    url: databaseUrl,
  },
});

schemaファイルはschemas配下に書けば認識してくれる

kenjkenj

共通するカラムはこんな感じで切り出しておくと使いやすい

import { timestamp, uuid } from 'drizzle-orm/pg-core';

export const id = uuid('id').primaryKey().defaultRandom();

const createdAt = timestamp('created_at', { withTimezone: true })
  .defaultNow()
  .notNull();
const updatedAt = timestamp('updated_at', { withTimezone: true })
  .defaultNow()
  .notNull();

export const defaultTimestamps = {
  createdAt,
  updatedAt,
};

export const schemaBase = {
  id,
  createdAt,
  updatedAt,
};

kenjkenj

generate する際は名前を指定したほうがよい。
でないと、自動で名前が作成されてわかりにくくなる

npx drizzle-kit generate --config drizzle.config.ts --name=create_hoges_table
kenjkenj

--customを付けると空のSQLファイルができるのでシードデータなど追加するのに便利

npx drizzle-kit generate --config drizzle.config.ts --custom --name=seed_hoges_table
INSERT INTO "hoges" ("name") VALUES ('hogehoge');
INSERT INTO "hoges" ("name") VALUES ('foofoo');

kenjkenj

generateは名前を付けつつ細かく実行したほうが、何をしているのかがわかりやすい

kenjkenj

generateしてミスったら drizzle-kit drop で削除できる

kenjkenj
  • migrate実行したあとにrollbackはできない
  • じゃあどうやってrollbackするんだ?
  • おそらく打ち消す感じのスキーマ か customで空のsqlファイル作成して対応する感じかな
kenjkenj

https://zenn.dev/mpyw/articles/rdb-ids-and-timestamps-best-practices#postgres-3

これを参考に ON UPDATE CURRENT_TIMESTAMP の対応をする

CREATE FUNCTION refresh_updated_at_step1() RETURNS trigger AS
$$
BEGIN
  IF NEW.updated_at = OLD.updated_at THEN
    NEW.updated_at := NULL;
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE FUNCTION refresh_updated_at_step2() RETURNS trigger AS
$$
BEGIN
  IF NEW.updated_at IS NULL THEN
    NEW.updated_at := OLD.updated_at;
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE FUNCTION refresh_updated_at_step3() RETURNS trigger AS
$$
BEGIN
  IF NEW.updated_at IS NULL THEN
    NEW.updated_at := CURRENT_TIMESTAMP;
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

テーブル作成するときは忘れずにtriggerをセットする

CREATE TRIGGER refresh_accounts_updated_at_step1
    BEFORE UPDATE ON accounts
    FOR EACH ROW
    EXECUTE FUNCTION refresh_updated_at_step1();

CREATE TRIGGER refresh_accounts_updated_at_step2
    BEFORE UPDATE ON accounts
    FOR EACH ROW
    EXECUTE FUNCTION refresh_updated_at_step2();

CREATE TRIGGER refresh_accounts_updated_at_step3
    BEFORE UPDATE ON accounts
    FOR EACH ROW
    EXECUTE FUNCTION refresh_updated_at_step3();

テーブル作成時に自動でトリガーをセットするイベントを作成しようとしたが権限を変えないといけなかったので、一旦generateしたあとに書くようにしている

漏れる可能性あるので、テストやら自動化するかで対策したい

kenjkenj

シードデータの作成はcustom オプションで空のsqlファイル作成してやるのがいいのか、
別途tsファイルで実行するのがいいのか迷っている

一旦sqlファイルで様子を見る