Explorar o código

Add by_id() function for Filter.

Kestrel %!s(int64=2) %!d(string=hai) anos
pai
achega
720f934631

+ 10 - 0
microrm-macros/src/entity.rs

@@ -225,6 +225,8 @@ pub(crate) fn derive(tokens: TokenStream) -> TokenStream {
 
     let field_count = fields.named.iter().count();
 
+    let columns_name = format_ident!("_{}_columns", &input.ident.to_string().to_case(Case::Snake));
+
     quote!{
         // Related types for #struct_name
 
@@ -234,6 +236,7 @@ pub(crate) fn derive(tokens: TokenStream) -> TokenStream {
         // Implementations for #struct_name
         impl #microrm_ref::entity::Entity for #struct_name {
             type ID = #id_name;
+            type IDColumn = #columns_name::ID;
 
             fn table_name() -> &'static str { #table_name }
             fn column_count() -> usize {
@@ -243,6 +246,9 @@ pub(crate) fn derive(tokens: TokenStream) -> TokenStream {
             fn values(&self) -> Vec<&dyn #microrm_ref::model::Modelable> {
                 vec![ #(#value_references),* ]
             }
+            fn visit_values<F: FnMut(&dyn #microrm_ref::model::Modelable) -> ()>(&self, visit: &mut F) {
+                #(visit(#value_references));*
+            }
 
             fn build_from(stmt: &#microrm_ref::re_export::sqlite::Statement) -> #microrm_ref::re_export::sqlite::Result<Self> {
                 Ok(Self {
@@ -254,6 +260,10 @@ pub(crate) fn derive(tokens: TokenStream) -> TokenStream {
                 #columns_array_name.as_ref()
             }
 
+            fn id_column() -> Self::IDColumn {
+                Self::ID
+            }
+
             /*fn foreign_keys() -> &'static [&'static dyn #microrm_ref::entity::EntityForeignKey<Self::Column>] {
                 &[#(#foreign_keys),*]
             }*/

+ 5 - 1
microrm/src/entity.rs

@@ -3,13 +3,17 @@ use crate::model::Modelable;
 /// A database entity, aka a struct representing a row in a table
 pub trait Entity: 'static + for<'de> serde::Deserialize<'de> + serde::Serialize {
     type ID: EntityID;
+    type IDColumn: EntityColumn<Entity = Self>;
     fn table_name() -> &'static str;
     fn column_count() -> usize
     where
         Self: Sized;
     fn columns() -> &'static [&'static dyn EntityColumn<Entity = Self>];
+    fn id_column() -> Self::IDColumn;
+
     fn values(&self) -> Vec<&dyn Modelable>;
-    // TODO: visit_values() to avoid heap allocation
+    // visit_values() avoids heap allocation at the cost of programming complexity
+    fn visit_values<F: FnMut(&dyn Modelable) -> ()>(&self, visit: &mut F);
 
     fn build_from(stmt: &sqlite::Statement) -> sqlite::Result<Self>
     where

+ 13 - 0
microrm/src/query/filter.rs

@@ -1,5 +1,6 @@
 use std::marker::PhantomData;
 use std::hash::{Hash,Hasher};
+use crate::entity::EntityID;
 use crate::{Entity,entity::EntityColumn,WithID,QueryInterface,model::Modelable};
 use super::{Resolvable,build::CompareOp};
 use super::build::*;
@@ -28,6 +29,18 @@ where
         }
     }
 
+    fn by_id<I: EntityID<Entity = Self::Table>>(self, given: &'r I) -> Filter<'r, 'q, Self, <Self::Table as Entity>::IDColumn, I>
+        where Self: Sized {
+
+        Filter {
+            wrap: self,
+            col: Self::Table::id_column(),
+            op: CompareOp::Equals,
+            given,
+            _ghost: PhantomData
+        }
+    }
+
     fn by_op<C: EntityColumn<Entity = Self::Table>, G: Modelable + ?Sized>(
         self,
         col: C,

+ 5 - 3
microrm/src/query/update.rs

@@ -19,7 +19,6 @@ impl<'r, 'q, T: Entity> Update<'r, 'q, T> {
         }
     }
 
-    // pub fn entire(&self, to: &T) -> Entire<'r, 'q, T>impl Filterable<'r, 'q, Table = T> {
     pub fn to(self, to: &'r T) -> Entire<'r, 'q, T> {
         Entire {
             wrap: self,
@@ -101,11 +100,9 @@ impl<'r, 'q, T: Entity> QueryComponent for Entire<'r, 'q, T> {
 
         // skip ID
         for col in 0..T::column_count()-1 {
-            println!("col: {}", col);
             values[col].bind_to(stmt, ind + col)?;
         }
 
-        println!("bound!");
         Ok(ind + T::column_count() - 1)
     }
 }
@@ -258,5 +255,10 @@ mod test {
         assert_eq!(check.len(), 1);
         assert_eq!(check[0].key, "c");
         assert_eq!(check[0].value, "d");
+
+        let check = qi.get().by_id(&id).all().unwrap();
+        assert_eq!(check.len(), 1);
+        assert_eq!(check[0].key, "c");
+        assert_eq!(check[0].value, "d");
     }
 }