storage/webstorage/engines/
sqlite.rs1use std::path::PathBuf;
6use std::sync::Arc;
7
8use base::threadpool::ThreadPool;
9use log::error;
10use rusqlite::Connection;
11
12use crate::shared::{DB_INIT_PRAGMAS, DB_PRAGMAS};
13use crate::webstorage::OriginEntry;
14use crate::webstorage::engines::WebStorageEngine;
15
16pub struct SqliteEngine {
17 connection: Connection,
18}
19
20impl SqliteEngine {
21 pub fn new(db_dir: &Option<PathBuf>, _pool: Arc<ThreadPool>) -> rusqlite::Result<Self> {
22 let connection = match db_dir {
23 Some(path) => {
24 let path = path.join("webstorage.sqlite");
25 Self::init_db(&path)?
26 },
27 None => Connection::open_in_memory()?,
28 };
29 for pragma in DB_PRAGMAS.iter() {
31 let _ = connection.execute(pragma, []);
32 }
33 Ok(SqliteEngine { connection })
34 }
35
36 pub fn init_db(path: &PathBuf) -> rusqlite::Result<Connection> {
37 if let Some(parent) = path.parent() {
38 let _ = std::fs::create_dir_all(parent);
39 }
40 let connection = Connection::open(path)?;
41 for pragma in DB_INIT_PRAGMAS.iter() {
42 let _ = connection.execute(pragma, []);
43 }
44 connection.execute("CREATE TABLE IF NOT EXISTS data (id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT, value TEXT);", [])?;
45 Ok(connection)
46 }
47}
48
49impl WebStorageEngine for SqliteEngine {
50 type Error = rusqlite::Error;
51
52 fn load(&self) -> Result<OriginEntry, Self::Error> {
53 let mut stmt = self.connection.prepare("SELECT key, value FROM data;")?;
54 let rows = stmt.query_map([], |row| {
55 let key: String = row.get(0)?;
56 let value: String = row.get(1)?;
57 Ok((key, value))
58 })?;
59
60 let mut map = OriginEntry::default();
61 for row in rows {
62 let (key, value) = row?;
63 map.insert(key, value);
64 }
65 Ok(map)
66 }
67
68 fn clear(&mut self) -> Result<(), Self::Error> {
69 self.connection.execute("DELETE FROM data;", [])?;
70 Ok(())
71 }
72
73 fn delete(&mut self, key: &str) -> Result<(), Self::Error> {
74 self.connection
75 .execute("DELETE FROM data WHERE key = ?;", [key])?;
76 Ok(())
77 }
78
79 fn set(&mut self, key: &str, value: &str) -> Result<(), Self::Error> {
80 self.connection.execute(
82 "INSERT INTO data (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value=excluded.value;",
83 [key, value],
84 )?;
85 Ok(())
86 }
87
88 fn save(&mut self, data: &OriginEntry) {
89 fn save_inner(conn: &mut Connection, data: &OriginEntry) -> rusqlite::Result<()> {
90 let tx = conn.transaction()?;
91 tx.execute("DELETE FROM data;", [])?;
92 let mut stmt = tx.prepare("INSERT INTO data (key, value) VALUES (?, ?);")?;
93 for (key, value) in data.inner() {
94 stmt.execute(rusqlite::params![key, value])?;
95 }
96 drop(stmt);
97 tx.commit()?;
98 Ok(())
99 }
100 if let Err(e) = save_inner(&mut self.connection, data) {
101 error!("localstorage save error: {:?}", e);
102 }
103 }
104}