Compare commits

...

2 Commits

Author SHA1 Message Date
mxhagen
84efaaad3f make update fn signature more straightforward 2024-12-11 22:32:34 +01:00
mxhagen
109f6a5a70 bump version 2024-12-11 22:32:34 +01:00
4 changed files with 18 additions and 15 deletions

2
Cargo.lock generated
View File

@ -118,7 +118,7 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]] [[package]]
name = "squail" name = "squail"
version = "0.1.0" version = "0.1.2"
dependencies = [ dependencies = [
"rusqlite", "rusqlite",
"squail-macros", "squail-macros",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "squail" name = "squail"
version = "0.1.1" version = "0.1.2"
edition = "2021" edition = "2021"
[dependencies] [dependencies]

View File

@ -3,7 +3,9 @@ use proc_macro::TokenStream;
use quote::{quote, ToTokens}; use quote::{quote, ToTokens};
use syn::{parse_macro_input, Data, DeriveInput, Fields}; 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)] #[proc_macro_derive(Table)]
@ -116,10 +118,10 @@ pub fn derive_table(input: TokenStream) -> TokenStream {
match self.id { match self.id {
None => self.insert(conn), None => self.insert(conn),
Some(id) => { Some(id) => {
if !self.update(conn)? { match self.update(conn) {
return self.insert(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! { let update_fn = quote! {
/// Update a table row using the calling struct instance. /// Update a table row using the calling struct instance.
/// ///
/// If the row does not yet exist, this fails. /// If `id` is `None`, this fails with `InvalidQuery`.
/// A version that inserts a new row instead also exists. See `update_or_insert`. /// If the row does not exist, this fails with `QueryReturnedNoRows`.
/// ///
/// Result contains `true` if a row was updated. /// A version that inserts a new row instead also exists. See `update_or_insert`.
pub fn update(&self, conn: &rusqlite::Connection) -> rusqlite::Result<bool> pub fn update(&self, conn: &rusqlite::Connection) -> rusqlite::Result<()>
where #(#to_sql_trait_bounds),* where #(#to_sql_trait_bounds),*
{ {
if self.id.is_none() { if self.id.is_none() {
// TODO: bad design, should probably fail instead return Err(rusqlite::Error::InvalidQuery)
return Ok(false);
} }
let updated_count = conn.execute(#update_sql, rusqlite::params![#(#field_accessors),*])?; let updated_count = conn.execute(#update_sql, rusqlite::params![#(#field_accessors),*])?;
Ok(updated_count > 0) match updated_count {
0 => Err(rusqlite::Error::QueryReturnedNoRows),
_ => Ok(()),
}
} }
}; };

View File

@ -67,8 +67,7 @@ fn test_table_derive_macro() {
.expect("After (mutable) insertion, id should not be None"); .expect("After (mutable) insertion, id should not be None");
larry.age += 1; larry.age += 1;
let updated_something = larry.update(&conn).expect("Updating should work"); larry.update(&conn).expect("Updating should work");
assert!(updated_something, "Should have updated a row");
let larry_copy = Person::get_by_id(&conn, larry_id).expect("Querying a row should work"); let larry_copy = Person::get_by_id(&conn, larry_id).expect("Querying a row should work");
assert_eq!( assert_eq!(