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_IN_MEMORY_INIT_PRAGMAS, DB_IN_MEMORY_PRAGMAS, 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(Some(&path))?
26 },
27 None => Self::init_db(None)?,
28 };
29 Ok(SqliteEngine { connection })
30 }
31
32 pub fn init_db(db_path: Option<&PathBuf>) -> rusqlite::Result<Connection> {
33 let connection = if let Some(path) = db_path {
34 if let Some(parent) = path.parent() {
35 let _ = std::fs::create_dir_all(parent);
36 }
37 let conn = Connection::open(path)?;
38 for pragma in DB_INIT_PRAGMAS.iter() {
39 let _ = conn.execute(pragma, []);
40 }
41 for pragma in DB_PRAGMAS.iter() {
42 let _ = conn.execute(pragma, []);
43 }
44 conn
45 } else {
46 let conn = Connection::open_in_memory()?;
50 for pragma in DB_IN_MEMORY_INIT_PRAGMAS.iter() {
51 let _ = conn.execute(pragma, []);
52 }
53 for pragma in DB_IN_MEMORY_PRAGMAS.iter() {
54 let _ = conn.execute(pragma, []);
55 }
56 conn
57 };
58 connection.execute("CREATE TABLE IF NOT EXISTS data (id INTEGER PRIMARY KEY AUTOINCREMENT, key TEXT, value TEXT);", [])?;
59 Ok(connection)
60 }
61}
62
63impl WebStorageEngine for SqliteEngine {
64 type Error = rusqlite::Error;
65
66 fn load(&self) -> Result<OriginEntry, Self::Error> {
67 let mut stmt = self.connection.prepare("SELECT key, value FROM data;")?;
68 let rows = stmt.query_map([], |row| {
69 let key: String = row.get(0)?;
70 let value: String = row.get(1)?;
71 Ok((key, value))
72 })?;
73
74 let mut map = OriginEntry::default();
75 for row in rows {
76 let (key, value) = row?;
77 map.insert(key, value);
78 }
79 Ok(map)
80 }
81
82 fn clear(&mut self) -> Result<(), Self::Error> {
83 self.connection.execute("DELETE FROM data;", [])?;
84 Ok(())
85 }
86
87 fn delete(&mut self, key: &str) -> Result<(), Self::Error> {
88 self.connection
89 .execute("DELETE FROM data WHERE key = ?;", [key])?;
90 Ok(())
91 }
92
93 fn set(&mut self, key: &str, value: &str) -> Result<(), Self::Error> {
94 let tx = self.connection.transaction()?;
99 let rows = tx.execute("UPDATE data SET value = ? WHERE key = ?", [value, key])?;
100 if rows == 0 {
101 tx.execute("INSERT INTO data (key, value) VALUES (?, ?)", [key, value])?;
102 }
103 tx.commit()?;
104 Ok(())
105 }
106
107 fn save(&mut self, data: &OriginEntry) {
108 fn save_inner(conn: &mut Connection, data: &OriginEntry) -> rusqlite::Result<()> {
109 let tx = conn.transaction()?;
110 tx.execute("DELETE FROM data;", [])?;
111 let mut stmt = tx.prepare("INSERT INTO data (key, value) VALUES (?, ?);")?;
112 for (key, value) in data.inner() {
113 stmt.execute(rusqlite::params![key, value])?;
114 }
115 drop(stmt);
116 tx.commit()?;
117 Ok(())
118 }
119 if let Err(e) = save_inner(&mut self.connection, data) {
120 error!("localstorage save error: {:?}", e);
121 }
122 }
123}