📘

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