1use rusqlite::{Connection, OptionalExtension, params};
2
3pub const SETTINGS_TABLE_SQL: &str =
4 "CREATE TABLE IF NOT EXISTS settings (key TEXT PRIMARY KEY, value TEXT NOT NULL);";
5
6pub fn get(connection: &Connection, key: &str) -> rusqlite::Result<Option<String>> {
7 connection
8 .query_row(
9 "SELECT value FROM settings WHERE key = ?1",
10 params![key],
11 |row| row.get(0),
12 )
13 .optional()
14}
15
16pub fn set(connection: &Connection, key: &str, value: &str) -> rusqlite::Result<()> {
17 connection.execute(
18 "INSERT INTO settings(key, value) VALUES (?1, ?2)
19 ON CONFLICT(key) DO UPDATE SET value = excluded.value",
20 params![key, value],
21 )?;
22 Ok(())
23}
24
25pub fn clear(connection: &Connection, key: &str) -> rusqlite::Result<()> {
26 connection.execute("DELETE FROM settings WHERE key = ?1", params![key])?;
27 Ok(())
28}
29
30#[cfg(test)]
31mod tests {
32 use super::*;
33
34 #[test]
35 fn get_set_and_clear_share_one_table_contract() {
36 let connection = Connection::open_in_memory().unwrap();
37 connection.execute_batch(SETTINGS_TABLE_SQL).unwrap();
38 assert_eq!(get(&connection, "desk").unwrap(), None);
39 set(&connection, "desk", "paper").unwrap();
40 assert_eq!(get(&connection, "desk").unwrap().as_deref(), Some("paper"));
41 clear(&connection, "desk").unwrap();
42 assert_eq!(get(&connection, "desk").unwrap(), None);
43 }
44}