Sfoglia il codice sorgente

Add some documentation and an Index::search() method.

Kestrel 7 mesi fa
parent
commit
a3f208bbee
3 ha cambiato i file con 52 aggiunte e 11 eliminazioni
  1. 30 0
      microrm/src/query.rs
  2. 3 3
      microrm/src/schema.rs
  3. 19 8
      microrm/src/schema/index.rs

+ 30 - 0
microrm/src/query.rs

@@ -777,6 +777,36 @@ impl<'a, AI: RelationInterface> Queryable for &'a AI {
     }
 }
 
+impl<E: Entity, EPL: EntityPartList<Entity = E>> Index<E, EPL> {
+    /// Perform a search through this index
+    ///
+    /// Note that this is simply sugar for `idmap_instance.indexed(self, values)`.
+    pub fn search<'a>(
+        &'a self,
+        values: impl 'a + QueryEquivalentList<EPL::DatumList>,
+    ) -> impl 'a + Queryable<EntityOutput = E, OutputContainer = Option<Stored<E>>> {
+        self.indexed(self, values)
+    }
+}
+
+impl<'a, E: Entity, EPL: EntityPartList<Entity = E>> Queryable for &'a Index<E, EPL> {
+    type EntityOutput = E;
+    type OutputContainer = Vec<Stored<E>>;
+    type StaticVersion = &'static Index<E, EPL>;
+
+    fn build(&self) -> Query {
+        Query::new()
+            .attach(QueryPart::Root, "SELECT DISTINCT".into())
+            .attach(QueryPart::Columns, "*".into())
+            .attach(QueryPart::From, format!("`{}`", E::entity_name()))
+    }
+    fn bind(&self, _stmt: &mut StatementContext, _index: &mut i32) {}
+
+    fn conn(&self) -> &Connection {
+        &self.conn
+    }
+}
+
 #[cfg(test)]
 mod query_build_test {
     #[test]

+ 3 - 3
microrm/src/schema.rs

@@ -275,13 +275,13 @@ pub trait DatabaseItem {
     fn accept_item_visitor(visitor: &mut impl DatabaseItemVisitor);
 }
 
-/// Visitor trait for iterating across the types in a [`DatabaseSpec`].
+/// Visitor trait for iterating across the types in a [`Database`].
 pub trait DatabaseItemVisitor {
-    /// Visit an IDMap<T> type.
+    /// Visit an `IDMap<T>` type.
     fn visit_idmap<T: Entity>(&mut self)
     where
         Self: Sized;
-    /// Visit an Index<T, PL> type.
+    /// Visit an `Index<T, PL>` type.
     fn visit_index<T: Entity, PL: EntityPartList<Entity = T>>(&mut self)
     where
         Self: Sized;

+ 19 - 8
microrm/src/schema/index.rs

@@ -1,8 +1,7 @@
-#![allow(missing_docs)]
-
-use crate::db::Connection;
-
-use super::entity::{Entity, EntityPart, EntityPartList};
+use crate::{
+    db::Connection,
+    schema::entity::{Entity, EntityPart, EntityPartList},
+};
 
 /// Trait used to get entity part types by index, used for index schema generation.
 pub trait IndexedEntityPart<const N: usize> {
@@ -12,17 +11,29 @@ pub trait IndexedEntityPart<const N: usize> {
     type Part: EntityPart<Entity = Self::Entity>;
 }
 
+/// Signifier used to specify which indexed part to retrieve.
 pub struct IndexSignifier<const N: usize>;
 
+/// Turns a list of signifiers into an [`EntityPartList`].
 pub trait IndexPartList<E: Entity, II> {
+    /// The resulting [`EntityPartList`].
     type PartList: EntityPartList<Entity = E>;
 }
 
-pub struct Index<E: Entity, EPL: EntityPartList<Entity = E>>(std::marker::PhantomData<(E, EPL)>);
+/// A search index across given fields. Note that since this is a unique index, it also enforces a
+/// uniqueness constraint across the fields.
+pub struct Index<E: Entity, EPL: EntityPartList<Entity = E>> {
+    pub(crate) conn: Connection,
+    _ghost: std::marker::PhantomData<(E, EPL)>,
+}
 
 impl<E: Entity, EPL: EntityPartList<Entity = E>> Index<E, EPL> {
-    pub fn build(_conn: Connection) -> Self {
-        Self(std::marker::PhantomData)
+    /// Construct an Index instance.
+    pub fn build(conn: Connection) -> Self {
+        Self {
+            conn,
+            _ghost: std::marker::PhantomData,
+        }
     }
 }