items.rs

 1use anyhow::{Context, Result};
 2use indoc::indoc;
 3use sqlez::migrations::Migration;
 4
 5use crate::{
 6    model::{ItemId, PaneId, SerializedItem, SerializedItemKind, WorkspaceId},
 7    Db,
 8};
 9
10// 1) Move all of this into Workspace crate
11// 2) Deserialize items fully
12// 3) Typed prepares (including how you expect to pull data out)
13// 4) Investigate Tree column impls
14pub(crate) const ITEM_MIGRATIONS: Migration = Migration::new(
15    "item",
16    &[indoc! {"
17        CREATE TABLE items(
18            item_id INTEGER NOT NULL, -- This is the item's view id, so this is not unique
19            workspace_id BLOB NOT NULL,
20            pane_id INTEGER NOT NULL,
21            kind TEXT NOT NULL,
22            position INTEGER NOT NULL,
23            FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id) ON DELETE CASCADE
24            FOREIGN KEY(pane_id) REFERENCES panes(pane_id) ON DELETE CASCADE
25            PRIMARY KEY(item_id, workspace_id)
26        ) STRICT;
27    "}],
28);
29
30impl Db {
31    pub(crate) fn get_items(&self, pane_id: PaneId) -> Result<Vec<SerializedItem>> {
32        Ok(self
33            .prepare(indoc! {"
34                SELECT item_id, kind FROM items
35                WHERE pane_id = ?
36                ORDER BY position"})?
37            .with_bindings(pane_id)?
38            .rows::<(ItemId, SerializedItemKind)>()?
39            .into_iter()
40            .map(|(item_id, kind)| match kind {
41                SerializedItemKind::Terminal => SerializedItem::Terminal { item_id },
42                _ => unimplemented!(),
43            })
44            .collect())
45    }
46
47    pub(crate) fn save_items(
48        &self,
49        workspace_id: &WorkspaceId,
50        pane_id: PaneId,
51        items: &[SerializedItem],
52    ) -> Result<()> {
53        let mut delete_old = self
54            .prepare("DELETE FROM items WHERE workspace_id = ? AND pane_id = ? AND item_id = ?")
55            .context("Preparing deletion")?;
56        let mut insert_new = self.prepare(
57            "INSERT INTO items(item_id, workspace_id, pane_id, kind, position) VALUES (?, ?, ?, ?, ?)",
58        ).context("Preparing insertion")?;
59        for (position, item) in items.iter().enumerate() {
60            delete_old
61                .with_bindings((workspace_id, pane_id, item.item_id()))?
62                .exec()?;
63
64            insert_new
65                .with_bindings((item.item_id(), workspace_id, pane_id, item.kind(), position))?
66                .exec()?;
67        }
68
69        Ok(())
70    }
71}