Drizzle ORMにおけるPostgreSQL ENUM型

SQLをDrizzle ORMに変換する際のPostgreSQL ENUM型の処理方法。pgEnumとテキストベースの代替手段を解説します。

Dialect-Specific

詳細な説明

DrizzleにおけるENUM型

PostgreSQLはカラムを定義済みの値セットに制限するカスタムENUM型をサポートしています。Drizzleはこの目的でpgEnum()ビルダーを提供しますが、SQLコンバーターはインラインのENUM型をtext()にマッピングします。これはCREATE TABLE文だけではenum値を常に抽出できないためです。

SQLにおけるPostgreSQL ENUM

CREATE TYPE status AS ENUM ('active', 'inactive', 'suspended');

CREATE TABLE accounts (
  id SERIAL PRIMARY KEY,
  email VARCHAR(255) NOT NULL,
  status status NOT NULL DEFAULT 'active'
);

pgEnumを使用したDrizzle

DrizzleのpgEnum()はテーブルの外側で定義されます:

import { pgEnum, pgTable, serial, varchar } from "drizzle-orm/pg-core";

export const statusEnum = pgEnum("status", ["active", "inactive", "suspended"]);

export const accounts = pgTable("accounts", {
  id: serial("id").primaryKey(),
  email: varchar("email", { length: 255 }).notNull(),
  status: statusEnum("status").notNull().default("active"),
});

コンバーターの動作

SQLコンバーターはENUM型のカラムをtext()にマッピングします。理由は:

  1. CREATE TYPEは別文: CREATE TYPE ... AS ENUM文はCREATE TABLEとは別であり、コンバーターはCREATE TABLEの解析に焦点を当てています。
  2. インラインENUM構文: MySQLのインラインENUM('a', 'b', 'c')構文は値を抽出するために特別な解析が必要です。

変換後、適切な箇所でtext()カラムを手動でpgEnum()に置き換える必要があります。

MySQL ENUMの代替

MySQLはカラム定義でインラインENUMをサポートしています:

CREATE TABLE accounts (
  id INT AUTO_INCREMENT PRIMARY KEY,
  role ENUM('admin', 'user', 'moderator') NOT NULL
);

Drizzleのmysql-coreはmysqlEnum()を提供します:

import { mysqlEnum, mysqlTable, serial } from "drizzle-orm/mysql-core";

export const accounts = mysqlTable("accounts", {
  id: serial("id").primaryKey(),
  role: mysqlEnum("role", ["admin", "user", "moderator"]).notNull(),
});

CHECK制約を使用したテキスト

SQLite(ネイティブENUMがない)では、型安全性のためにTypeScript共用体型とtext()を使用します:

export const accounts = sqliteTable("accounts", {
  role: text("role", { enum: ["admin", "user", "moderator"] }).notNull(),
});

ユースケース

PostgreSQLデータベースがステータスフィールド、ロール、カテゴリにENUM型を使用しており、基本的なテーブル構造の変換後にDrizzle ORMでそれらをどのように表現するかを知る必要がある場合。

試してみる — SQL to Drizzle Schema

フルツールを開く