Touched up sql macro

Mikayla Maki created

Change summary

crates/db/src/db.rs                 | 61 +++++++++++++-----------------
crates/editor/src/persistence.rs    | 11 +++--
crates/terminal/src/persistence.rs  | 14 +++---
crates/workspace/src/persistence.rs | 47 +++++++++++++++++++----
4 files changed, 78 insertions(+), 55 deletions(-)

Detailed changes

crates/db/src/db.rs 🔗

@@ -82,36 +82,31 @@ macro_rules! connection {
 }
 
 #[macro_export]
-macro_rules! exec_method {
-    ($id:ident(): $sql:literal) => {
-         pub fn $id(&self) -> $crate::sqlez::anyhow::Result<()> {
-             use $crate::anyhow::Context;
-
-             self.exec($sql)?()
-                 .context(::std::format!(
-                     "Error in {}, exec failed to execute or parse for: {}",
-                     ::std::stringify!($id),
-                     ::std::stringify!($sql),
-                 ))
-         }
+macro_rules! sql_method {
+    ($id:ident() ->  Result<()>: $sql:literal) => {
+        pub fn $id(&self) -> $crate::sqlez::anyhow::Result<()> {
+            use $crate::anyhow::Context;
+
+            self.exec($sql)?().context(::std::format!(
+                "Error in {}, exec failed to execute or parse for: {}",
+                ::std::stringify!($id),
+                ::std::stringify!($sql),
+            ))
+        }
     };
-    ($id:ident($($arg:ident: $arg_type:ty),+): $sql:literal) => {
-         pub fn $id(&self, $($arg: $arg_type),+) -> $crate::sqlez::anyhow::Result<()> {
-             use $crate::anyhow::Context;
-
-             self.exec_bound::<($($arg_type),+)>($sql)?(($($arg),+))
-                 .context(::std::format!(
-                     "Error in {}, exec_bound failed to execute or parse for: {}",
-                     ::std::stringify!($id),
-                     ::std::stringify!($sql),
-                 ))
-         }
+    ($id:ident($($arg:ident: $arg_type:ty),+) -> Result<()>: $sql:literal) => {
+        pub fn $id(&self, $($arg: $arg_type),+) -> $crate::sqlez::anyhow::Result<()> {
+            use $crate::anyhow::Context;
+
+            self.exec_bound::<($($arg_type),+)>($sql)?(($($arg),+))
+                .context(::std::format!(
+                    "Error in {}, exec_bound failed to execute or parse for: {}",
+                    ::std::stringify!($id),
+                    ::std::stringify!($sql),
+                ))
+        }
     };
-}
-
-#[macro_export]
-macro_rules! select_method {
-    ($id:ident() ->  $return_type:ty: $sql:literal) => {
+    ($id:ident() ->  Result<Vec<$return_type:ty>>: $sql:literal) => {
          pub fn $id(&self) -> $crate::sqlez::anyhow::Result<Vec<$return_type>> {
              use $crate::anyhow::Context;
 
@@ -123,7 +118,7 @@ macro_rules! select_method {
                  ))
          }
     };
-    ($id:ident($($arg:ident: $arg_type:ty),+) -> $return_type:ty: $sql:literal) => {
+    ($id:ident($($arg:ident: $arg_type:ty),+) -> Result<Vec<$return_type:ty>>: $sql:literal) => {
          pub fn $id(&self, $($arg: $arg_type),+) -> $crate::sqlez::anyhow::Result<Vec<$return_type>> {
              use $crate::anyhow::Context;
 
@@ -135,11 +130,7 @@ macro_rules! select_method {
                  ))
          }
     };
-}
-
-#[macro_export]
-macro_rules! select_row_method {
-    ($id:ident() ->  $return_type:ty: $sql:literal) => {
+    ($id:ident() ->  Result<Option<$return_type:ty>>: $sql:literal) => {
          pub fn $id(&self) -> $crate::sqlez::anyhow::Result<Option<$return_type>> {
              use $crate::anyhow::Context;
 
@@ -151,7 +142,7 @@ macro_rules! select_row_method {
                  ))
          }
     };
-    ($id:ident($($arg:ident: $arg_type:ty),+) ->  $return_type:ty: $sql:literal) => {
+    ($id:ident($($arg:ident: $arg_type:ty),+) ->  Result<Option<$return_type:ty>>: $sql:literal) => {
          pub fn $id(&self, $($arg: $arg_type),+) -> $crate::sqlez::anyhow::Result<Option<$return_type>>  {
              use $crate::anyhow::Context;
 

crates/editor/src/persistence.rs 🔗

@@ -1,7 +1,7 @@
 use std::path::{Path, PathBuf};
 
 use anyhow::{Context, Result};
-use db::{connection, exec_method};
+use db::{connection, sql_method};
 use indoc::indoc;
 use sqlez::domain::Domain;
 use workspace::{ItemId, Workspace, WorkspaceId};
@@ -39,8 +39,9 @@ impl EditorDb {
         .context("Path not found for serialized editor")
     }
 
-    exec_method!(save_path(item_id: ItemId, workspace_id: WorkspaceId, path: &Path):
-        "INSERT OR REPLACE INTO editors(item_id, workspace_id, path)
-         VALUES (?, ?, ?)"
-    );
+    sql_method! {
+        save_path(item_id: ItemId, workspace_id: WorkspaceId, path: &Path) -> Result<()>:
+            "INSERT OR REPLACE INTO editors(item_id, workspace_id, path)
+            VALUES (?, ?, ?)"
+    }
 }

crates/terminal/src/persistence.rs 🔗

@@ -1,6 +1,6 @@
 use std::path::{Path, PathBuf};
 
-use db::{connection, exec_method, indoc, select_row_method, sqlez::domain::Domain};
+use db::{connection, indoc, sql_method, sqlez::domain::Domain};
 
 use workspace::{ItemId, Workspace, WorkspaceId};
 
@@ -28,16 +28,16 @@ impl Domain for Terminal {
 }
 
 impl TerminalDb {
-    exec_method!(
-        save_working_directory(item_id: ItemId, workspace_id: WorkspaceId, working_directory: &Path):
+    sql_method! {
+        save_working_directory(item_id: ItemId, workspace_id: WorkspaceId, working_directory: &Path) -> Result<()>:
             "INSERT OR REPLACE INTO terminals(item_id, workspace_id, working_directory)
              VALUES (?1, ?2, ?3)"
-    );
+    }
 
-    select_row_method!(
-        get_working_directory(item_id: ItemId, workspace_id: WorkspaceId) -> PathBuf:
+    sql_method! {
+        get_working_directory(item_id: ItemId, workspace_id: WorkspaceId) -> Result<Option<PathBuf>>:
             "SELECT working_directory
              FROM terminals 
              WHERE item_id = ? AND workspace_id = ?"
-    );
+    }
 }

crates/workspace/src/persistence.rs 🔗

@@ -5,7 +5,7 @@ pub mod model;
 use std::path::Path;
 
 use anyhow::{anyhow, bail, Context, Result};
-use db::{connection, select_row_method};
+use db::{connection, sql_method};
 use gpui::Axis;
 use indoc::indoc;
 
@@ -190,10 +190,10 @@ impl WorkspaceDb {
         .log_err();
     }
 
-    select_row_method!(
-        next_id() -> WorkspaceId:
+    sql_method! {
+        next_id() -> Result<Option<WorkspaceId>>:
             "INSERT INTO workspaces DEFAULT VALUES RETURNING workspace_id"
-    );
+    }
 
     /// Returns the previous workspace ids sorted by last modified along with their opened worktree roots
     pub fn recent_workspaces(&self, limit: usize) -> Vec<(WorkspaceId, WorkspaceLocation)> {
@@ -384,6 +384,37 @@ mod tests {
 
     use super::*;
 
+    #[test]
+    fn test_next_id_stability() {
+        env_logger::try_init().ok();
+
+        let db = WorkspaceDb(open_memory_db(Some("test_workspace_id_stability")));
+
+        db.migrate(
+            "test_table",
+            &["CREATE TABLE test_table(
+                text TEXT,
+                workspace_id INTEGER,
+                FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id)
+                    ON DELETE CASCADE
+            ) STRICT;"],
+        )
+        .unwrap();
+        
+        let id = db.next_id().unwrap();
+    
+        db.exec_bound("INSERT INTO test_table(text, workspace_id) VALUES (?, ?)")
+            .unwrap()(("test-text-1", id))
+        .unwrap();
+
+        let test_text_1 = db
+            .select_row_bound::<_, String>("SELECT text FROM test_table WHERE workspace_id = ?")
+            .unwrap()(1)
+        .unwrap()
+        .unwrap();
+        assert_eq!(test_text_1, "test-text-1");
+    }
+    
     #[test]
     fn test_workspace_id_stability() {
         env_logger::try_init().ok();
@@ -439,19 +470,19 @@ mod tests {
         });
         db.save_workspace(&workspace_2);
 
-        let test_text_1 = db
+        let test_text_2 = db
             .select_row_bound::<_, String>("SELECT text FROM test_table WHERE workspace_id = ?")
             .unwrap()(2)
         .unwrap()
         .unwrap();
-        assert_eq!(test_text_1, "test-text-2");
+        assert_eq!(test_text_2, "test-text-2");
 
-        let test_text_2 = db
+        let test_text_1 = db
             .select_row_bound::<_, String>("SELECT text FROM test_table WHERE workspace_id = ?")
             .unwrap()(1)
         .unwrap()
         .unwrap();
-        assert_eq!(test_text_2, "test-text-1");
+        assert_eq!(test_text_1, "test-text-1");
     }
 
     #[test]