やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Rust自習(SQLite3 2)

 オンメモリでなくファイルに保存する。

成果物

コード

 前回のコードとほぼ同じ。open()の引数:memory:をファイルパス/tmp/work/db.sqlite3にしただけ。

fn main() {
    let connection = sqlite3::open("/tmp/work/db.sqlite3").unwrap();
    connection
        .execute(
            "
            CREATE TABLE users (name TEXT, age INTEGER);
            INSERT INTO users (name, age) VALUES ('Alice', 42);
            INSERT INTO users (name, age) VALUES ('Bob', 69);
            ",
        )
        .unwrap();
    connection
        .iterate("SELECT * FROM users WHERE age > 50", |pairs| {
            for &(column, value) in pairs.iter() {
                println!("{} = {}", column, value.unwrap());
            }
            true
        })
        .unwrap();
}

DBファイル確認

$ sqlite3 /tmp/work/db.sqlite3 
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
sqlite> select * from sqlite_master;
table|users|users|2|CREATE TABLE users (name TEXT, age INTEGER)
sqlite> .tables
users
sqlite> select * from users;
Alice|42
Bob|69
sqlite> .exit

 ちゃんとDBファイルが作成されていた。成功。

2回目でエラー

 2回目以降の実行で「table users already exists」エラーになる。create文で作ろうとした名前のテーブルはすでに存在するため怒られた。

$ cargo run
...
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { code: Some(1), message: Some("table users already exists") }', src/libcore/result.rs:999:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

テーブル既存確認

select count(*) from sqlite_master where type='table' and name='テーブル名';

 取得した1行目1列目が0なら、テーブル名テーブルは存在しない。1なら存在する。

テーブルが既存なら作らない

fn main() {
    let connection = sqlite3::open("/tmp/work/db.sqlite3").unwrap();

    if let Some(row) = connection.prepare("select count(*) from sqlite_master where type='table' and name='users';").unwrap().cursor().next().unwrap() {
        if 0 == row[0].as_integer().unwrap() {
            connection
                .execute(
                    "
                    CREATE TABLE users (name TEXT, age INTEGER);
                    INSERT INTO users (name, age) VALUES ('Alice', 42);
                    INSERT INTO users (name, age) VALUES ('Bob', 69);
                    ",
                )
                .unwrap();
        }
    }
    connection
        .iterate("SELECT * FROM users WHERE age > 50", |pairs| {
            for &(column, value) in pairs.iter() {
                println!("{} = {}", column, value.unwrap());
            }
            true
        })
        .unwrap();
}

 usersテーブルがないときだけcreate文を発行する。これで2回目以降もエラーなく実行できる。

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux

前回まで