Supabase Tips サーバーのスキーマとそのテーブルのデータをローカルのSupabaseに反映させる。

# 想定

最初はSupabaseのサーバー上でプロジェクトを作って、後からSupabaseのローカル開発環境を構築した時に、サーバーからスキーマとテーブルのデータをローカルに反映させたい時。

# 疑問

SupabaseではAIに Supabase のドキュメントを読み込ませて、それを踏まえて回答をしてくれます。
Supabaseに関して疑問に思ったことは ↓このAIに聞いてみると良いかもしれません。

https://supabase.com/docs



# コピー

基本３種類のコマンドがあるみたいです。

diff コマンド  (差分を取る)

dumpコマンド (保存する)

PUSH PULLコマンド (シンクロさせる)

今回は、これらのうち diffコマンド を使って サーバーからローカルにスキーマを反映させる方法を紹介します。

<details><summary>diff コマンドのヘルプ</summary>

```
> supabase db diff -h
Diffs the local database for schema changes

Usage:
  supabase db diff [flags]

Flags:
      --db-url string    Diffs against the database specified by the connection string (must be percent-encoded).
  -f, --file string      Saves schema diff to a new migration file.
  -h, --help             help for diff
      --linked           Diffs local migration files against the linked project.
      --local            Diffs local migration files against the local database. (default true)
  -s, --schema strings   Comma separated list of schema to include. (default all)
      --use-migra        Use migra to generate schema diff. (default true)
      --use-pgadmin      Use pgAdmin to generate schema diff.

```

※against は比較するという意味です。

diff コマンドは、サーバー側の設定をすべて出力してくれます。

</details>


<details><summary>「データベース管理におけるツールの使い分けについて」 </summary>
サーバーとローカルの差分を埋めるのが目的なので diffコマンド を今回は利用してみました。
どの方法を使うかはもう個人の好みだと思います。

ただデータが大量になってきたり、複雑になってきたりすると migra 等の差分検出ツールやバックアップ専用ツールで使えるオプションがあったりするので、その辺りは調べてから使い分けると良いかもしれません。
DBeaver等のGUIツールを使うのも良いかもしれません。

各種ツールがあるのは知っていますが、どの場面でどのツールを使うのが最適かの知識はありません、DB関連のツールは豊富にありすぎます。

</details>



# 環境

Supabaseのアカウント
Supabaseのサーバーダッシュボード
Supabaseのローカル開発環境
SupabaseのCLIのインストール

```terminal
> supabase  -v
1.93.0

```


これらはすべて 登録 and インストール済み とします。



# 用語

## サーバー
Supabaseのサーバー側DB

## ローカル
Supabaseのローカル側DB

## サーバーのダッシュボード

`https://supabase.com/dashboard/project/[Reference ID (=project-id)]`

## ローカルのダッシュボード

`http://localhost:54323/project/default`



# 重要コマンド

Supabase cliの更新

scoop update supabase


現在保存されているマイグレーションファイルとシードファイルをすべて適用します。

supabase db reset

※逆に言えば、マイグレーションファイルやシードファイルに保存していないものをすべて破棄してしまいます。
ローカル開発環境で色々テーブルやデータをさわった後で元に戻したい時は大変便利です。

ローカルのSupabaseを開始します。

supabase start

これまでの変更を保存して終了します。

supabase stop

これまでの変更が破棄されて終了します。

supabase stop --no-backup



## マイグレーション関連の操作

サーバーとローカルのマイグレーション状況を表示します。
supabase migration list

※↑このコマンドはあくまでもローカル側からみたスキーマの状態です。

REMOTE（サーバー）側への適用方法
supabase migration repair [タイムスタンプ] --status applied
例
supabase migration repair 20231017082823 --status applied

REMOTE（サーバー）側の削除方法
supabase migration repair [タイムスタンプ] --status reverted
例
supabase migration repair 20231017082823 --status reverted

※タイムスタンプは、

supabase migration list

↑このコマンドで出てくる表で確認出来ます。

ローカル側にスキーマを追加する場合はマイグレーションファイルを生成するコマンドを実行します。
supabase migration new [create_[ファイル名]]


ローカル側はマイグレーションファイルを削除するだけで消えます。

マイグレーションファイルを削除した場合は、その結果を環境へ反映させるために↓このコマンドを実行します。

supabase db reset



## diffコマンドの基礎

基本的に差分がすべてターミナルに出力されます。
マイグレーションファイルに保存したい時はファイル名を指定します。

### 現在のローカルとの差分

supabase db diff

### リンク先（＝通常サーバー側）との差分

supabase db diff --linked



## dumpコマンドの基礎

supabase db dump

↑このコマンドはサーバー側のスキーマとデータをダンプします。
これらを指定するオプションが提供されています。

スキーマのみを指定するオプション

データのみを指定するオプション

helpコマンドもしくは下の方に書いた参照URL Supabase CLI のコマンド (v1.93.0) を御覧ください。



# サーバーに作ってあったスキーマ（テーブル等）やデータをローカルに反映させる方法

0からやる時はdiffコマンドを使います。
最初に **ローカル** のマイグレーションファイルを全部削除します。
※インストール時に用意された初期サンプルなどのデータが残っている場合などがあるため。



## マイグレーションファイルの場所

supabase\migrations

↑このフォルダにマイグレーションファイルが保存されています。



## 現状把握

次にサーバーとローカルのマイグレーションの状況を確認します。

```terminal
> supabase migration list

    LOCAL │ REMOTE │ TIME (UTC)
  ────────┼────────┼─────────────

```

※supabase migration list このコマンドはあくまでもローカル側からみたスキーマの状態です。



タイムスタンプ (数字) が残っていたら
supabase migration repair
↑このコマンドを使って操作します。

次にdiffコマンドでローカルの差分を取ります。
supabase db diff
スキーマの設定がないのなら何も起こらず終了するはずです。

ローカルにマイグレーションファイルを新しく作ります。
supabase migration new [create_[ファイル名]]
※ファイル名は自由につけられます。

```terminal
> supabase migration new create_local

Created new migration at supabase\migrations\20231019063619_create_local.sql.

```



新しいマイグレーションを記録するファイルが出来ました。


次に先ほど作成したマイグレーションファイルにサーバーの差分を取ります。
supabase db diff --linked > supabase\migrations\20231019063619_create_local.sql

↓ローカルのテーブルの状況をブラウザ上から確認しておきます。
現在、テーブルは何も作られていないはずです。

ローカル ダッシュボード

http://localhost:54323/project/default/editor


↓reset コマンドで マイグレーションファイルをローカルに反映させます。

supabase db reset

ローカル ダッシュボードをブラウザを差再読み込みしてもう一度見てみます。

http://localhost:54323/project/default/editor

サーバーで作ったテーブルがローカルに反映されているはずです。

注意：この手法ではサーバーのスキーマのコピーをローカルに反映できますがサーバーのデータは保存されません、なので別にバックアップ作業をする必要があります。

マイグレーションの状況を見てみます。

```terminal
> supabase migration list

        LOCAL      │ REMOTE │     TIME (UTC)
  ─────────────────┼────────┼──────────────────────
    20231019063619 │        │ 2023-10-19 06:36:19

```

※数字部分（タイムスタンプ）は開発環境によって異なります。

supabase migration repairコマンドを利用してサーバー側に反映させます。

supabase migration repair [タイムスタンプ] --status applied

例
supabase migration repair 20231019063619 --status applied

```terminal
> supabase migration list

        LOCAL      │     REMOTE     │     TIME (UTC)
  ─────────────────┼────────────────┼──────────────────────
    20231019063619 │ 20231019063619 │ 2023-10-19 06:36:19

```

↑LOCALとREMOTEの数字が同じになっているはずです。

以上でスキーマがローカルにも反映されました。
次にサーバーのテーブルに保存してあるデータをローカルにも反映させます。



# サーバー側のデータの取り方

supabase db dump ダンプコマンドを使います。

supabase db dump -f supabase/seed.sql --data-only

↑このコマンドでseedファイルにデータが保存されました。

↓resetコマンドでseedファイルの情報をローカルに反映させます。

supabase db reset

これでサーバーとローカルのスキーマとデータの同期が取れました。

以上で作業は終了です。



# etc

supabase db push
supabase db pull

↑これらのコマンドも考えたのですが、これらのコマンドはサーバーとローカルの同期が取れてない状態の時に使ってもエラーが出るだけなので使用しませんでした。

サーバーとローカルがシンクロしている時に変更を反映させたい場合に便利なコマンドではないでしょうか？





# 参考

https://qiita.com/masakinihirota/items/b4b168a056dc10776d87

https://qiita.com/masakinihirota/items/b84c071415eeebb4a252