diff --git a/Cargo.lock b/Cargo.lock index 6e8a247..713ab5b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -118,7 +118,7 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "squail" -version = "0.1.1" +version = "0.1.2" dependencies = [ "rusqlite", "squail-macros", diff --git a/Cargo.toml b/Cargo.toml index 0ede629..d68efc1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "squail" -version = "0.1.1" +version = "0.1.2" edition = "2021" [dependencies] diff --git a/macros/src/lib.rs b/macros/src/lib.rs index ece8335..b3680ca 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -3,7 +3,9 @@ use proc_macro::TokenStream; use quote::{quote, ToTokens}; use syn::{parse_macro_input, Data, DeriveInput, Fields}; -// TODO: wrap functions in a trait? would probably use the other crate +// TODO: wrap functions in a trait? would probably use the other (main) crate + +// TODO: own error enum (for update). also use the other (main) crate for this #[proc_macro_derive(Table)] @@ -116,10 +118,10 @@ pub fn derive_table(input: TokenStream) -> TokenStream { match self.id { None => self.insert(conn), Some(id) => { - if !self.update(conn)? { - return self.insert(conn); + match self.update(conn) { + Ok(_) => return Ok(id), + Err(_) => return self.insert(conn), } - Ok(id) }, } } @@ -136,19 +138,21 @@ pub fn derive_table(input: TokenStream) -> TokenStream { let update_fn = quote! { /// Update a table row using the calling struct instance. /// - /// If the row does not yet exist, this fails. - /// A version that inserts a new row instead also exists. See `update_or_insert`. + /// If `id` is `None`, this fails with `InvalidQuery`. + /// If the row does not exist, this fails with `QueryReturnedNoRows`. /// - /// Result contains `true` if a row was updated. - pub fn update(&self, conn: &rusqlite::Connection) -> rusqlite::Result + /// A version that inserts a new row instead also exists. See `update_or_insert`. + pub fn update(&self, conn: &rusqlite::Connection) -> rusqlite::Result<()> where #(#to_sql_trait_bounds),* { if self.id.is_none() { - // TODO: bad design, should probably fail instead - return Ok(false); + return Err(rusqlite::Error::InvalidQuery) } let updated_count = conn.execute(#update_sql, rusqlite::params![#(#field_accessors),*])?; - Ok(updated_count > 0) + match updated_count { + 0 => Err(rusqlite::Error::QueryReturnedNoRows), + _ => Ok(()), + } } }; diff --git a/src/test/macros.rs b/src/test/macros.rs index fbaa007..600f843 100644 --- a/src/test/macros.rs +++ b/src/test/macros.rs @@ -67,8 +67,7 @@ fn test_table_derive_macro() { .expect("After (mutable) insertion, id should not be None"); larry.age += 1; - let updated_something = larry.update(&conn).expect("Updating should work"); - assert!(updated_something, "Should have updated a row"); + larry.update(&conn).expect("Updating should work"); let larry_copy = Person::get_by_id(&conn, larry_id).expect("Querying a row should work"); assert_eq!(