Loading...

2023-11-06(月) 15:00

⚒️ Supabase CLIを使ってデータベースを操作する

Supabase
Supabase CLI を使ってローカル環境の Supabase のデータベースにテーブルを作成したり、データを投入したりします。また、その後本番環境の Supabaseにローカル環境の内容をプッシュして反映するまでの手順を解説します。

目次

前提と注意事項

この記事では以下を前提としています。

  • Supabase CLI がインストールされていること
  • ローカル環境に Supabase 環境が構築されていること

上記については以下の記事にまとめていますのでよければ参考にしてください。

⚙️ Supabase CLIとSupabaseのローカル開発環境をセットアップする

Supabase CLIをmacOSで使えるようにし、Supabaseをローカル環境に構築するまでの手順を解説します。

ritaiz.com

この記事のゴール

Supabase CLI を使ってローカル環境の Supabase のデータベースにテーブルを作成したり、データを投入したりします。
また、その後本番環境(リモート)の Supabase(supabase.com)にローカル環境の内容をプッシュして反映するまでの手順を解説します。 以降では、本番環境のことをローカルに対してリモートと表記します。

テーブルを作成する

テーブルを作成したり変更したりするには、まず作成(もしくは変更)するテーブルについて記述したマイグレーションファイルを作成し、それを元にしたマイグレーションを実行するという流れになります。 Supabase CLI では、以下のようにmigration newを使って新しくマイグレーションファイルを作成できます。 なお、以降では、Supabase を使用するプロジェクトのルートディレクトリを./my-projectとしています。

./my-project
$ supabase migration new create_users_table

以下が実行結果です。

./my-project
$ supabase migration new create_users_table
Created new migration at supabase/migrations/20231104222217_create_users_table.sql

./my-project/supabase/migrationsの中にタイムスタンプ付きのマイグレーションファイルが作成されます。 このマイグレーションファイルは、作成時点では空になっています。
ここにどのようなテーブルを作成するかを SQL 文で記述します。 例えば、以下のような内容にします。

./my-project/supabase/migrations/20231104222217_create_users_table.sql
create table
  public.users (
    id not null default uuid_generate_v4(),
    nickname text not null default ''::text,
    first_name text not null default ''::text,
    last_name text not null default ''::text,
    first_name_kana text default ''::text,
    last_name_kana text default ''::text,
    email text not null default ''::text,
    created_at timestamp with time zone not null default now(),
    updated_at timestamp with time zone not null default now()
  );

上記のマイグレーションファイルを作成したら、以下のコマンドでマイグレーションを実行します。

./my-project
$ supabase db reset

以下が実行結果です。

./my-project
$ supabase db reset
Resetting local database...
Recreating database...
Setting up initial schema...
Applying migration 20231104222217_create_users_table.sql...
Seeding data supabase/seed.sql...
Restarting containers...
Finished supabase db reset on branch update/update-migration.

ここでローカルの Supabase のダッシュボード(http://127.0.0.1:54323)にブラウザでアクセスし、テーブル一覧を確認してみると、以下のようにusersテーブルが作成されていることを確認できます。

ローカルのSupabaseのダッシュボードに作成されたテーブル

これでマイグレーションファイルを作成し、マイグレーションを実行することでテーブルをローカル環境の Supabase に作成することができました。

なお、supabase db resetは、全てのテーブルを一旦削除した上ですべてのマイグレーションファイルを実行します。 すなわち、データベース自体を削除して再構築するコマンドになります。そのため、もし開発中のアプリを通して投入したデータも削除されてしまいます。
もし新しく作成したマイグレーションファイルだけを実行したい場合は、以下のようにsupabase migration upを使用します。

./my-project
$ supabase migration up

以下が実行結果です。

./my-project
 supabase migration up
Connecting to local database...
Applying migration 20231105002001_create_new_table.sql...
Local database is up to date.

supabase db resetとは異なり、最後のマイグレーション実行以降に新しく作成されたマイグレーションファイルだけを実行します。 本記事執筆時点だと、確認した限りはローカル環境のマイグレーションを戻すコマンドは存在しないようです。 (リモートのマイグレーションを戻すコマンドとしてはsupabase migration repairを使って可能です。)

テーブルを変更する

今度はテーブルに新しくカラムを追加してみます。 例えば、住所用のカラムとしてaddressカラムを追加してみます。 作成した場合と同様に、まずはマイグレーションファイルを作成します。

./my-project
$ supabase migration new add_address_to_users_table

マイグレーションファイルの中身を以下のようにします。

./my-project/supabase/migrations/20231104222217_add_address_to_users_table.sql
alter table
if exists public.users add address text;

再度マイグレーションを実行します。

./my-project
$ supabase db reset

以下が実行結果です。

./my-project
$ supabase db reset
Resetting local database...
Recreating database...
Setting up initial schema...
Applying migration 20231104222217_create_users_table.sql...
Applying migration 20231105033533_add_address_to_users_table.sql...
Seeding data supabase/seed.sql...
Restarting containers...
Finished supabase db reset on branch update/update-migration.

ブラウザでローカルの Supabase のダッシュボードにアクセスしてみると、usersテーブルにaddressカラムが追加されていることを確認できるはずです。

テストデータを投入する

supabase db resetでは全てのテーブルを削除してしまうので、開発中のアプリケーションを通して投入したデータも消えてしまいます。 そこで、テストデータ自体もsupabase db resetと同時に投入するために、supabase/seed.sqlを使用します。 supabase/seed.sqlは、supabase db resetを実行するときに自動的に実行される SQL ファイルです。 supabase initを実行した時にプロジェクトのsupabaseディレクトリの中にseed.sqlがデフォルトで作成されています。 デフォルトだと中身は空なので、例として以下の内容にします。

./my-project/supabase/seed.sql
insert into users
  (nickname, first_name, last_name, first_name_kana, last_name_kana, email)
values
  ('テスト名', '太郎','Supabase', 'Tarou','upabase', '[email protected]'),
  ('テスト名2', '太郎2','Supabase', 'Tarou2','upabase', '[email protected]'),
  ('テスト名3', '太3','Supabase', 'Tarou3','upabase', '[email protected]');

上記はusersテーブルにテストデータを3件投入する例になります。supabase db resetを実行すれば、テストデータが投入されていることを確認できるはずです。

RLS (Row Level Security) を適用する

RLS (Row Level Security) についてもマイグレーションファイルを作成して反映することができます。 まずマイグレーションファイルを作成します。

./my-project
$ supabase migration new create_rls_policy_for_users_table

以下の内容にします。

./my-project/supabase/migrations/20231104222217_create_rls_policy_for_users_table.sql
-- RLSを有効化
alter table users enable row level security;
 
-- users ポリシーを作成
-- selectに対しては誰でも可とする
create policy users_select on users for select using (
  true
);
 
-- update, delete, insert に対して、
-- users テーブルの id カラムの値が auth.uid() と一致する場合のみ許可する
-- auth.uid() は、Supabaseにおいて認証されたユーザーのUIDを返す
-- usersテーブルのIDとしてSupabaseのUIDを保存している前提
create policy users_update on users for update using (
  (users.id = auth.uid())
);
 
create policy users_delete on users for delete using (
  (users.id = auth.uid())
);
 
create policy users_insert
  on users for insert with check (
    (users.id = auth.uid())
  );

supabase db resetでマイグレーションを実行後、ローカルの Supabsae でusersテーブルを確認すると、以下のように4 active RLS policiesと表示されていることを確認できます。

RLSのポリシーが適用されている

4 active RLS policiesをクリックすると、以下のように適用したポリシーの詳細を確認できます。

適用されたRLSのポリシー

Databsae Function を作成する

Database Function も同じようにマイグレーションファイルで作成できます。

./my-project
$ supabase migration new create_hello_world_function

以下のような内容にします。

./my-project/supabase/migrations/20231104222217_create_hello_world_function.sql
create or replace function hello_world()
returns text
language sql
as $$
  select "Hello World!";
$$;

上記のhello_world関数自体は意味のないものですが、マイグレーションを実行すると以下のようにローカルの Supabase のFunctionshello_world関数が作成されていることを確認できます。

作成されたDatabase Function

リモートにデータを反映する

これまでに実行したマイグレーションの内容をリモートに反映させてみます。

ローカルとリモートのプロジェクトを紐付ける

まずはじめに、リモートの Supabase に現在のプロジェクトを紐付けます。 supabase linkコマンドを使います。

./my-project
$ supabase link --project-ref xxxxxxxxxxxxxxxxx

上記のxxxxxxxxxxxxxxxxxの部分は、自身の Supabase プロジェクト固有のプロジェクト ID です。このプロジェクト ID は、リモートの Supabase のダッシュボードにログインし後の URL から確認できます。具体的には以下のようなフォーマットになっており<project-id>部分がプロジェクト ID にあたります。

プロジェクトURL
https://supabase.com/dashboard/project/<project-id>

supabase linkを実行すると以下のように表示され、パスワード入力を求められます。これはプロジェクト作成時に設定したデータベースのパスワードです。

./my-project
$ supabase link --project-ref xxxxxxxxxxxxxxxxx
Enter your database password (or leave blank to skip):

パスワードが正しければ正常に紐付けが完了し、以下のようにFinished supabase link.と表示されます。

./my-project
$ supabase link --project-ref xxxxxxxxxxxxxxxxx
Enter your database password (or leave blank to skip):
Finished supabase link.

これで紐付けが完了です。

リモートのマイグレーション反映状況を確認する

紐付けが完了したらsupabase migration listを実行してローカルとリモートのマイグレーションの反映状況を確認します。

./my-project
$ supabase migration list
Connecting to remote database...
 
 
        LOCAL       REMOTE      TIME (UTC)
  ─────────────────┼────────┼──────────────────────
    20231104222217          2023-11-04 22:22:17
    20231105033533          2023-11-05 03:35:33
    20231105055711          2023-11-05 05:57:11
    20231105060551          2023-11-05 06:05:51

上記を見ると、LOCALには5個のマイグレーションが実行されていますが、REMOTEには何も実行されていないことがわかります。

リモートにマイグレーションを反映する

ここでsupabase db pushコマンドを使うことで、ローカルのマイグレーションをリモートに反映させることができます。

./my-project
$ supabase db push

以下が実行結果です。

./my-project
$ supabase db push
Connecting to remote database...
Applying migration 20231104222217_create_users_table.sql...
Applying migration 20231105033533_add_address_to_users_table.sql...
Applying migration 20231105055711_create_rls_policy_for_users_table.sql...
Applying migration 20231105060551_create_hello_world_function.sql...
Finished supabase db push.

上記のように、未反映のマイグレーションがリモートに反映されます。 リモートの Supabase にログインして確認すると、ローカルに作成したテーブルやカラムが反映されていることが確認できると思います。 なお、seed.sqlに記述したテストデータはローカル用でありリモートには反映されません。

他にも色々な状況のために Supabase CLI にはコマンドが用意されています。 全てはここで解説できないため、以下の公式ドキュメントを参考にしてください。

Supabase CLI

The Supabase CLI provides tools to develop your project locally and deploy to the Supabase Platform.

supabase.com

まとめ

Supabase CLI を使うことでデータベースに関連するおおよその操作を行うことができます。
また、マイグレーションファイルが作成、変更履歴として残るため、チーム開発でのデータベースの変更を管理することもできます。 さらにマイグレーションファイルがあれば同じ内容のデータベースを再現することもできるため、開発環境の構築も簡単になります。