From f38d9a6df20fc746f98c2a1132e67e6c3adf2c7a Mon Sep 17 00:00:00 2001 From: mxhagen Date: Mon, 9 Dec 2024 14:13:07 +0100 Subject: [PATCH] add sync function --- macros/src/lib.rs | 21 ++++++++++++++++++--- src/test/macros.rs | 11 +++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 95cc6b6..df7622d 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -4,8 +4,6 @@ use syn::{parse_macro_input, Data, DeriveInput, Fields}; // TODO: wrap functions in a trait -// TODO: add sync function (set fields of self by querying db) - // TODO: doc comments #[proc_macro_derive(Table)] @@ -126,7 +124,7 @@ pub fn derive_table(input: TokenStream) -> TokenStream { ); let update_fn = quote! { - pub fn update(&mut self, conn: &rusqlite::Connection) -> rusqlite::Result + pub fn update(&self, conn: &rusqlite::Connection) -> rusqlite::Result where #(#to_sql_trait_bounds),* { if self.id.is_none() { @@ -138,6 +136,22 @@ pub fn derive_table(input: TokenStream) -> TokenStream { }; + let sync_fn = quote! { + pub fn sync(&mut self, conn: &rusqlite::Connection) -> rusqlite::Result + where #(#from_sql_trait_bounds),* + { + if self.id.is_none() { + return Ok(false); + } + match #struct_name::get_by_id(conn, self.id.unwrap())? { + Some(person) => *self = person, + _ => return Ok(false), + }; + Ok(true) + } + }; + + let get_by_id_fn = quote! { pub fn get_by_id(conn: &rusqlite::Connection, id: i64) -> rusqlite::Result> where @@ -197,6 +211,7 @@ pub fn derive_table(input: TokenStream) -> TokenStream { #insert_fn #upsert_fn #update_fn + #sync_fn #get_by_id_fn #delete_fn #delete_by_id_fn diff --git a/src/test/macros.rs b/src/test/macros.rs index 44724eb..1be210a 100644 --- a/src/test/macros.rs +++ b/src/test/macros.rs @@ -87,11 +87,22 @@ fn test_table_derive_macro() { let larry_copy = Person::get_by_id(&conn, larry_id).expect("Querying a row should work"); assert_eq!(larry_copy, Some(larry.clone()), "Retrieving upserted row should give an identical row"); + conn.execute("UPDATE Person SET (age) = (27) WHERE id = ?1", [larry_id]) + .expect("Explicit Sqlite statement (not a library test) failed"); + + let found = larry.sync(&conn).expect("Syncing struct to existing row should succeed"); + assert!(found, "Row should have been found"); + assert_eq!(larry.age, 27, "Syncing struct to edited table row should work"); + Person::drop_table(&conn).expect("Dropping table should work"); Person::drop_table(&conn).expect_err("Dropping previously dropped table should err"); + + let exists: bool = conn.query_row("SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE type='table' AND name='Person');", [], |row| row.get(0)).expect("Explicit Sqlite statement (not a library test) failed"); + assert!(!exists, "Deleted table should not exist anymore but does"); } + // TODO: implement compile-error test(s) -- perhaps with `trybuild`? // // #[test]