use core::ops::Bound; use std::cell::Cell; use std::sync::{Arc, Mutex, RwLock, MutexGuard}; use ouroboros::self_referencing; use rusqlite::{params, Connection, Transaction}; use crate::{ Db, Error, Exporter, IDb, ITx, ITxFn, Result, TxError, TxFnResult, TxResult, Value, ValueIter, }; pub use rusqlite; impl From for Error { fn from(e: rusqlite::Error) -> Error { Error(format!("{}", e).into()) } } impl From for TxError { fn from(e: rusqlite::Error) -> TxError { TxError::Db(e.into()) } } pub struct SqliteDb { db: Mutex, trees: RwLock>, } impl SqliteDb { pub fn new(db: rusqlite::Connection) -> Db { let s = Self { db: Mutex::new(db), trees: RwLock::new(Vec::new()), }; Db(Arc::new(s)) } fn get_tree(&self, i: usize) -> Result { self.trees .read() .unwrap() .get(i) .cloned() .ok_or(Error("invalid tree id".into())) } } impl IDb for SqliteDb { fn open_tree(&self, name: &str) -> Result { let mut trees = self.trees.write().unwrap(); if let Some(i) = trees.iter().position(|x| x == name) { Ok(i) } else { self.db.lock().unwrap().execute( &format!( "CREATE TABLE IF NOT EXISTS {} ( k BLOB PRIMARY KEY, v BLOB )", name ), [], )?; let i = trees.len(); trees.push(name.to_string()); Ok(i) } } // ---- fn get<'a>(&'a self, tree: usize, key: &[u8]) -> Result>> { let tree = self.get_tree(tree)?; let db = self.db.lock().unwrap(); let mut stmt = db.prepare(&format!("SELECT v FROM {} WHERE k = ?1", tree))?; let mut res_iter = stmt.query([key])?; match res_iter.next()? { None => Ok(None), Some(v) => Ok(Some(v.get::<_, Vec>(0)?.into())), } } fn remove(&self, tree: usize, key: &[u8]) -> Result { let tree = self.get_tree(tree)?; let db = self.db.lock().unwrap(); let res = db.execute(&format!("DELETE FROM {} WHERE k = ?1", tree), params![key])?; Ok(res > 0) } fn len(&self, tree: usize) -> Result { let tree = self.get_tree(tree)?; let db = self.db.lock().unwrap(); let mut stmt = db.prepare(&format!("SELECT COUNT(*) FROM {}", tree))?; let mut res_iter = stmt.query([])?; match res_iter.next()? { None => Ok(0), Some(v) => Ok(v.get::<_, usize>(0)?.into()), } } fn insert(&self, tree: usize, key: &[u8], value: &[u8]) -> Result<()> { let tree = self.get_tree(tree)?; let db = self.db.lock().unwrap(); db.execute( &format!("INSERT OR REPLACE INTO {} (k, v) VALUES (?1, ?2)", tree), params![key, value], )?; Ok(()) } fn iter<'a>(&'a self, tree: usize) -> Result> { let tree = self.get_tree(tree)?; let db = self.db.lock().unwrap(); let sql = format!("SELECT k, v FROM {} ORDER BY k ASC", tree); let mut stmt = db.prepare(&sql)?; let res = stmt.query([])?; unimplemented!(); } fn iter_rev<'a>(&'a self, tree: usize) -> Result> { let tree = self.get_tree(tree)?; unimplemented!(); } fn range<'a, 'r>( &'a self, tree: usize, low: Bound<&'r [u8]>, high: Bound<&'r [u8]>, ) -> Result> { let tree = self.get_tree(tree)?; unimplemented!(); } fn range_rev<'a, 'r>( &'a self, tree: usize, low: Bound<&'r [u8]>, high: Bound<&'r [u8]>, ) -> Result> { let tree = self.get_tree(tree)?; unimplemented!(); } // ---- fn transaction(&self, f: &dyn ITxFn) -> TxResult<(), ()> { let trees = self.trees.read().unwrap(); let mut db = self.db.lock().unwrap(); let tx = SqliteTx { tx: db.transaction()?, trees: trees.as_ref(), }; match f.try_on(&tx) { TxFnResult::Ok => { tx.tx.commit()?; Ok(()) } TxFnResult::Abort => { tx.tx.rollback()?; Err(TxError::Abort(())) } TxFnResult::DbErr => { tx.tx.rollback()?; Err(TxError::Db(Error( "(this message will be discarded)".into(), ))) } } } // ---- fn export<'a>(&'a self) -> Result> { unimplemented!() } fn import<'a>(&self, ex: Exporter<'a>) -> Result<()> { unimplemented!() } // ---- } // ---- struct SqliteTx<'a> { tx: Transaction<'a>, trees: &'a [String], } impl<'a> SqliteTx<'a> { fn get_tree(&self, i: usize) -> Result { self.trees.get(i).cloned().ok_or(Error( "invalid tree id (it might have been openned after the transaction started)".into(), )) } } impl<'a> ITx<'a> for SqliteTx<'a> { fn get(&self, tree: usize, key: &[u8]) -> Result>> { let tree = self.get_tree(tree)?; let mut stmt = self .tx .prepare(&format!("SELECT v FROM {} WHERE k = ?1", tree))?; let mut res_iter = stmt.query([key])?; match res_iter.next()? { None => Ok(None), Some(v) => Ok(Some(v.get::<_, Vec>(0)?.into())), } } fn len(&self, tree: usize) -> Result { let tree = self.get_tree(tree)?; let mut stmt = self.tx.prepare(&format!("SELECT COUNT(*) FROM {}", tree))?; let mut res_iter = stmt.query([])?; match res_iter.next()? { None => Ok(0), Some(v) => Ok(v.get::<_, usize>(0)?.into()), } } fn insert(&self, tree: usize, key: &[u8], value: &[u8]) -> Result<()> { let tree = self.get_tree(tree)?; self.tx.execute( &format!("INSERT OR REPLACE INTO {} (k, v) VALUES (?1, ?2)", tree), params![key, value], )?; Ok(()) } fn remove(&self, tree: usize, key: &[u8]) -> Result { let tree = self.get_tree(tree)?; let res = self .tx .execute(&format!("DELETE FROM {} WHERE k = ?1", tree), params![key])?; Ok(res > 0) } fn iter(&self, _tree: usize) -> Result> { unimplemented!(); } fn iter_rev(&self, _tree: usize) -> Result> { unimplemented!(); } fn range<'r>( &self, _tree: usize, _low: Bound<&'r [u8]>, _high: Bound<&'r [u8]>, ) -> Result> { unimplemented!(); } fn range_rev<'r>( &self, _tree: usize, _low: Bound<&'r [u8]>, _high: Bound<&'r [u8]>, ) -> Result> { unimplemented!(); } }