use anyhow::Result; use std::path::PathBuf; use db::{define_connection, query, sqlez::statement::Statement, sqlez_macros::sql}; use workspace::{ItemId, WorkspaceDb, WorkspaceId}; define_connection! { pub static ref TERMINAL_DB: TerminalDb = &[sql!( CREATE TABLE terminals ( workspace_id INTEGER, item_id INTEGER UNIQUE, working_directory BLOB, PRIMARY KEY(workspace_id, item_id), FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id) ON DELETE CASCADE ) STRICT; ), // Remove the unique constraint on the item_id table // SQLite doesn't have a way of doing this automatically, so // we have to do this silly copying. sql!( CREATE TABLE terminals2 ( workspace_id INTEGER, item_id INTEGER, working_directory BLOB, PRIMARY KEY(workspace_id, item_id), FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id) ON DELETE CASCADE ) STRICT; INSERT INTO terminals2 (workspace_id, item_id, working_directory) SELECT workspace_id, item_id, working_directory FROM terminals; DROP TABLE terminals; ALTER TABLE terminals2 RENAME TO terminals; )]; } impl TerminalDb { query! { pub async fn update_workspace_id( new_id: WorkspaceId, old_id: WorkspaceId, item_id: ItemId ) -> Result<()> { UPDATE terminals SET workspace_id = ? WHERE workspace_id = ? AND item_id = ? } } query! { pub async fn save_working_directory( item_id: ItemId, workspace_id: WorkspaceId, working_directory: PathBuf ) -> Result<()> { INSERT OR REPLACE INTO terminals(item_id, workspace_id, working_directory) VALUES (?, ?, ?) } } query! { pub fn get_working_directory(item_id: ItemId, workspace_id: WorkspaceId) -> Result> { SELECT working_directory FROM terminals WHERE item_id = ? AND workspace_id = ? } } pub async fn delete_unloaded_items( &self, workspace: WorkspaceId, alive_items: Vec, ) -> Result<()> { let placeholders = alive_items .iter() .map(|_| "?") .collect::>() .join(", "); let query = format!( "DELETE FROM terminals WHERE workspace_id = ? AND item_id NOT IN ({placeholders})" ); self.write(move |conn| { let mut statement = Statement::prepare(conn, query)?; let mut next_index = statement.bind(&workspace, 1)?; for id in alive_items { next_index = statement.bind(&id, next_index)?; } statement.exec() }) .await } }