1use anyhow::Result;
2use std::path::PathBuf;
3
4use db::{define_connection, query, sqlez::statement::Statement, sqlez_macros::sql};
5use workspace::{ItemId, WorkspaceDb, WorkspaceId};
6
7define_connection! {
8 pub static ref TERMINAL_DB: TerminalDb<WorkspaceDb> =
9 &[sql!(
10 CREATE TABLE terminals (
11 workspace_id INTEGER,
12 item_id INTEGER UNIQUE,
13 working_directory BLOB,
14 PRIMARY KEY(workspace_id, item_id),
15 FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id)
16 ON DELETE CASCADE
17 ) STRICT;
18 ),
19 // Remove the unique constraint on the item_id table
20 // SQLite doesn't have a way of doing this automatically, so
21 // we have to do this silly copying.
22 sql!(
23 CREATE TABLE terminals2 (
24 workspace_id INTEGER,
25 item_id INTEGER,
26 working_directory BLOB,
27 PRIMARY KEY(workspace_id, item_id),
28 FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id)
29 ON DELETE CASCADE
30 ) STRICT;
31
32 INSERT INTO terminals2 (workspace_id, item_id, working_directory)
33 SELECT workspace_id, item_id, working_directory FROM terminals;
34
35 DROP TABLE terminals;
36
37 ALTER TABLE terminals2 RENAME TO terminals;
38 )];
39}
40
41impl TerminalDb {
42 query! {
43 pub async fn update_workspace_id(
44 new_id: WorkspaceId,
45 old_id: WorkspaceId,
46 item_id: ItemId
47 ) -> Result<()> {
48 UPDATE terminals
49 SET workspace_id = ?
50 WHERE workspace_id = ? AND item_id = ?
51 }
52 }
53
54 query! {
55 pub async fn save_working_directory(
56 item_id: ItemId,
57 workspace_id: WorkspaceId,
58 working_directory: PathBuf
59 ) -> Result<()> {
60 INSERT OR REPLACE INTO terminals(item_id, workspace_id, working_directory)
61 VALUES (?, ?, ?)
62 }
63 }
64
65 query! {
66 pub fn get_working_directory(item_id: ItemId, workspace_id: WorkspaceId) -> Result<Option<PathBuf>> {
67 SELECT working_directory
68 FROM terminals
69 WHERE item_id = ? AND workspace_id = ?
70 }
71 }
72
73 pub async fn delete_unloaded_items(
74 &self,
75 workspace: WorkspaceId,
76 alive_items: Vec<ItemId>,
77 ) -> Result<()> {
78 let placeholders = alive_items
79 .iter()
80 .map(|_| "?")
81 .collect::<Vec<&str>>()
82 .join(", ");
83
84 let query = format!(
85 "DELETE FROM terminals WHERE workspace_id = ? AND item_id NOT IN ({placeholders})"
86 );
87
88 self.write(move |conn| {
89 let mut statement = Statement::prepare(conn, query)?;
90 let mut next_index = statement.bind(&workspace, 1)?;
91 for id in alive_items {
92 next_index = statement.bind(&id, next_index)?;
93 }
94 statement.exec()
95 })
96 .await
97 }
98}