unistore_sqlite/
config.rs1use std::path::PathBuf;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
9pub enum SynchronousMode {
10 Off,
12 #[default]
14 Normal,
15 Full,
17 Extra,
19}
20
21impl SynchronousMode {
22 pub fn as_pragma(&self) -> &'static str {
24 match self {
25 Self::Off => "OFF",
26 Self::Normal => "NORMAL",
27 Self::Full => "FULL",
28 Self::Extra => "EXTRA",
29 }
30 }
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
35pub enum JournalMode {
36 Delete,
38 Truncate,
40 Persist,
42 Memory,
44 #[default]
46 Wal,
47 Off,
49}
50
51impl JournalMode {
52 pub fn as_pragma(&self) -> &'static str {
54 match self {
55 Self::Delete => "DELETE",
56 Self::Truncate => "TRUNCATE",
57 Self::Persist => "PERSIST",
58 Self::Memory => "MEMORY",
59 Self::Wal => "WAL",
60 Self::Off => "OFF",
61 }
62 }
63}
64
65#[derive(Debug, Clone)]
67pub struct SqliteConfig {
68 pub path: Option<PathBuf>,
70
71 pub synchronous: SynchronousMode,
73
74 pub journal_mode: JournalMode,
76
77 pub foreign_keys: bool,
79
80 pub busy_timeout_ms: u32,
82
83 pub cache_size: i32,
85
86 pub page_size: u32,
88
89 pub read_only: bool,
91
92 pub create_if_missing: bool,
94}
95
96impl Default for SqliteConfig {
97 fn default() -> Self {
98 Self {
99 path: None,
100 synchronous: SynchronousMode::Normal,
101 journal_mode: JournalMode::Wal,
102 foreign_keys: true,
103 busy_timeout_ms: 5000,
104 cache_size: -2000, page_size: 4096,
106 read_only: false,
107 create_if_missing: true,
108 }
109 }
110}
111
112impl SqliteConfig {
113 pub fn memory() -> Self {
115 Self {
116 path: None,
117 journal_mode: JournalMode::Memory,
118 ..Default::default()
119 }
120 }
121
122 pub fn file(path: impl Into<PathBuf>) -> Self {
124 Self {
125 path: Some(path.into()),
126 ..Default::default()
127 }
128 }
129
130 pub fn performance() -> Self {
136 Self {
137 synchronous: SynchronousMode::Off,
138 journal_mode: JournalMode::Wal,
139 cache_size: -10000, ..Default::default()
141 }
142 }
143
144 pub fn durable() -> Self {
149 Self {
150 synchronous: SynchronousMode::Full,
151 journal_mode: JournalMode::Wal,
152 foreign_keys: true,
153 ..Default::default()
154 }
155 }
156
157 pub fn with_path(mut self, path: impl Into<PathBuf>) -> Self {
159 self.path = Some(path.into());
160 self
161 }
162
163 pub fn with_synchronous(mut self, mode: SynchronousMode) -> Self {
165 self.synchronous = mode;
166 self
167 }
168
169 pub fn with_journal_mode(mut self, mode: JournalMode) -> Self {
171 self.journal_mode = mode;
172 self
173 }
174
175 pub fn with_foreign_keys(mut self, enabled: bool) -> Self {
177 self.foreign_keys = enabled;
178 self
179 }
180
181 pub fn with_busy_timeout(mut self, ms: u32) -> Self {
183 self.busy_timeout_ms = ms;
184 self
185 }
186
187 pub fn with_read_only(mut self, read_only: bool) -> Self {
189 self.read_only = read_only;
190 self
191 }
192
193 pub fn to_pragmas(&self) -> Vec<String> {
195 let mut pragmas = Vec::new();
196
197 pragmas.push(format!("PRAGMA page_size = {};", self.page_size));
199
200 pragmas.push(format!("PRAGMA journal_mode = {};", self.journal_mode.as_pragma()));
202
203 pragmas.push(format!("PRAGMA synchronous = {};", self.synchronous.as_pragma()));
205
206 pragmas.push(format!(
208 "PRAGMA foreign_keys = {};",
209 if self.foreign_keys { "ON" } else { "OFF" }
210 ));
211
212 pragmas.push(format!("PRAGMA busy_timeout = {};", self.busy_timeout_ms));
214
215 pragmas.push(format!("PRAGMA cache_size = {};", self.cache_size));
217
218 pragmas
219 }
220
221 pub fn path_string(&self) -> String {
223 match &self.path {
224 Some(p) => p.to_string_lossy().to_string(),
225 None => ":memory:".to_string(),
226 }
227 }
228
229 pub fn is_memory(&self) -> bool {
231 self.path.is_none()
232 }
233}
234
235#[cfg(test)]
236mod tests {
237 use super::*;
238
239 #[test]
240 fn test_memory_config() {
241 let config = SqliteConfig::memory();
242 assert!(config.is_memory());
243 assert_eq!(config.path_string(), ":memory:");
244 }
245
246 #[test]
247 fn test_file_config() {
248 let config = SqliteConfig::file("/tmp/test.db");
249 assert!(!config.is_memory());
250 assert!(config.path_string().contains("test.db"));
251 }
252
253 #[test]
254 fn test_pragmas() {
255 let config = SqliteConfig::default();
256 let pragmas = config.to_pragmas();
257 assert!(pragmas.iter().any(|p| p.contains("journal_mode")));
258 assert!(pragmas.iter().any(|p| p.contains("synchronous")));
259 assert!(pragmas.iter().any(|p| p.contains("foreign_keys")));
260 }
261
262 #[test]
263 fn test_presets() {
264 let perf = SqliteConfig::performance();
265 assert_eq!(perf.synchronous, SynchronousMode::Off);
266
267 let durable = SqliteConfig::durable();
268 assert_eq!(durable.synchronous, SynchronousMode::Full);
269 }
270}