Rustのデータベース接続|Dieselの使い方

先生

Rustで安全かつ効率的にデータベースを操作!Dieselの使い方を徹底解説します。

Rustでデータベース接続:Diesel入門

Rustでデータベースを扱うなら、Dieselは強力な選択肢です。Dieselは、Rustの型安全性を活かしつつ、効率的なデータベース操作を可能にするORM(Object-Relational Mapper)です。この記事では、Dieselの基本的な使い方を通して、Rustでのデータベース接続を解説します。

Dieselを使うことで、SQLクエリを直接記述する手間を減らし、コンパイル時に型チェックを行うことで、実行時エラーのリスクを低減できます。データベースとの連携をより安全かつ効率的に行うための第一歩を踏み出しましょう。

Dieselのセットアップ

まず、Dieselをプロジェクトに導入します。Cargo.tomlファイルに以下の依存関係を追加してください。


toml
[dependencies]
diesel = { version = "2.0", features = ["postgres"] } # 使用するデータベースに合わせてfeaturesを変更
dotenv = "0.15"

上記の例では、PostgreSQLを使用する場合の設定です。MySQLやSQLiteを使用する場合は、postgresの部分をそれぞれmysqlsqliteに変更してください。

次に、.envファイルを作成し、データベースの接続情報を記述します。


.env
DATABASE_URL=postgres://user:password@localhost/database_name

DATABASE_URL には、実際のデータベース接続文字列を設定してください。userpasswordlocalhostdatabase_name は、ご自身の環境に合わせて変更する必要があります。

データベーススキーマの定義

Dieselでは、データベースのテーブル構造をRustの型として定義します。schema.rsファイルを作成し、テーブルの定義を記述します。


rust
// schema.rs
table! {
    posts (
        id,
    ) {
        id -> Int4,
        title -> Varchar,
        body -> Text,
        published -> Bool,
    }
}

この例では、postsという名前のテーブルを定義しています。idtitlebodypublishedというカラムがあり、それぞれの型も指定されています。この定義に基づいて、Dieselは安全なクエリを生成できます。

次に、Diesel CLIを使ってスキーマを生成します。まず、Diesel CLIをインストールします。


bash
cargo install diesel_cli --no-default-features --features postgres # 使用するデータベースに合わせてfeaturesを変更

インストール後、プロジェクトのルートディレクトリで以下のコマンドを実行します。


bash
diesel setup
diesel migration generate create_posts

diesel setup は初期設定を行い、diesel migration generate create_posts はマイグレーションファイルを作成します。 create_posts はマイグレーションの名前で、テーブルを作成する処理を記述します。


rust
// migrations/XXXX_create_posts/up.sql
CREATE TABLE posts (
    id SERIAL PRIMARY KEY,
    title VARCHAR NOT NULL,
    body TEXT NOT NULL,
    published BOOLEAN NOT NULL DEFAULT FALSE
);

// migrations/XXXX_create_posts/down.sql
DROP TABLE posts;

up.sql にはテーブル作成のSQLを、down.sql にはテーブル削除のSQLを記述します。最後に、マイグレーションを実行します。


bash
diesel migration run

Dieselを使ったCRUD操作

Dieselを使って、データベースのCRUD操作(Create、Read、Update、Delete)を行う方法を見ていきましょう。

まずは、モデルを定義します。


rust
// src/models.rs
use diesel::prelude::*;

#[derive(Queryable)]
pub struct Post {
    pub id: i32,
    pub title: String,
    pub body: String,
    pub published: bool,
}

#[derive(Insertable)]
#[diesel(table_name = crate::schema::posts)]
pub struct NewPost<'a> {
    pub title: &'a str,
    pub body: &'a str,
}

Queryable は、データベースから取得したデータを格納するための構造体です。Insertable は、データベースに新しいレコードを挿入するための構造体です。

次に、CRUD操作を行うための関数を実装します。


rust
// src/lib.rs

pub mod models;
pub mod schema;

use diesel::prelude::*;
use dotenvy::dotenv;
use std::env;

use self::models::{Post, NewPost};

pub fn establish_connection() -> PgConnection {
    dotenv().ok();

    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    PgConnection::establish(&database_url)
        .unwrap_or_else(|_| panic!("Error connecting to {}", database_url))
}

pub fn create_post(conn: &mut PgConnection, title: &str, body: &str) -> Post {
    use crate::schema::posts;

    let new_post = NewPost { title, body };

    diesel::insert_into(posts::table)
        .values(&new_post)
        .get_result(conn)
        .expect("Error saving new post")
}

pub fn read_posts(conn: &mut PgConnection) -> Vec<Post> {
    use crate::schema::posts::dsl::*;

    posts
        .load::<Post>(conn)
        .expect("Error loading posts")
}

pub fn update_post(conn: &mut PgConnection, post_id: i32, new_title: &str) -> Post {
    use crate::schema::posts::dsl::*;

    diesel::update(posts.filter(id.eq(post_id)))
        .set(title.eq(new_title))
        .get_result(conn)
        .expect(&format!("Unable to find post {}", post_id))
}

pub fn delete_post(conn: &mut PgConnection, post_id: i32) -> usize {
    use crate::schema::posts::dsl::*;

    diesel::delete(posts.filter(id.eq(post_id)))
        .execute(conn)
        .expect("Error deleting posts")
}

これらの関数を使うことで、データベースのCRUD操作を簡単に行うことができます。

参考リンク

まとめ

Dieselを使うことで、Rustで型安全かつ効率的にデータベースを操作できます。セットアップからCRUD操作まで、この記事で紹介した内容を参考に、ぜひDieselをRustプロジェクトに取り入れてみてください。Dieselは、Rustの強力な型システムと組み合わせることで、より安全で信頼性の高いアプリケーション開発を支援します。