executor_sqlite.rs (2800B)
1 use crate::sqlite_util; 2 use crate::{ExecOutcome, SqlExecutor, error::SqlError}; 3 use rusqlite::{Connection, params_from_iter}; 4 use serde_json::Value; 5 use std::path::Path; 6 use std::sync::{Arc, Mutex}; 7 8 pub struct SqliteExecutor { 9 conn: Arc<Mutex<Connection>>, 10 } 11 12 impl SqliteExecutor { 13 pub fn open<P: AsRef<Path>>(path: P) -> Result<Self, SqlError> { 14 let conn = Connection::open(path).map_err(SqlError::from)?; 15 Ok(Self { 16 conn: Arc::new(Mutex::new(conn)), 17 }) 18 } 19 20 pub fn open_memory() -> Result<Self, SqlError> { 21 let conn = Connection::open_in_memory().map_err(SqlError::from)?; 22 Ok(Self { 23 conn: Arc::new(Mutex::new(conn)), 24 }) 25 } 26 } 27 28 impl SqlExecutor for SqliteExecutor { 29 fn exec(&self, sql: &str, params_json: &str) -> Result<ExecOutcome, SqlError> { 30 let binds = sqlite_util::parse_params(params_json)?; 31 let conn = self.conn.lock().map_err(|_| SqlError::Internal)?; 32 if binds.is_empty() { 33 let total_changes_before = conn.total_changes(); 34 conn.execute_batch(sql).map_err(SqlError::from)?; 35 let total_changes_after = conn.total_changes(); 36 let last_insert_id = conn.last_insert_rowid(); 37 return Ok(ExecOutcome { 38 changes: (total_changes_after - total_changes_before) as i64, 39 last_insert_id, 40 }); 41 } 42 let n = conn 43 .execute(sql, params_from_iter(binds)) 44 .map_err(SqlError::from)?; 45 let last_insert_id = conn.last_insert_rowid(); 46 Ok(ExecOutcome { 47 changes: n as i64, 48 last_insert_id, 49 }) 50 } 51 52 fn query_raw(&self, sql: &str, params_json: &str) -> Result<String, SqlError> { 53 let binds = sqlite_util::parse_params(params_json)?; 54 let rows = { 55 let conn = self.conn.lock().map_err(|_| SqlError::Internal)?; 56 let mut stmt = conn.prepare(sql).map_err(SqlError::from)?; 57 let mapped = stmt.query_map(params_from_iter(binds), sqlite_util::row_to_json)?; 58 mapped.collect::<Result<Vec<_>, _>>()? 59 }; 60 Ok(Value::from(rows).to_string()) 61 } 62 63 fn begin(&self) -> Result<(), SqlError> { 64 let conn = self.conn.lock().map_err(|_| SqlError::Internal)?; 65 conn.execute("BEGIN", []).map_err(SqlError::from)?; 66 Ok(()) 67 } 68 69 fn commit(&self) -> Result<(), SqlError> { 70 let conn = self.conn.lock().map_err(|_| SqlError::Internal)?; 71 conn.execute("COMMIT", []).map_err(SqlError::from)?; 72 Ok(()) 73 } 74 75 fn rollback(&self) -> Result<(), SqlError> { 76 let conn = self.conn.lock().map_err(|_| SqlError::Internal)?; 77 conn.execute("ROLLBACK", []).map_err(SqlError::from)?; 78 Ok(()) 79 } 80 }