🫰
RustからSupabase上のDBにアクセスする方法
こんにちは。カズマです。
ほぼ自分用のメモですが、共有させて頂きます。
SupabaseのデータベースをRustから利用するための手順を説明します。
最初にSupabaseでテーブルを作成し、次にRustからそのテーブルにアクセスする方法を見ていきましょう。
1. Supabaseの設定
Supabaseプロジェクトの作成
- Supabaseにアクセスし、アカウント作成・ログイン
- 「New Project」をクリックして新しいプロジェクトを作成
- プロジェクト名、パスワード、リージョンを設定して「Create new project」
テーブルの作成
- Supabaseダッシュボードで「Table Editor」に移動
- 「Create a new table」をクリック
- テーブル名とカラムを設定します(例:
posts
テーブル):-
id
: uuid, primary key -
title
: text, not null -
content
: text -
created_at
: timestamptz, default: now()
-
- 「Save」をクリックしてテーブルを作成
接続情報の取得
- ダッシュボードの「Connect」タブを開く
- 「Direct Connection」のURLをメモ
2. Rustプロジェクトのセットアップ
新しいプロジェクトの作成
cargo new supabase-test
cd supabase-test
必要なクレートの追加
Cargo.toml
に以下を追加:
[dependencies]
tokio = { version = "1", features = ["full"] }
sqlx = { version = "0.7", features = [
"runtime-tokio-rustls",
"postgres",
"time",
"uuid",
"chrono",
] } # chrono機能を追加
serde = { version = "1", features = ["derive"] }
serde_json = "1"
dotenv = "0.15"
uuid = { version = "1.3", features = ["v4", "serde"] }
chrono = { version = "0.4", features = ["serde"] }
環境変数ファイルの作成
プロジェクトルートに.env
ファイルを作成:
DATABASE_URL="postgres://postgres:[YOUR-PASSWORD]@db.[YOUR-PROJECT-ID].supabase.co:5432/postgres"
※Supabaseの接続文字列URIをコピーして貼り付けます。
3. Rustコードの実装
src/main.rs
に以下のコードを実装します:
use serde::{Deserialize, Serialize};
use sqlx::{postgres::PgPoolOptions, FromRow};
use uuid::Uuid;
#[derive(Debug, Serialize, Deserialize, FromRow)]
struct Post {
id: Uuid,
title: String,
content: Option<String>,
created_at: Option<chrono::DateTime<chrono::Utc>>,
}
#[derive(Debug, Serialize, Deserialize)]
struct NewPost {
title: String,
content: Option<String>,
}
#[tokio::main]
async fn main() -> Result<(), sqlx::Error> {
// 環境変数の読み込み
dotenv::dotenv().ok();
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
// データベース接続プールの作成
let pool = PgPoolOptions::new()
.max_connections(5)
.connect(&database_url)
.await?;
println!("Connected to Supabase PostgreSQL!");
// 新しい投稿の追加
let new_post = NewPost {
title: "Hello from Rust".to_string(),
content: Some("This is my first post from Rust to Supabase!".to_string()),
};
let post = sqlx::query_as::<_, Post>(
"INSERT INTO posts (title, content) VALUES ($1, $2) RETURNING id, title, content, created_at"
)
.bind(&new_post.title)
.bind(&new_post.content)
.fetch_one(&pool)
.await?;
println!("Created post: {:?}", post);
// 全ての投稿を取得
let posts = sqlx::query_as::<_, Post>("SELECT id, title, content, created_at FROM posts")
.fetch_all(&pool)
.await?;
println!("All posts:");
for post in posts {
println!("- {:?}", post);
}
Ok(())
}
4. 実行とテスト
cargo run
無事にSupabaseに接続してデータを格納/参照することができました。
このコードを実行すると:
- Supabaseのデータベースに接続
- 新しい投稿をテーブルに追加
- すべての投稿を取得して表示
トラブルシューティング
-
接続エラー: Supabaseのファイアウォール設定を確認してください。デフォルトでは、すべてのIPからの接続が許可されています。
-
認証エラー: パスワードが正しいことを確認してください。また、Supabaseのダッシュボードで「Database」→「Connection Pooling」がオンになっているか確認してください。
-
SQLxの準備エラー: クエリが正しいことを確認してください。Supabaseはデフォルトで
created_at
のようなタイムスタンプ列を自動的に追加します。
Discussion