📘
Supabaseのauth.usersと自前のテーブル間でリレーションを貼る方法
はじめに
Supabaseでは、デフォルトで auth.users
テーブルが用意されています。アプリ側のユーザー情報とこのテーブルをリレーションしたくなることはよくありますよね。
ところが、Drizzle ORM でマイグレーションを実行しようとすると、こんなエラーが出て困ったことはありませんか?
PostgresError: permission denied for schema auth
この記事では、マイグレーションエラーを回避しつつ auth.users
にリレーションを貼る安全な方法を紹介します。
auth.users
を参照しようとすると詰む
背景:素直に 以下のように、authSchema.table("users")
を使って auth.users
を参照しようとすると…
// NG: この方法だと permission denied エラーになる
const authSchema = pgSchema("auth");
export const Users = authSchema.table("users", {
id: uuid("id").primaryKey(),
});
export const Profile = pgTable("profile", {
id: uuid("id")
.primaryKey()
.references(() => Users.id, { onDelete: "cascade" }),
name: varchar("name", { length: 25 }).notNull(),
email: varchar("email", { length: 255 }).notNull(),
});
この状態で drizzle-kit push や migrate を実行すると、PostgreSQL からこのようなエラーが返ってきます:
PostgresError: permission denied for schema auth
これは、Supabase の auth スキーマが read-only に制限されており、Drizzle がマイグレーション対象として扱おうとして失敗してしまうためです。
解決法:drizzle-orm/supabase に用意された authUsers を使う
実は、Drizzle ORM には drizzle-orm/supabase パッケージに authUsers という定義済みの参照が用意されています。
これを使えば、マイグレーション対象にならず、安全にリレーションを貼るだけが可能になります。
以下のように書き換えることで、マイグレーションエラーを回避できました。
import { authUsers } from "drizzle-orm/supabase";
import { pgTable, uuid, varchar } from "drizzle-orm/pg-core";
export const Profile = pgTable("profile", {
id: uuid("id")
.primaryKey()
.references(() => authUsers.id, { onDelete: "cascade" }), // ✅ ここで安全に参照
name: varchar("name", { length: 25 }).notNull(),
email: varchar("email", { length: 255 }).notNull(),
});
これで auth.users に対して外部キーリレーションを貼りつつ、permission denied エラーも発生しませんでした 🎉
まとめ
- Supabase の auth.users は read-only なスキーマのため、Drizzle でマイグレーション対象に含めるとエラーになる
- pgSchema("auth").table("users") を使うとマイグレーションが失敗する
- 解決策として、drizzle-orm/supabase の authUsers を使うと安全に参照できる
Supabase × Drizzle を使っている方で同じようにハマった方の助けになれば嬉しいです 🙌
Discussion