use sqlite::{Connection, State};
pub trait FromSqliteRow {
fn from_row(row: &sqlite::Row) -> Self;
}
pub struct SqliteClient {
conn: Connection,
}
impl SqliteClient {
pub fn new(db_path: &str) -> Result<Self, sqlite::Error> {
let conn = Connection::open(db_path)?;
Ok(SqliteClient { conn })
}
pub fn execute(&self, sql: &str) -> Result<(), sqlite::Error> {
let mut stmt = self.conn.prepare(sql)?;
match stmt.next()? {
State::Done => Ok(()),
_ => Err(sqlite::Error {
code: None,
message: Some("ExecuteReturnedResults, please use query...".to_string()),
}),
}
}
pub fn query<T: FromSqliteRow>(&self, sql: &str) -> Vec<T> {
let stmt = self.conn.prepare(sql).unwrap();
let mut results = Vec::new();
for row in stmt.into_iter().map(|row| row.unwrap()) {
results.push(T::from_row(&row));
}
results
}
}
#[cfg(test)]
mod tests {
use from_sqlite_row_macro::FromSqliteRow;
use super::*;
#[derive(Debug, FromSqliteRow)]
struct User {
id: i64, name: String,
}
#[test]
fn it_works() {
let util = SqliteClient::new("docs/test.db").expect("Failed to create SqliteUtil");
let user_results = util.query::<User>("SELECT id, name FROM users");
println!("User results: {:?}", user_results);
for item in user_results {
println!("id = {}, name = {}", item.id, item.name);
}
}
}