Browse Source

Code cleanups.

Kestrel 2 years ago
parent
commit
3320d25bef

+ 4 - 13
microrm-macros/src/lib.rs

@@ -4,7 +4,7 @@ use quote::{quote,format_ident};
 
 use convert_case::{Case, Casing};
 
-#[proc_macro_derive(Model, attributes(microrm))]
+#[proc_macro_derive(Entity, attributes(microrm))]
 pub fn derive_model(tokens: TokenStream) -> TokenStream {
     let input = parse_macro_input!(tokens as DeriveInput);
 
@@ -14,12 +14,6 @@ pub fn derive_model(tokens: TokenStream) -> TokenStream {
 
     let table_name = format!("{}", struct_name).to_case(Case::Snake);
 
-    let entity_impl = quote!{
-        impl crate::model::Entity for #struct_name {
-            fn table_name() -> &'static str { #table_name }
-        }
-    };
-
     if let syn::Data::Struct(st) = input.data {
         if let syn::Fields::Named(fields) = st.fields {
 
@@ -38,19 +32,16 @@ pub fn derive_model(tokens: TokenStream) -> TokenStream {
                 value_references.push(quote!{ &self. #field_name });
             }
 
-            let field_count = fields.named.len();
-
             let ret = quote!{
-                #entity_impl
-
                 #[derive(Clone,Copy,strum::IntoStaticStr,strum::EnumCount)]
                 enum #enum_name {
                     #variants
                 }
 
-                impl crate::model::EntityColumn for #struct_name {
+                impl crate::model::Entity for #struct_name {
+                    fn table_name() -> &'static str { #table_name }
                     type Column = #enum_name;
-                    fn count() -> usize {
+                    fn column_count() -> usize {
                         <Self::Column as strum::EnumCount>::COUNT
                     }
                     fn index(c: Self::Column) -> usize {

+ 8 - 9
microrm/src/lib.rs

@@ -1,9 +1,9 @@
 pub mod model;
 pub mod query;
 
-pub use microrm_macros::Model;
+pub use microrm_macros::Entity;
 
-#[derive(Debug,serde::Serialize,serde::Deserialize,Model)]
+#[derive(Debug,serde::Serialize,serde::Deserialize,Entity)]
 struct Metaschema {
     key: String,
     value: String
@@ -36,7 +36,8 @@ impl DB {
         use sha2::Digest;
 
         let mut hasher = sha2::Sha256::new();
-        schema.create().iter().map(|sql| hasher.update(sql.as_bytes()));
+        schema.drop().iter().map(|sql| hasher.update(sql.as_bytes())).count();
+        schema.create().iter().map(|sql| hasher.update(sql.as_bytes())).count();
 
         base64::encode(hasher.finalize())
     }
@@ -52,20 +53,18 @@ impl DB {
 
             for ds in self.schema.drop() {
                 let prepared = self.conn.prepare(ds);
-                let result = prepared.unwrap().execute([]).expect("Creation sql failed");
+                prepared.unwrap().execute([]).expect("Dropping sql failed");
             }
 
             for cs in self.schema.create() {
                 let prepared = self.conn.prepare(cs);
-                let result = prepared.unwrap().execute([]).expect("Creation sql failed");
+                prepared.unwrap().execute([]).expect("Creation sql failed");
             }
 
             query::add(self, &Metaschema { key: "schema_hash".to_string(), value: self.schema_hash.clone() });
 
             println!("re-search results: {:?}", query::get_one_by::<Metaschema, _>(self, MetaschemaColumns::Key, "schema_hash"));
         }
-
-        // println!("schema: {:?}", schema);
     }
 }
 
@@ -73,7 +72,7 @@ impl DB {
 mod test {
     use super::DB;
 
-    #[derive(serde::Deserialize,crate::Model)]
+    #[derive(serde::Serialize,serde::Deserialize,crate::Entity)]
     struct S1 {
         id: i32,
     }
@@ -85,6 +84,6 @@ mod test {
 
     #[test]
     fn in_memory_schema() {
-        let db = DB::new_in_memory(simple_schema());
+        let _db = DB::new_in_memory(simple_schema());
     }
 }

+ 7 - 10
microrm/src/model.rs

@@ -36,8 +36,13 @@ impl serde::de::Error for ModelError {
 impl std::error::Error for ModelError { }
 
 /// A database entity, aka a struct representing a row in a table
-pub trait Entity {
+pub trait Entity : for<'de> serde::Deserialize<'de> + serde::Serialize {
+    type Column;
     fn table_name() -> &'static str;
+    fn column_count() -> usize where Self: Sized;
+    fn index(c: Self::Column) -> usize where Self: Sized;
+    fn name(c: Self::Column) -> &'static str where Self: Sized;
+    fn values(&self) -> Vec<&dyn rusqlite::ToSql>;
 }
 
 /// How we describe an entire schema
@@ -52,7 +57,7 @@ impl SchemaModel {
         Self { drop: Vec::new(), create: Vec::new() }
     }
 
-    pub fn add<'de, E: Entity + EntityColumn + serde::Deserialize<'de>>(mut self) -> Self {
+    pub fn add<'de, E: Entity>(mut self) -> Self {
         let (drop, create) = create::sql_for::<E>();
         self.drop.push(drop);
         self.create.push(create);
@@ -62,11 +67,3 @@ impl SchemaModel {
     pub fn drop(&self) -> &Vec<String> { &self.drop }
     pub fn create(&self) -> &Vec<String> { &self.create }
 }
-
-pub trait EntityColumn {
-    type Column;
-    fn count() -> usize where Self: Sized;
-    fn index(c: Self::Column) -> usize where Self: Sized;
-    fn name(c: Self::Column) -> &'static str where Self: Sized;
-    fn values(&self) -> Vec<&dyn rusqlite::ToSql>;
-}

+ 6 - 6
microrm/src/model/create.rs

@@ -22,17 +22,17 @@ impl<'de, 'a> serde::de::Deserializer<'de> for &'a mut CreateDeserializer<'de> {
         todo!()
     }
 
-    fn deserialize_i32<V: Visitor<'de>>(mut self, v: V) -> Result<V::Value, Self::Error> {
+    fn deserialize_i32<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
         self.column_types.push("integer".to_owned());
         v.visit_i32(0)
     }
 
-    fn deserialize_i64<V: Visitor<'de>>(mut self, v: V) -> Result<V::Value, Self::Error> {
+    fn deserialize_i64<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
         self.column_types.push("integer".to_owned());
         v.visit_i64(0)
     }
 
-    fn deserialize_string<V: Visitor<'de>>(mut self, v: V) -> Result<V::Value, Self::Error> {
+    fn deserialize_string<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
         self.column_types.push("varchar".to_owned());
         v.visit_string("".to_owned())
     }
@@ -53,7 +53,7 @@ impl<'de> serde::de::SeqAccess<'de> for CreateDeserializer<'de> {
     }
 }
 
-pub fn sql_for<'de, T: crate::model::EntityColumn + crate::model::Entity + serde::de::Deserialize<'de>>() -> (String,String) {
+pub fn sql_for<'de, T: crate::model::Entity>() -> (String,String) {
     let mut cd = CreateDeserializer { table_name: None, column_names: None, column_types: Vec::new(), _de: std::marker::PhantomData{} };
 
     T::deserialize(&mut cd).expect("SQL creation failed!");
@@ -70,10 +70,10 @@ pub fn sql_for<'de, T: crate::model::EntityColumn + crate::model::Entity + serde
 
 #[cfg(test)]
 mod test {
-    #[derive(serde::Deserialize,crate::Model)]
+    #[derive(serde::Serialize,serde::Deserialize,crate::Entity)]
     struct Empty {}
 
-    #[derive(serde::Deserialize,crate::Model)]
+    #[derive(serde::Serialize,serde::Deserialize,crate::Entity)]
     struct Single {
         e: i32
     }

+ 0 - 5
microrm/src/model/load.rs

@@ -12,11 +12,6 @@ impl<'de> RowDeserializer<'de> {
         // we skip the rowid by starting at index 1
         Self { row, col_index: 1 }
     }
-
-    fn next_col_value<T>(&mut self) -> T {
-        self.col_index += 1;
-        todo!()
-    }
 }
 
 impl<'de, 'a> serde::de::Deserializer<'de> for &'a mut RowDeserializer<'de> {

+ 2 - 2
microrm/src/model/store.rs

@@ -1,3 +1,3 @@
-pub fn serialize_as_row<'data, T: serde::Serialize + crate::model::EntityColumn>(value: &'data T) -> Vec<&'data dyn rusqlite::ToSql> {
-    (value as &dyn crate::model::EntityColumn<Column = _>).values()
+pub fn serialize_as_row<'data, T: crate::model::Entity>(value: &'data T) -> Vec<&'data dyn rusqlite::ToSql> {
+    value.values()
 }

+ 14 - 14
microrm/src/query.rs

@@ -4,41 +4,41 @@ pub use crate::DB;
 pub struct ID (i64);
 
 #[derive(Debug)]
-pub struct WithID<T: crate::model::Entity + crate::model::EntityColumn> {
+pub struct WithID<T: crate::model::Entity + crate::model::Entity> {
     wrap: T,
     id: ID
 }
 
-impl<T: crate::model::Entity + crate::model::EntityColumn> WithID<T> {
+impl<T: crate::model::Entity + crate::model::Entity> WithID<T> {
     fn wrap(what: T, raw_id: i64) -> Self {
         Self { wrap: what, id: ID { 0: raw_id } }
     }
 }
 
-impl<T: crate::model::Entity + crate::model::EntityColumn> WithID<T> {
+impl<T: crate::model::Entity + crate::model::Entity> WithID<T> {
     pub fn id(&self) -> ID { self.id }
 }
 
-impl<T: crate::model::Entity + crate::model::EntityColumn> AsRef<T> for WithID<T> {
+impl<T: crate::model::Entity + crate::model::Entity> AsRef<T> for WithID<T> {
     fn as_ref(&self) -> &T { return &self.wrap }
 }
 
-impl<T: crate::model::Entity + crate::model::EntityColumn> std::ops::Deref for WithID<T> {
+impl<T: crate::model::Entity + crate::model::Entity> std::ops::Deref for WithID<T> {
     type Target = T;
     fn deref(&self) -> &Self::Target { &self.wrap }
 }
 
-impl<T: crate::model::Entity + crate::model::EntityColumn> std::ops::DerefMut for WithID<T> {
+impl<T: crate::model::Entity + crate::model::Entity> std::ops::DerefMut for WithID<T> {
     fn deref_mut(&mut self) -> &mut Self::Target { &mut self.wrap }
 }
 
 
 /// Search for an entity by a property
-pub fn get_one_by<T: crate::model::Entity + crate::model::EntityColumn + for<'de> serde::Deserialize<'de>, V: rusqlite::ToSql>(
-    db: &DB, c: <T as crate::model::EntityColumn>::Column, val: V) -> Option<WithID<T>> {
+pub fn get_one_by<T: crate::model::Entity, V: rusqlite::ToSql>(
+    db: &DB, c: <T as crate::model::Entity>::Column, val: V) -> Option<WithID<T>> {
 
     let table_name = <T as crate::model::Entity>::table_name();
-    let column_name = <T as crate::model::EntityColumn>::name(c);
+    let column_name = <T as crate::model::Entity>::name(c);
     let mut prepared = db.conn.prepare(&format!("SELECT rowid, tbl.* FROM {} tbl WHERE {} = ?1", table_name, column_name)).ok()?;
 
     let result = prepared.query_row([&val], |row| {
@@ -50,16 +50,16 @@ pub fn get_one_by<T: crate::model::Entity + crate::model::EntityColumn + for<'de
 }
 
 /// Add an entity to its table
-pub fn add<T: crate::model::Entity + crate::model::EntityColumn + serde::Serialize>(db: &DB, m: &T) -> Option<ID> {
+pub fn add<T: crate::model::Entity + serde::Serialize>(db: &DB, m: &T) -> Option<ID> {
     let row = crate::model::store::serialize_as_row(m);
 
-    let placeholders = (0..<T as crate::model::EntityColumn>::count()).map(|n| format!("?{}", n+1)).collect::<Vec<_>>().join(",");
+    let placeholders = (0..<T as crate::model::Entity>::column_count()).map(|n| format!("?{}", n+1)).collect::<Vec<_>>().join(",");
 
     let res = db.conn.prepare(&format!("INSERT INTO {} VALUES ({})", <T as crate::model::Entity>::table_name(), placeholders));
     let mut prepared = res.ok()?;
 
     // make sure we bound enough things
-    assert_eq!(row.len(), <T as crate::model::EntityColumn>::count());
+    assert_eq!(row.len(), <T as crate::model::Entity>::column_count());
 
     let id = prepared.insert(rusqlite::params_from_iter(row)).ok()?;
     Some(ID { 0: id })
@@ -70,8 +70,8 @@ pub struct Context<'a> {
 }
 
 impl<'a> Context<'a> {
-    pub fn get_one_by<T: crate::model::Entity + crate::model::EntityColumn + for<'de> serde::Deserialize<'de>, V: rusqlite::ToSql>(
-        &self, c: <T as crate::model::EntityColumn>::Column, val: V) -> Option<WithID<T>> {
+    pub fn get_one_by<T: crate::model::Entity + for<'de> serde::Deserialize<'de>, V: rusqlite::ToSql>(
+        &self, c: <T as crate::model::Entity>::Column, val: V) -> Option<WithID<T>> {
 
         get_one_by(self.db, c, val)
     }