Skip to main content

eventuary_sqlite/
database.rs

1use std::path::Path;
2use std::sync::{Arc, Mutex};
3
4use rusqlite::Connection;
5
6use eventuary_core::{Error, Result};
7
8pub type SqliteConn = Arc<Mutex<Connection>>;
9
10#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
11pub struct SqliteDatabaseConfig;
12
13pub struct SqliteDatabase {
14    conn: SqliteConn,
15    config: SqliteDatabaseConfig,
16}
17
18impl SqliteDatabase {
19    pub fn open(path: impl AsRef<Path>) -> Result<Self> {
20        let conn = Connection::open(path).map_err(|e| Error::Store(e.to_string()))?;
21        Self::init(conn, SqliteDatabaseConfig)
22    }
23
24    pub fn open_in_memory() -> Result<Self> {
25        let conn = Connection::open_in_memory().map_err(|e| Error::Store(e.to_string()))?;
26        Self::init(conn, SqliteDatabaseConfig)
27    }
28
29    pub fn open_with_config(path: impl AsRef<Path>, config: SqliteDatabaseConfig) -> Result<Self> {
30        let conn = Connection::open(path).map_err(|e| Error::Store(e.to_string()))?;
31        Self::init(conn, config)
32    }
33
34    pub fn open_in_memory_with_config(config: SqliteDatabaseConfig) -> Result<Self> {
35        let conn = Connection::open_in_memory().map_err(|e| Error::Store(e.to_string()))?;
36        Self::init(conn, config)
37    }
38
39    fn init(conn: Connection, config: SqliteDatabaseConfig) -> Result<Self> {
40        let _: String = conn
41            .pragma_update_and_check(None, "journal_mode", "WAL", |row| row.get(0))
42            .map_err(|e| Error::Store(e.to_string()))?;
43
44        Ok(Self {
45            conn: Arc::new(Mutex::new(conn)),
46            config,
47        })
48    }
49
50    pub fn conn(&self) -> SqliteConn {
51        Arc::clone(&self.conn)
52    }
53
54    pub fn config(&self) -> &SqliteDatabaseConfig {
55        &self.config
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[test]
64    fn default_config_is_empty_database_config() {
65        let default_config: SqliteDatabaseConfig = Default::default();
66        assert_eq!(default_config, SqliteDatabaseConfig);
67    }
68
69    #[test]
70    fn open_in_memory_creates_no_component_tables() {
71        let db = SqliteDatabase::open_in_memory().unwrap();
72        let conn = db.conn();
73        let guard = conn.lock().unwrap();
74        let count: i64 = guard
75            .query_row(
76                "SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'",
77                [],
78                |row| row.get(0),
79            )
80            .unwrap();
81        assert_eq!(count, 0);
82    }
83}