Rustを初めて触ってその流れでDBからデータ取得までを試してみた

とある理由で、ほぼ遊び感覚で、Rustを使う機会がありました。
多少勉強しましたが、新しく難しい概念に悩まされ、イマイチ理解は進みません。
とりあえず手を動かしたかったので、DB取得までをやってみました。
メモとして残しますが、もっとRustらしく書けるんだろうなと感じています。
rusqliteを使って、sqlite3からデータを取得し表示するまでです。

環境構築は本家を参考にしました。
www.rust-lang.org

以降は、 rustc 1.42.0-nightly で動作確認済みです。
また、 my.db という名前でsqlite3のDBを用意していて、スキーマ等は以下の通りです。

$ sqlite3 my.db
sqlite> .schema users
CREATE TABLE users (user_id int primary key, name text not null);
sqlite> select * from users;
1|田中太郎
2|鈴木次郎

実際に書いたコードは以下です。

Cargo.toml

[package]
name = "demo"
version = "0.1.0"

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

[dependencies]
rusqlite = "*"

main.rs

extern crate rusqlite;

use rusqlite::{Connection, NO_PARAMS};

#[derive(Debug)]
struct User {
    user_id: usize,
    name: String,
}

fn get_users() -> Vec<User> {
    let conn = Connection::open("my.db").unwrap();
    let mut stmt = conn.prepare("
        SELECT
            user_id, name
        FROM
            users
        ORDER BY
            user_id ASC
    ",
    ).unwrap();

    let users = stmt.query_map(NO_PARAMS, |row| {
        Ok(User {
            user_id: row.get::<_, i64>(0).unwrap() as usize,
            name: row.get::<_, String>(1).unwrap(),
        })
    }).unwrap();

    let mut result: Vec<User> = vec![];
    for user in users {
        result.push(user.unwrap());
    }

    result
}

fn get_user(user_id: usize) -> Option<User> {
    let conn = Connection::open("my.db").unwrap();
    let mut stmt = conn.prepare("
        SELECT
            user_id, name
        FROM
            users
        WHERE
            user_id = ?
    ",
    ).unwrap();

    let id = user_id as i64;
    let mut users = stmt.query_map(&[&id], |row| {
        Ok(User {
            user_id: row.get::<_, i64>(0).unwrap() as usize,
            name: row.get::<_, String>(1).unwrap(),
        })
    }).unwrap();

    let user = users.next();
    match user {
        Some(user) => Some(user.unwrap()),
        None => None,
    }
}

fn main() {
    // 一覧取得
    println!("{:?}", get_users());
    // 存在するidを取得
    println!("{:?}", get_user(1));
    // 存在しないidを取得
    println!("{:?}", get_user(999));
}

上記を実行すると以下のようになります。

$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.02s
     Running `target/debug/demo`
[User { user_id: 1, name: "田中太郎" }, User { user_id: 2, name: "鈴木次郎" }]
Some(User { user_id: 1, name: "田中太郎" })
None

ユーザ一覧の取得とユーザ単体の取得(いる場合といない場合)についてうまくできました。
もうちょっとRustらしく書けそうなところもあり、 unwrap() しすぎな感じもありますが、今後の自分に期待します。