Browse Source

WIP for query builder

Kestrel 2 years ago
parent
commit
9123fcca7e
3 changed files with 161 additions and 0 deletions
  1. 21 0
      Cargo.lock
  2. 2 0
      microrm/Cargo.toml
  3. 138 0
      microrm/src/query.rs

+ 21 - 0
Cargo.lock

@@ -90,6 +90,26 @@ dependencies = [
  "unicode-width",
 ]
 
+[[package]]
+name = "const-str"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b60160dfb442e53d068d55ec16675a7d9df6cacd072d3540742a1e7bcdb6150"
+dependencies = [
+ "const-str-proc-macro",
+]
+
+[[package]]
+name = "const-str-proc-macro"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c047fef6b3d672b32b454079702745d0fc64a69a2c7933caf75684ba41d5df2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "convert_case"
 version = "0.5.0"
@@ -341,6 +361,7 @@ name = "microrm"
 version = "0.2.4"
 dependencies = [
  "base64",
+ "const-str",
  "criterion",
  "lazy_static",
  "microrm-macros",

+ 2 - 0
microrm/Cargo.toml

@@ -17,6 +17,8 @@ serde_bytes = { version = "0.11.6" }
 serde_json = { version = "1.0" }
 lazy_static = { version = "1.4.0" }
 
+const-str = { version = "0.3.1" }
+
 microrm-macros = { path = "../microrm-macros", version = "0.2.1" }
 
 [dev-dependencies]

+ 138 - 0
microrm/src/query.rs

@@ -160,7 +160,10 @@ impl<'l> QueryInterface<'l> {
         query.reset().expect("Couldn't reset query");
         with(query)
     }
+}
 
+// Legacy interface
+impl<'l> QueryInterface<'l> {
     /// Search for an entity by a property
     pub fn get_one_by<C: EntityColumn, V: Modelable>(
         &self,
@@ -420,3 +423,138 @@ impl<'l> QueryInterface<'l> {
         )
     }
 }
+
+/*
+
+qi.get().by(Table::Column, value).by(Table::OtherColumn, value).one()
+qi.get().id(some_id).one()
+qi.get().by(Table::Column, value).all()
+
+ * */
+
+pub struct BuildResult(String, bool);
+
+pub trait Buildable {
+    fn build() -> BuildResult;
+}
+
+pub trait Gettable<'sq, 'l, T: Entity> {
+    type Builder: Buildable;
+    fn qi(&self) -> &'sq QueryInterface<'l> { todo!() }
+}
+
+pub struct GetQuery<'sq, 'l, T: Entity> {
+    qi: &'sq QueryInterface<'l>,
+    _ghost: std::marker::PhantomData<(T, &'sq str)>,
+}
+
+
+impl<'sq, 'l, T: Entity> Gettable<'sq, 'l, T> for GetQuery<'sq, 'l, T> {
+    type Builder = GetBuild<T>;
+}
+
+pub struct GetBuild<T: Entity> { _ghost: std::marker::PhantomData<T> }
+
+impl<T: Entity> Buildable for GetBuild<T> {
+    fn build() -> BuildResult {
+        todo!()
+    }
+}
+
+pub struct ByClause<'sq, 'l, T: Entity, Col: EntityColumn<Entity = T>, Wrap: Gettable<'sq, 'l, T>> {
+    wrap: Wrap,
+    col: &'sq Col,
+    data: &'sq dyn Modelable,
+    _ghost: std::marker::PhantomData<(&'sq str, &'l str, T, Col, Wrap)>,
+}
+
+pub struct ByBuild<Col: EntityColumn, Wrap: Buildable> {
+    _ghost: std::marker::PhantomData<(Col, Wrap)>
+}
+
+impl<Col: EntityColumn, Wrap: Buildable> Buildable for ByBuild<Col, Wrap> {
+    fn build() -> BuildResult {
+        Wrap::build();
+        todo!()
+    }
+}
+
+impl<'sq, 'l, T: Entity> GetQuery<'sq, 'l, T> {
+    pub fn by<NCol: EntityColumn<Entity = T>>(self, col: &'sq NCol, data: &'sq dyn Modelable) -> ByClause<'sq, 'l, T, NCol, Self> {
+        ByClause { wrap: self, col, data, _ghost: std::marker::PhantomData }
+    }
+}
+
+impl<'sq, 'l, T: Entity, Col: EntityColumn<Entity = T>, Wrap: Gettable<'sq, 'l, T>> Gettable<'sq, 'l, T> for ByClause<'sq, 'l, T, Col, Wrap> {
+    type Builder = ByBuild<Col, Wrap::Builder>;
+
+    /*fn build_query(&self) -> (String, bool) {
+        let (parent, is_where) = self.wrap.build_query();
+        (format!("{} {} {} = ?", parent, if is_where { "AND" } else { "WHERE" }, "<>"), true)
+    }*/
+}
+
+impl<'sq, 'l, T: Entity, Col: EntityColumn<Entity = T>, Wrap: Gettable<'sq, 'l, T>> ByClause<'sq, 'l, T, Col, Wrap> {
+    fn build_query(&self) {
+        // <Self as Gettable<T>>::build_query(self);
+        // <Self as Gettable<T>>::Builder;
+        <<Self as Gettable<T>>::Builder>::build();
+    }
+
+    pub fn one(self) -> Option<T> {
+        // let ty = std::any::TypeId::of::<ByClause<'static, 'static, T, Col, Wrap>>();
+        todo!()
+    }
+
+    pub fn all(self) -> Vec<T> {
+        todo!()
+    }
+
+    pub fn by<NCol: EntityColumn<Entity = T>>(self, col: &'sq NCol, data: &'sq dyn Modelable) -> ByClause<'sq, 'l, T, NCol, Self> {
+        ByClause { wrap: self, col, data, _ghost: std::marker::PhantomData }
+    }
+}
+
+impl<'l> QueryInterface<'l> {
+    // pub fn get<'q, T: Entity>(&'q self) -> GetQuery<T> where 'q: 'l {
+    pub fn get<'sq, T: Entity>(&'sq self) -> GetQuery<T> where 'sq: 'l {
+        GetQuery::<'sq, 'l, _> { qi: self, _ghost: std::marker::PhantomData }
+    }
+}
+
+#[cfg(test)]
+mod get_test {
+    use microrm_macros::Entity;
+    use serde::{Serialize, Deserialize};
+
+    use crate::QueryInterface;
+
+
+    #[derive(Entity, Serialize, Deserialize)]
+    #[microrm_internal]
+    pub struct KVStore {
+        key: String,
+        value: String
+    }
+
+    fn simple_test<'sq, 'l>(qi: &'sq QueryInterface<'l>) {
+        let g = qi.get::<'sq, KVStore>();
+        // qi.get::<'l,'_,KVStore>();
+
+        //let t = g.by(&KVStore::Key, &"test");
+        //drop(t);
+        
+    }
+
+    #[test]
+    fn test_build_query() {
+        let db = crate::DB::new_in_memory(crate::Schema::new()).unwrap();
+        let qi = db.query_interface();
+
+        simple_test(&qi);
+
+        {
+        
+        }
+    }
+}