LoginSignup
4
3

More than 1 year has passed since last update.

【Rust】SQLxで非同期にMySQLにクエリを送ってみた話。

Posted at

はじめに

RustでDBを扱うとなるとDIESELが定番らしいですが、こちらはどうやら非同期処理を扱っていない様子。
ということで、このところ非同期処理で人気になってきたらしいSQLxを使ってみたので、その過程を記事にしてみました。
チュートリアルみたいな感覚で見て頂けると嬉しい限りです。

事前知識

事前知識として、以下のようなものがあると理解がしやすいかなと思います。
もし本記事で分からないところがあれば、参考文献として見てみてください。
ちなみに自分は一昨日くらいにMySQLを触り始めた者です。

環境

  • OS: Windows 10
  • Rust: 1.57.0
    • 各クレートの詳細は後述のCargo.tomlを参照されたし。

SQLxとは

開発を始める前に、まずはSQLxがどのようなクレートなのかを紹介します。
といっても、GitHubのREADMEに書かれていることの丸パクリなので大した情報量はないです。

SQLxとは以下のような特徴をもつ純Rust製のSQLフレームワークです。

  • 非同期処理による同時実行性を提供
  • PostgreSQL、MySQL、SQLite、及びMSSQLをサポート
  • マクロにより、SQL構文をそのまま埋め込める

やはり非同期処理があるといいですね。
The☆Rustって感じがします(適当

CLIインストール

ではSQLxを使うために、ぼちぼち環境構築をしていきましょう。
とはいっても、SQLxのCLIをインストールするだけです。

cargo install --version="0.5.10" sqlx-cli

versionのところは適宜変更してください。
後述のCargo.tomlのsqlxのバージョンと合わせるといいでしょう。

開発

ではいよいよSQLxを使っていきます。
今回はSQLxがどんなものかを試したいだけなので、

+------+--------------------------+
| id   | name                     |
+------+--------------------------+
|    1 | yukarisann kawaii yatta- |
+------+--------------------------+

こんな感じのテーブルを作ることを目標にします。
ユカリサンカワイイヤッター

プロジェクト作成

まずはお馴染みのcargoでRustのプロジェクトを作成します。

cargo new sqlx_mysql

依存関係

次にCargo.tomlに依存関係を記述します。

Cargo.toml
[package]
name = "sqlx_mysql"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
async-std = { version = "1.8.0", features = [ "attributes" ] }
dotenv = "0.15.0"
sqlx = { version = "0.5.10", features = [ "mysql", "runtime-async-std-native-tls" ] }

各クレートの役割は以下のような感じです。

async-std dotenv sqlx
main()のasync化 .envの読み込み MySQLへのアクセス

.env作成

環境変数を記述する.envをプロジェクトルートに作成しましょう。

.env
DATABASE_URL=mysql://[user]:[password]@[host]:[port]/sqlx_test

諸々の個人情報は、ご自分の環境に合わせて適宜変更してください。
自分はだいたい以下のようになりました。

.env
DATABASE_URL=mysql://root:[password]@localhost:3306/sqlx_test

DB作成

開発に使うDBを作成します。
先程の.envに記述したsqlx_testというDBを以下のコマンドで新規作成しましょう。

sqlx db create

マイグレーションファイル作成

以下のコマンドでマイグレーションファイルを作成します。

sqlx migrate add test

するとmigrations/[timestamp]_test.sqlが作成されているはずなので、そこに以下のSQL構文を記述しましょう。

[timestamp]_test.sql
CREATE TABLE IF NOT EXISTS hoge(
    id int,
    name varchar(255)
);

そうしたら、以下のコマンドでマイグレーションを反映させます。

sqlx migrate run

main.rs

ようやっとmain.rsを書きます。

src/main.rs
use std::{env,process};
use dotenv::dotenv;
use sqlx::mysql::MySqlPool;

#[async_std::main]
async fn main(){
    dotenv().ok();    // .envの読み込み
    let database_url=match env::var("DATABASE_URL"){
        Ok(ok)=>ok,
        Err(err)=>{
            eprint!("Error: std::env said, {}\n",err);
            process::exit(1);
        }
    };

    let pool=match MySqlPool::connect(&database_url).await{
        Ok(ok)=>ok,
        Err(err)=>{
            eprint!("Error: sqlx said, {}\n",err);
            process::exit(1);
        }
    };

    if let Err(err)=sqlx::query!(r#"
        INSERT INTO hoge(
            id,
            name
        )
        VALUES(
            1,
            "yukarisann kawaii yatta-"
        );
    "#)
    .execute(&pool)
    .await{
        eprint!("Error: sqlx said {}\n",err);
        process::exit(1);
    }
}

かなりのウンコードですが、ゆかりさんの可愛さが全てを解決してくれます。
やったね!

真面目にポイントを解説すると、query!内の文字列はr##でraw文字列にした方がいいと思います。
raw文字列はエスケープシーケンスを必要としないので、""の中に""を素のまま記述できるんですね。
そんなことしなくたって、中に記述するのを''に変えればいいだけの話じゃん。

実行

とりあえず動くものはできたので、実際に動かしてみましょう。

cargo run

めっさ長いコンパイルを乗り越えたら多分正常に実行されているはずです。
コンパイルエラーが起きていなければ、以下のSQL構文でテーブルを確認してみましょう。

USE sqlx_test;
SELECT * FROM hoge;

上手くいけば、目標としていた以下のような出力が得られるはずです。

+------+--------------------------+
| id   | name                     |
+------+--------------------------+
|    1 | yukarisann kawaii yatta- |
+------+--------------------------+

ディレクトリ構成

最終的に、以下のようなディレクトリ構成になります。

📦sqlx_mysql
 ┣ 📂migrations
 ┃ ┗ 📜[timestamp]_test.sql
 ┣ 📂src
 ┃ ┗ 📜main.rs
 ┣ 📜.env
 ┣ 📜.gitignore
 ┣ 📜Cargo.lock
 ┗ 📜Cargo.toml

おわりに

今回SQLxのほんのさきっちょを触ってみて、やはりSQL構文を直書きできるのは素直で書きやすいなと思いました。
ただやはり開発が活発ということもあり、公式のexampleが少し不足気味な気がします。
あと、ドキュメントをもう少し整備してくれるとありがたいですね。
そこら辺の問題はクレートが安定化するにつれて解決していくはずなので、ありがたやと手を合わせながら待ちましょう。

またね。

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3