kvp.rs

 1use anyhow::Result;
 2use rusqlite::OptionalExtension;
 3
 4use super::Db;
 5
 6pub(crate) const KVP_M_1: &str = "
 7CREATE TABLE kv_store(
 8    key TEXT PRIMARY KEY,
 9    value TEXT NOT NULL
10) STRICT;
11";
12
13impl Db {
14    pub fn read_kvp(&self, key: &str) -> Result<Option<String>> {
15        let lock = self.connection.lock();
16        let mut stmt = lock.prepare_cached("SELECT value FROM kv_store WHERE key = (?)")?;
17
18        Ok(stmt.query_row([key], |row| row.get(0)).optional()?)
19    }
20
21    pub fn delete_kvp(&self, key: &str) -> Result<()> {
22        let lock = self.connection.lock();
23
24        let mut stmt = lock.prepare_cached("DELETE FROM kv_store WHERE key = (?)")?;
25
26        stmt.execute([key])?;
27
28        Ok(())
29    }
30
31    pub fn write_kvp(&self, key: &str, value: &str) -> Result<()> {
32        let lock = self.connection.lock();
33
34        let mut stmt =
35            lock.prepare_cached("INSERT OR REPLACE INTO kv_store(key, value) VALUES ((?), (?))")?;
36
37        stmt.execute([key, value])?;
38
39        Ok(())
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use anyhow::Result;
46
47    use super::*;
48
49    #[test]
50    fn test_kvp() -> Result<()> {
51        let db = Db::open_in_memory()?;
52
53        assert_eq!(db.read_kvp("key-1")?, None);
54
55        db.write_kvp("key-1", "one")?;
56        assert_eq!(db.read_kvp("key-1")?, Some("one".to_string()));
57
58        db.write_kvp("key-1", "one-2")?;
59        assert_eq!(db.read_kvp("key-1")?, Some("one-2".to_string()));
60
61        db.write_kvp("key-2", "two")?;
62        assert_eq!(db.read_kvp("key-2")?, Some("two".to_string()));
63
64        db.delete_kvp("key-1")?;
65        assert_eq!(db.read_kvp("key-1")?, None);
66
67        Ok(())
68    }
69}