db.rs

 1pub mod items;
 2pub mod kvp;
 3mod migrations;
 4pub mod pane;
 5pub mod workspace;
 6
 7use std::fs;
 8use std::ops::Deref;
 9use std::path::Path;
10
11use anyhow::Result;
12use indoc::indoc;
13use kvp::KVP_MIGRATION;
14use pane::PANE_MIGRATIONS;
15use sqlez::connection::Connection;
16use sqlez::thread_safe_connection::ThreadSafeConnection;
17
18pub use workspace::*;
19
20#[derive(Clone)]
21struct Db(ThreadSafeConnection);
22
23impl Deref for Db {
24    type Target = sqlez::connection::Connection;
25
26    fn deref(&self) -> &Self::Target {
27        &self.0.deref()
28    }
29}
30
31impl Db {
32    /// Open or create a database at the given directory path.
33    pub fn open(db_dir: &Path, channel: &'static str) -> Self {
34        // Use 0 for now. Will implement incrementing and clearing of old db files soon TM
35        let current_db_dir = db_dir.join(Path::new(&format!("0-{}", channel)));
36        fs::create_dir_all(&current_db_dir)
37            .expect("Should be able to create the database directory");
38        let db_path = current_db_dir.join(Path::new("db.sqlite"));
39
40        Db(
41            ThreadSafeConnection::new(db_path.to_string_lossy().as_ref(), true)
42                .with_initialize_query(indoc! {"
43                    PRAGMA journal_mode=WAL;
44                    PRAGMA synchronous=NORMAL;
45                    PRAGMA foreign_keys=TRUE;
46                    PRAGMA case_sensitive_like=TRUE;
47                "})
48                .with_migrations(&[KVP_MIGRATION, WORKSPACES_MIGRATION, PANE_MIGRATIONS]),
49        )
50    }
51
52    pub fn persisting(&self) -> bool {
53        self.persistent()
54    }
55
56    /// Open a in memory database for testing and as a fallback.
57    pub fn open_in_memory() -> Self {
58        Db(
59            ThreadSafeConnection::new("Zed DB", false).with_initialize_query(indoc! {"
60                    PRAGMA journal_mode=WAL;
61                    PRAGMA synchronous=NORMAL;
62                    PRAGMA foreign_keys=TRUE;
63                    PRAGMA case_sensitive_like=TRUE;
64                    "}),
65        )
66    }
67
68    pub fn write_to<P: AsRef<Path>>(&self, dest: P) -> Result<()> {
69        let destination = Connection::open_file(dest.as_ref().to_string_lossy().as_ref());
70        self.backup_main(&destination)
71    }
72}
73
74impl Drop for Db {
75    fn drop(&mut self) {
76        self.exec(indoc! {"
77            PRAGMA analysis_limit=500;
78            PRAGMA optimize"})
79            .ok();
80    }
81}