Abandoning rusqlite, the API is miserable

Mikayla Maki created

Change summary

crates/db/examples/serialize-pane.rs | 42 +++++++++--------
crates/db/src/pane.rs                | 71 +++++++++++++++++++++++++++--
crates/db/src/workspace.rs           |  6 ++
crates/db/test.db                    |  0 
4 files changed, 94 insertions(+), 25 deletions(-)

Detailed changes

crates/db/examples/serialize-pane.rs 🔗

@@ -19,26 +19,30 @@ fn main() -> anyhow::Result<()> {
     let workspace_1 = db.workspace_for_roots(&["/tmp"]);
     let workspace_2 = db.workspace_for_roots(&["/tmp", "/tmp2"]);
     let workspace_3 = db.workspace_for_roots(&["/tmp3", "/tmp2"]);
-    dbg!(&workspace_1, &workspace_2, &workspace_3);
-    db.write_to(file).ok();
 
-    db.save_dock_pane(&SerializedDockPane {
-        workspace_id: workspace_1.workspace_id,
-        anchor_position: DockAnchor::Expanded,
-        visible: true,
-    });
-    db.save_dock_pane(&SerializedDockPane {
-        workspace_id: workspace_2.workspace_id,
-        anchor_position: DockAnchor::Bottom,
-        visible: true,
-    });
-    db.save_dock_pane(&SerializedDockPane {
-        workspace_id: workspace_3.workspace_id,
-        anchor_position: DockAnchor::Right,
-        visible: false,
-    });
-
-    // db.write_to(file).ok();
+    db.save_dock_pane(
+        workspace_1.workspace_id,
+        &SerializedDockPane {
+            anchor_position: DockAnchor::Expanded,
+            visible: true,
+        },
+    );
+    db.save_dock_pane(
+        workspace_2.workspace_id,
+        &SerializedDockPane {
+            anchor_position: DockAnchor::Bottom,
+            visible: true,
+        },
+    );
+    db.save_dock_pane(
+        workspace_3.workspace_id,
+        &SerializedDockPane {
+            anchor_position: DockAnchor::Right,
+            visible: false,
+        },
+    );
+
+    db.write_to(file).ok();
 
     println!("Wrote database!");
 

crates/db/src/pane.rs 🔗

@@ -1,7 +1,9 @@
+
 use gpui::Axis;
 
+use rusqlite::{OptionalExtension, Connection};
 use serde::{Deserialize, Serialize};
-use serde_rusqlite::to_params_named;
+use serde_rusqlite::{from_row, to_params_named};
 
 use crate::{items::ItemId, workspace::WorkspaceId};
 
@@ -134,6 +136,10 @@ pub struct SerializedPane {
     children: Vec<ItemId>,
 }
 
+
+//********* CURRENTLY IN USE TYPES: *********
+
+
 #[derive(Default, Debug, PartialEq, Eq, Deserialize, Serialize)]
 pub enum DockAnchor {
     #[default]
@@ -144,11 +150,29 @@ pub enum DockAnchor {
 
 #[derive(Default, Debug, PartialEq, Eq, Deserialize, Serialize)]
 pub struct SerializedDockPane {
-    pub workspace_id: WorkspaceId,
     pub anchor_position: DockAnchor,
     pub visible: bool,
 }
 
+impl SerializedDockPane {
+    pub fn to_row(&self, workspace: WorkspaceId) -> DockRow {
+        DockRow { workspace_id: workspace, anchor_position: self.anchor_position, visible: self.visible }
+    }
+}
+
+#[derive(Default, Debug, PartialEq, Eq, Deserialize, Serialize)]
+pub(crate) struct DockRow {
+    workspace_id: WorkspaceId,
+    anchor_position: DockAnchor,
+    visible: bool,
+}
+
+impl DockRow {
+    pub fn to_pane(&self) -> SerializedDockPane {
+        SerializedDockPane { anchor_position: self.anchor_position, visible: self.visible }
+    }
+}
+
 impl Db {
     pub fn get_pane_group(&self, pane_group_id: PaneGroupId) -> SerializedPaneGroup {
         let axis = self.get_pane_group_axis(pane_group_id);
@@ -203,17 +227,52 @@ impl Db {
         unimplemented!();
     }
 
-    pub fn get_dock_pane(&self, _workspace: WorkspaceId) -> Option<SerializedDockPane> {
-        None
+    pub fn get_dock_pane(&self, workspace: WorkspaceId) -> Option<SerializedDockPane> {
+        fn logic(conn: &Connection, workspace: WorkspaceId) -> anyhow::Result<Option<SerializedDockPane>> {
+
+            let mut stmt = conn.prepare("SELECT workspace_id, anchor_position, visible FROM dock_panes WHERE workspace_id = ?")?;
+            
+            let dock_panes = stmt.query_row([workspace.raw_id()], |row_ref| from_row::<DockRow>).optional();
+            
+            let mut dock_panes_iter = stmt.query_and_then([workspace.raw_id()], from_row::<DockRow>)?;
+            let dock_pane = dock_panes_iter
+                    .next()
+                    .and_then(|dock_row|
+                        dock_row
+                            .ok()
+                            .map(|dock_row| dock_row.to_pane()));
+            
+            Ok(dock_pane)
+        }
+
+        self.real()
+            .map(|db| {
+                let lock = db.connection.lock();
+                
+                match logic(&lock, workspace) {
+                    Ok(dock_pane) => dock_pane,
+                    Err(err) => {
+                        log::error!("Failed to get the dock pane: {}", err);
+                        None
+                    },
+                }
+            })
+            .unwrap_or(None)
+            
     }
 
-    pub fn save_dock_pane(&self, dock_pane: &SerializedDockPane) {
-        to_params_named(dock_pane)
+    pub fn save_dock_pane(&self, workspace: WorkspaceId, dock_pane: SerializedDockPane) {
+        to_params_named(dock_pane.to_row(workspace))
+            .map_err(|err| {
+                log::error!("Failed to parse params for the dock row: {}", err);
+                err
+            })
             .ok()
             .zip(self.real())
             .map(|(params, db)| {
                 // TODO: overwrite old dock panes if need be
                 let query = "INSERT INTO dock_panes (workspace_id, anchor_position, visible) VALUES (:workspace_id, :anchor_position, :visible);";
+                
                 db.connection
                     .lock()
                     .execute(query, params.to_slice().as_slice())

crates/db/src/workspace.rs 🔗

@@ -36,6 +36,12 @@ CREATE TABLE worktree_roots(
 #[derive(Debug, PartialEq, Eq, Copy, Clone, Default, Deserialize, Serialize)]
 pub struct WorkspaceId(i64);
 
+impl WorkspaceId {
+    pub fn raw_id(&self) -> i64 {
+        self.0
+    }
+}
+
 #[derive(Default, Debug)]
 pub struct SerializedWorkspace {
     pub workspace_id: WorkspaceId,