ChatGPTにあれこれ質問しながらRustでSQLiteのデータベース作ってレコード作成→読み取りまでやってみた
まずは質問してみる
A rusqliteを使って実装する
rusqliteとは
GitHub - rusqlite/rusqlite: Ergonomic bindings to SQLite for Rust
RustでSQLiteへ接続する時のあれこれをやってくれるクレート
ORMではなく単なるドライバ
Cargo.tomlのdependenciesに追加しておこう
[dependencies] rusqlite = { version = "0.29.0" }
サンプルコード
ChatGPTが↓のようなコードを書いてくれた
use rusqlite::{params, Connection}; fn main() -> Result<(), Box<dyn std::error::Error>> { let conn = Connection::open("example.db")?; conn.execute( "CREATE TABLE IF NOT EXISTS person ( id INTEGER PRIMARY KEY, name TEXT NOT NULL, age INTEGER NOT NULL )", [], )?; let name = "Alice"; let age = 42; conn.execute( "INSERT INTO person (name, age) VALUES (?1, ?2)", params![name, age], )?; let mut stmt = conn.prepare("SELECT name, age FROM person WHERE id = 1")?; let person: (String, i32) = stmt.query_row([], |row| Ok((row.get(0)?, row.get(1)?)))?; println!("Found person: {:?}", person); Ok(()) }
わからないところを聞く
↑のコードを読んだときに浮かんだのはdynって何だっけ?mutは再代入禁止?...という初歩的な疑問ばかりで全然読めなかった
なのでRustのドキュメント使って調べる、ではなくAIに質問(脳死)
Q Result<(), Box>のdynって何?
A dynはトレイトオブジェクトを宣言する識別子
トレイトオブジェクトはトレイトを実装したインスタンスを表す
トレイトはインターフェースのようにある構造体で実装すべきメソッド/フィールドを定義する
要するにOOPのポリモーフィズムを実現するための機能で、今回の場合エラーの戻り値にstd:error:Errorと同じメソッドが実装されている何かしらのオブジェクトが来るということを表している(と理解した)
Q 関数の戻り値の後ろについてる"?"の意味は?
A Result型のハンドリングを簡便化するシンタックスシュガー
fn foo() -> Result<i32, String> { let x = bar()?; // bar()がErrを返す場合、foo()はそのErrを返す Ok(x) }
bar()がOKを返す場合は変数xにその値が代入され、Errを返す場合はその場でfoo()もそのErrを返すようになる
Q 引数を|で囲い|row|ってしてるけど何?
A その引数がクロージャとして扱われることを表している
クロージャとは無名関数(jsでいうアロー関数とか)のことであり、クロージャのスコープ内の変数はキャプチャ(そのスコープ内で固定)される
fn main() { let x = 10; let y = 20; let add = || { x + y }; println!("The result is {}", add()); }
例えばこのようなコードだと、変数addにx + yを返す無名関数が代入される
そして、xとyはキャプチャされているのでaddをいつどこで呼び出しても30が返ってくる
サンプルコードでは以下のようにstmt.query_row()の第二引数
でクロージャを使っている
let person: (String, i32) = stmt.query_row([], |row| Ok((row.get(0)?, row.get(1)?)))?;
大分わかりにくい形になっているが、やっていること自体はrow
を引数にとりrow
のインデックス0と1の値(=personテーブルのnameとage)をタプルとして返すだけの関数
実行する
cargo run
で実行してみよう
※環境によっては= note: /usr/bin/ld: cannot find -lsqlite3: No such file or directory
というエラーが発生するかもしれない
これは以下のようにしてsqlite3のライブラリをインストールしてやればOK
sudo apt-get install libsqlite3-dev
実行してみてFound person: ("Alice", 42)
と表示されれば成功
また、SQLiteなのでデータベースがファイル出力される(サンプルコードそのままだとexample.dbという名前)