sqlite_graphrag/storage/
backend.rs1use rusqlite::Connection;
10
11pub trait StorageBackend {
16 fn execute_sql(
18 &self,
19 sql: &str,
20 params: &[&dyn rusqlite::types::ToSql],
21 ) -> Result<usize, crate::errors::AppError>;
22
23 fn query_one<T, F>(
25 &self,
26 sql: &str,
27 params: &[&dyn rusqlite::types::ToSql],
28 f: F,
29 ) -> Result<Option<T>, crate::errors::AppError>
30 where
31 F: FnOnce(&rusqlite::Row<'_>) -> Result<T, rusqlite::Error>;
32
33 fn as_connection(&self) -> &Connection;
36}
37
38pub struct SqliteBackend {
40 conn: Connection,
41}
42
43impl SqliteBackend {
44 pub fn new(conn: Connection) -> Self {
46 Self { conn }
47 }
48
49 pub fn into_inner(self) -> Connection {
51 self.conn
52 }
53}
54
55impl StorageBackend for SqliteBackend {
56 fn execute_sql(
57 &self,
58 sql: &str,
59 params: &[&dyn rusqlite::types::ToSql],
60 ) -> Result<usize, crate::errors::AppError> {
61 self.conn
62 .execute(sql, params)
63 .map_err(crate::errors::AppError::Database)
64 }
65
66 fn query_one<T, F>(
67 &self,
68 sql: &str,
69 params: &[&dyn rusqlite::types::ToSql],
70 f: F,
71 ) -> Result<Option<T>, crate::errors::AppError>
72 where
73 F: FnOnce(&rusqlite::Row<'_>) -> Result<T, rusqlite::Error>,
74 {
75 match self.conn.query_row(sql, params, f) {
76 Ok(val) => Ok(Some(val)),
77 Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None),
78 Err(e) => Err(crate::errors::AppError::Database(e)),
79 }
80 }
81
82 fn as_connection(&self) -> &Connection {
83 &self.conn
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn sqlite_backend_wraps_connection() {
93 let conn = Connection::open_in_memory().unwrap();
94 conn.execute_batch("CREATE TABLE test (id INTEGER PRIMARY KEY, val TEXT)")
95 .unwrap();
96 let backend = SqliteBackend::new(conn);
97 let affected = backend
98 .execute_sql(
99 "INSERT INTO test (val) VALUES (?1)",
100 &[&"hello" as &dyn rusqlite::types::ToSql],
101 )
102 .unwrap();
103 assert_eq!(affected, 1);
104
105 let result: Option<String> = backend
106 .query_one("SELECT val FROM test WHERE id = 1", &[], |r| r.get(0))
107 .unwrap();
108 assert_eq!(result, Some("hello".to_string()));
109 }
110}