Kestrel 2 år sedan
förälder
incheckning
b14912a0a7

+ 21 - 19
microrm/src/lib.rs

@@ -66,14 +66,14 @@ pub enum DBError {
     SanityCheckFailure,
 }
 
-#[derive(PartialEq,Debug)]
+#[derive(PartialEq, Debug)]
 pub enum CreateMode {
     /// The database must exist and have a valid schema already
     MustExist,
     /// It's fine if the database doesn't exist, but it must have a valid schema if it does
     AllowNewDatabase,
     /// Nuke the contents if need be, just get the database
-    AllowSchemaUpdate
+    AllowSchemaUpdate,
 }
 
 impl std::fmt::Display for DBError {
@@ -92,11 +92,7 @@ pub struct DB {
 }
 
 impl DB {
-    pub fn new(
-        schema: model::SchemaModel,
-        path: &str,
-        mode: CreateMode
-    ) -> Result<Self, DBError> {
+    pub fn new(schema: model::SchemaModel, path: &str, mode: CreateMode) -> Result<Self, DBError> {
         Self::from_connection(
             sqlite::Connection::open(path).map_err(|_| DBError::ConnectFailure)?,
             schema,
@@ -152,15 +148,23 @@ impl DB {
 
     fn check_schema(&self, mode: CreateMode) -> Result<(), DBError> {
         let mut has_metaschema = false;
-        self.conn.iterate(format!("SELECT * FROM \"sqlite_master\" WHERE \"type\"='table' AND \"name\"='{}'", Metaschema::table_name()), |row| {
-            println!("row: {:?}", row);
-            has_metaschema = true;
-            true
-        }).map_err(|e| DBError::EarlyFailure(e))?;
+        self.conn
+            .iterate(
+                format!(
+                    "SELECT * FROM \"sqlite_master\" WHERE \"type\"='table' AND \"name\"='{}'",
+                    Metaschema::table_name()
+                ),
+                |row| {
+                    println!("row: {:?}", row);
+                    has_metaschema = true;
+                    true
+                },
+            )
+            .map_err(|e| DBError::EarlyFailure(e))?;
 
         if mode != CreateMode::MustExist {
             println!("Creating schema!");
-            return self.create_schema()
+            return self.create_schema();
         }
 
         let qi = query::QueryInterface::new(self);
@@ -197,12 +201,10 @@ impl DB {
 
         let qi = query::QueryInterface::new(self);
 
-        let add_result = qi.add(
-            &meta::Metaschema {
-                key: "schema_hash".to_string(),
-                value: self.schema_hash.clone(),
-            },
-        );
+        let add_result = qi.add(&meta::Metaschema {
+            key: "schema_hash".to_string(),
+            value: self.schema_hash.clone(),
+        });
 
         assert!(add_result.is_some());
 

+ 3 - 1
microrm/src/model.rs

@@ -52,7 +52,9 @@ impl std::error::Error for ModelError {}
 /// A database value, aka a single column of a single row
 pub trait Modelable {
     fn bind_to(&self, stmt: &mut sqlite::Statement, col: usize) -> sqlite::Result<()>;
-    fn build_from(stmt: &sqlite::Statement, col_offset: usize) -> sqlite::Result<(Self, usize)> where Self: Sized;
+    fn build_from(stmt: &sqlite::Statement, col_offset: usize) -> sqlite::Result<(Self, usize)>
+    where
+        Self: Sized;
 }
 
 /// A database entity, aka a struct representing a row in a table

+ 4 - 2
microrm/src/model/create.rs

@@ -219,7 +219,8 @@ mod test {
             super::sql_for::<Single>(),
             (
                 r#"DROP TABLE IF EXISTS "single""#.to_owned(),
-                r#"CREATE TABLE IF NOT EXISTS "single" (id integer primary key,"e" integer)"#.to_owned()
+                r#"CREATE TABLE IF NOT EXISTS "single" (id integer primary key,"e" integer)"#
+                    .to_owned()
             )
         );
 
@@ -227,7 +228,8 @@ mod test {
             super::sql_for::<Reference>(),
             (
                 r#"DROP TABLE IF EXISTS "reference""#.to_owned(),
-                r#"CREATE TABLE IF NOT EXISTS "reference" (id integer primary key,"e" integer)"#.to_owned()
+                r#"CREATE TABLE IF NOT EXISTS "reference" (id integer primary key,"e" integer)"#
+                    .to_owned()
             )
         );
     }

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

@@ -1,5 +1,5 @@
-use serde::de::Visitor;
 use super::Modelable;
+use serde::de::Visitor;
 
 pub struct RowDeserializer<'de, 'l> {
     row: &'de sqlite::Statement<'l>,
@@ -49,14 +49,16 @@ impl<'de, 'a, 'l> serde::de::Deserializer<'de> for &'a mut RowDeserializer<'de,
     }
 
     fn deserialize_i64<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
-        let built = Modelable::build_from(self.row, self.col_index).map_err(|e| Self::Error::LoadError(e.to_string()))?;
+        let built = Modelable::build_from(self.row, self.col_index)
+            .map_err(|e| Self::Error::LoadError(e.to_string()))?;
         let res = v.visit_i64(built.0);
         self.col_index += built.1;
         res
     }
 
     fn deserialize_string<V: Visitor<'de>>(self, v: V) -> Result<V::Value, Self::Error> {
-        let built = Modelable::build_from(self.row, self.col_index).map_err(|e| Self::Error::LoadError(e.to_string()))?;
+        let built = Modelable::build_from(self.row, self.col_index)
+            .map_err(|e| Self::Error::LoadError(e.to_string()))?;
         let res = v.visit_string(built.0);
         self.col_index += built.1;
         res

+ 16 - 4
microrm/src/model/modelable.rs

@@ -5,7 +5,10 @@ impl Modelable for i32 {
     fn bind_to(&self, stmt: &mut sqlite::Statement, col: usize) -> sqlite::Result<()> {
         (*self as i64).bind(stmt, col)
     }
-    fn build_from(stmt: &sqlite::Statement, col_offset: usize) -> sqlite::Result<(Self, usize)> where Self: Sized {
+    fn build_from(stmt: &sqlite::Statement, col_offset: usize) -> sqlite::Result<(Self, usize)>
+    where
+        Self: Sized,
+    {
         stmt.read::<i64>(col_offset).map(|x| (x as i32, 1))
     }
 }
@@ -14,7 +17,10 @@ impl Modelable for i64 {
     fn bind_to(&self, stmt: &mut sqlite::Statement, col: usize) -> sqlite::Result<()> {
         self.bind(stmt, col)
     }
-    fn build_from(stmt: &sqlite::Statement, col_offset: usize) -> sqlite::Result<(Self, usize)> where Self: Sized {
+    fn build_from(stmt: &sqlite::Statement, col_offset: usize) -> sqlite::Result<(Self, usize)>
+    where
+        Self: Sized,
+    {
         stmt.read(col_offset).map(|x| (x, 1))
     }
 }
@@ -23,7 +29,10 @@ impl<'a> Modelable for &'a str {
     fn bind_to(&self, stmt: &mut sqlite::Statement, col: usize) -> sqlite::Result<()> {
         self.bind(stmt, col)
     }
-    fn build_from(_stmt: &sqlite::Statement, _col_offset: usize) -> sqlite::Result<(Self, usize)> where Self: Sized {
+    fn build_from(_stmt: &sqlite::Statement, _col_offset: usize) -> sqlite::Result<(Self, usize)>
+    where
+        Self: Sized,
+    {
         unreachable!("sqlite only gives Strings back, not &strs!");
     }
 }
@@ -32,7 +41,10 @@ impl Modelable for std::string::String {
     fn bind_to(&self, stmt: &mut sqlite::Statement, col: usize) -> sqlite::Result<()> {
         self.as_str().bind(stmt, col)
     }
-    fn build_from(stmt: &sqlite::Statement, col_offset: usize) -> sqlite::Result<(Self, usize)> where Self: Sized {
+    fn build_from(stmt: &sqlite::Statement, col_offset: usize) -> sqlite::Result<(Self, usize)>
+    where
+        Self: Sized,
+    {
         stmt.read(col_offset).map(|x| (x, 1))
     }
 }

+ 37 - 21
microrm/src/query.rs

@@ -57,13 +57,17 @@ impl<'l> QueryInterface<'l> {
     }
 
     /// Helper function to process an expected one result
-    fn expect_one_result<T>(&self, stmt: &mut sqlite::Statement, with_result: &mut dyn FnMut(&mut sqlite::Statement) -> Option<T>) -> Option<T> {
+    fn expect_one_result<T>(
+        &self,
+        stmt: &mut sqlite::Statement,
+        with_result: &mut dyn FnMut(&mut sqlite::Statement) -> Option<T>,
+    ) -> Option<T> {
         let state = stmt.next();
         assert!(state.is_ok());
         assert_eq!(state.ok(), Some(sqlite::State::Row));
 
         let res = with_result(stmt);
-        
+
         let state = stmt.next();
         assert!(state.is_ok());
         assert_eq!(state.ok(), Some(sqlite::State::Done));
@@ -72,7 +76,11 @@ impl<'l> QueryInterface<'l> {
     }
 
     /// Search for an entity by a property
-    pub fn get_one_by<T: Entity<Column = C>, C: EntityColumns<Entity = T>, V: crate::model::Modelable>(
+    pub fn get_one_by<
+        T: Entity<Column = C>,
+        C: EntityColumns<Entity = T>,
+        V: crate::model::Modelable,
+    >(
         &self,
         c: C,
         val: V,
@@ -80,7 +88,8 @@ impl<'l> QueryInterface<'l> {
         let table_name = <T as Entity>::table_name();
         let column_name = <T as Entity>::name(c);
 
-        let mut prepared = self.db
+        let mut prepared = self
+            .db
             .conn
             .prepare(&format!(
                 "SELECT * FROM \"{}\" WHERE \"{}\" = ?",
@@ -95,14 +104,15 @@ impl<'l> QueryInterface<'l> {
         return self.expect_one_result(&mut prepared, &mut |stmt| {
             let id: i64 = stmt.read(0).ok()?;
             let mut rd = crate::model::load::RowDeserializer::from_row(&stmt);
-            return Some(WithID::wrap(T::deserialize(&mut rd).ok()?, id))
-        })
+            return Some(WithID::wrap(T::deserialize(&mut rd).ok()?, id));
+        });
     }
 
     /// Search for an entity by ID
-    pub fn get_one_by_id<I: EntityID<Entity=T>, T: Entity>(&self, id: I) -> Option<WithID<T>> {
+    pub fn get_one_by_id<I: EntityID<Entity = T>, T: Entity>(&self, id: I) -> Option<WithID<T>> {
         let table_name = <T as Entity>::table_name();
-        let mut prepared = self.db
+        let mut prepared = self
+            .db
             .conn
             .prepare(&format!("SELECT * FROM \"{}\" WHERE id = ?", table_name))
             .ok()?;
@@ -112,12 +122,16 @@ impl<'l> QueryInterface<'l> {
         return self.expect_one_result(&mut prepared, &mut |stmt| {
             let id: i64 = stmt.read(0).ok()?;
             let mut rd = crate::model::load::RowDeserializer::from_row(&stmt);
-            return Some(WithID::wrap(T::deserialize(&mut rd).ok()?, id))
-        })
+            return Some(WithID::wrap(T::deserialize(&mut rd).ok()?, id));
+        });
     }
 
     /// Search for all entities matching a property
-    pub fn get_all_by<T: Entity<Column = C>, C: EntityColumns<Entity = T>, V: crate::model::Modelable>(
+    pub fn get_all_by<
+        T: Entity<Column = C>,
+        C: EntityColumns<Entity = T>,
+        V: crate::model::Modelable,
+    >(
         &self,
         c: C,
         val: V,
@@ -125,7 +139,8 @@ impl<'l> QueryInterface<'l> {
         let table_name = <T as Entity>::table_name();
         let column_name = <T as Entity>::name(c);
 
-        let mut prepared = self.db
+        let mut prepared = self
+            .db
             .conn
             .prepare(&format!(
                 "SELECT * FROM \"{}\" WHERE \"{}\" = ?",
@@ -152,23 +167,24 @@ impl<'l> QueryInterface<'l> {
 
     /// Add an entity to its table
     pub fn add<T: Entity + serde::Serialize>(&self, m: &T) -> Option<<T as Entity>::ID> {
-
         let placeholders = (0..(<T as Entity>::column_count() - 1))
             .map(|n| "?".to_string())
             .collect::<Vec<_>>()
             .join(",");
 
-        let mut prepared = self.db.conn.prepare(&format!(
-            "INSERT INTO \"{}\" VALUES (NULL, {}) RETURNING \"id\"",
-            <T as Entity>::table_name(),
-            placeholders
-        )).ok()?;
+        let mut prepared = self
+            .db
+            .conn
+            .prepare(&format!(
+                "INSERT INTO \"{}\" VALUES (NULL, {}) RETURNING \"id\"",
+                <T as Entity>::table_name(),
+                placeholders
+            ))
+            .ok()?;
 
         crate::model::store::serialize_into(&mut prepared, m).ok()?;
 
-        let rowid = self.expect_one_result(&mut prepared, &mut |stmt| {
-            stmt.read::<i64>(0).ok()
-        })?;
+        let rowid = self.expect_one_result(&mut prepared, &mut |stmt| stmt.read::<i64>(0).ok())?;
 
         Some(<T as Entity>::ID::from_raw_id(rowid))