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}