use anyhow::{Context, Result};
use rusqlite::Connection;
use std::path::Path;
#[derive(Debug)]
pub struct SqliteDatabase {
conn: Connection,
}
impl SqliteDatabase {
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
let conn = Connection::open(path).context("Failed to open SQLite database")?;
Ok(Self { conn })
}
pub fn open_in_memory() -> Result<Self> {
let conn = Connection::open_in_memory().context("Failed to create in-memory database")?;
Ok(Self { conn })
}
pub fn execute(&self, sql: &str, params: &[&dyn rusqlite::ToSql]) -> Result<usize> {
let count = self
.conn
.execute(sql, params)
.with_context(|| format!("Failed to execute: {}", sql))?;
Ok(count)
}
pub fn execute_batch(&self, sql: &str) -> Result<()> {
self.conn
.execute_batch(sql)
.context("Failed to execute batch")?;
Ok(())
}
pub fn backend_name(&self) -> &'static str {
"sqlite"
}
pub fn connection(&self) -> &Connection {
&self.conn
}
pub fn connection_mut(&mut self) -> &mut Connection {
&mut self.conn
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sqlite_database_creation() -> Result<()> {
let db = SqliteDatabase::open_in_memory()?;
assert_eq!(db.backend_name(), "sqlite");
Ok(())
}
#[test]
fn test_basic_operations() -> Result<()> {
let db = SqliteDatabase::open_in_memory()?;
db.execute("CREATE TABLE test (id INTEGER, name TEXT)", &[])?;
let count = db.execute("INSERT INTO test VALUES (?, ?)", &[&1, &"test"])?;
assert_eq!(count, 1);
let name: String =
db.connection()
.query_row("SELECT name FROM test WHERE id = ?", [1], |row| row.get(0))?;
assert_eq!(name, "test");
Ok(())
}
}