structsy/
filter.rs

1use crate::internal::EmbeddedDescription;
2use crate::{
3    filter_builder::{FilterBuilder, Reader},
4    projection::Projection,
5    queries::ProjectionResult,
6    queries::{EmbeddedQuery, Query},
7    snapshot::Snapshot,
8    transaction::OwnedSytx,
9    Fetch, Persistent, Ref, Structsy, StructsyIter,
10};
11/// Generic filter for any Persistent structures
12///
13///
14/// # Example
15/// ```rust
16/// use structsy::{ Structsy, StructsyTx, StructsyError, Filter};
17/// use structsy_derive::{queries, embedded_queries, Persistent, PersistentEmbedded};
18///
19/// #[derive(Persistent)]
20/// struct WithEmbedded {
21///     embedded: Embedded,
22/// }
23///
24/// #[derive(PersistentEmbedded)]
25/// struct Embedded {
26///     name: String,
27/// }
28/// impl WithEmbedded {
29///     fn new(name: &str) -> WithEmbedded {
30///         WithEmbedded {
31///             embedded: Embedded { name: name.to_string() },
32///         }
33///     }
34/// }
35///
36/// #[queries(WithEmbedded)]
37/// trait WithEmbeddedQuery {
38///     fn embedded(self, embedded: Filter<Embedded>) -> Self;
39/// }
40///
41/// #[embedded_queries(Embedded)]
42/// trait EmbeddedQuery {
43///     fn by_name(self, name: String) -> Self;
44/// }
45///
46/// fn main() -> Result<(), StructsyError> {
47///     let structsy = Structsy::memory()?;
48///     structsy.define::<WithEmbedded>()?;
49///     let mut tx = structsy.begin()?;
50///     tx.insert(&WithEmbedded::new("aaa"))?;
51///     tx.commit()?;
52///     let embedded_filter = Filter::<Embedded>::new().by_name("aaa".to_string());
53///     let query = Filter::<WithEmbedded>::new().embedded(embedded_filter);
54///     assert_eq!(structsy.fetch(query).count(), 1);
55///     Ok(())
56/// }
57/// ```
58pub struct Filter<T> {
59    filter_builder: FilterBuilder<T>,
60}
61
62impl<T> Filter<T> {
63    pub fn new() -> Self {
64        Filter {
65            filter_builder: FilterBuilder::new(),
66        }
67    }
68    pub(crate) fn extract_filter(self) -> FilterBuilder<T> {
69        self.filter_builder
70    }
71}
72
73impl<T: Persistent> Filter<T> {
74    /// Make a projection from filtered structs.
75    ///
76    ///
77    /// # Example
78    /// ```rust
79    /// use structsy::{ Structsy, StructsyTx, StructsyError, Filter};
80    /// use structsy_derive::{queries, Projection, Persistent};
81    ///
82    /// #[derive(Persistent)]
83    /// struct Person {
84    ///     name:String,
85    ///     surname:String,
86    /// }
87    ///
88    /// impl Person {
89    ///     fn new(name:&str, surname:&str) -> Self {
90    ///         Person {
91    ///             name: name.to_string(),
92    ///             surname: surname.to_string(),
93    ///         }
94    ///     }
95    /// }
96    ///
97    /// #[queries(Person)]
98    /// trait PersonQuery {
99    ///     fn by_name(self, name:&str) -> Self;
100    /// }
101    ///
102    /// #[derive(Projection)]
103    /// #[projection = "Person" ]
104    /// struct NameProjection {
105    ///     name:String,
106    /// }
107    ///
108    ///
109    /// fn main() -> Result<(), StructsyError> {
110    ///     let structsy = Structsy::memory()?;
111    ///     structsy.define::<Person>()?;
112    ///     let mut tx = structsy.begin()?;
113    ///     tx.insert(&Person::new("a_name", "a_surname"))?;
114    ///     tx.commit()?;
115    ///     let query =
116    ///     Filter::<Person>::new().by_name("a_name").projection::<NameProjection>();
117    ///     assert_eq!(structsy.fetch(query).next().unwrap().name, "a_name");
118    ///     Ok(())
119    /// }
120    /// ```
121    pub fn projection<P: Projection<T>>(self) -> ProjectionResult<P, T> {
122        ProjectionResult::new(self.filter_builder)
123    }
124}
125
126impl<T> Default for Filter<T> {
127    fn default() -> Self {
128        Self::new()
129    }
130}
131
132impl<T: Persistent + 'static> Fetch<(Ref<T>, T)> for Filter<T> {
133    fn into(self, structsy: &Structsy) -> StructsyIter<(Ref<T>, T)> {
134        self.fetch(structsy)
135    }
136
137    fn into_tx(self, tx: &mut OwnedSytx) -> StructsyIter<(Ref<T>, T)> {
138        self.fetch_tx(tx)
139    }
140
141    fn fetch(self, structsy: &Structsy) -> StructsyIter<(Ref<T>, T)> {
142        let data = self.extract_filter().finish(Reader::Structsy(structsy.clone()));
143        StructsyIter::new(data)
144    }
145
146    fn fetch_tx(self, tx: &mut OwnedSytx) -> StructsyIter<(Ref<T>, T)> {
147        let data = self.extract_filter().finish(Reader::Tx(tx.reference()));
148        StructsyIter::new(data)
149    }
150
151    fn fetch_snapshot(self, snapshot: &Snapshot) -> StructsyIter<(Ref<T>, T)> {
152        let data = self.extract_filter().finish(Reader::Snapshot(snapshot.clone()));
153        StructsyIter::new(data)
154    }
155}
156
157impl<T: EmbeddedDescription + 'static> EmbeddedQuery<T> for Filter<T> {
158    fn filter_builder(&mut self) -> &mut FilterBuilder<T> {
159        &mut self.filter_builder
160    }
161    fn add_group(&mut self, filter: Filter<T>) {
162        let base = self.filter_builder();
163        base.and(filter.extract_filter());
164    }
165}
166
167impl<T: Persistent + 'static> Query<T> for Filter<T> {
168    fn filter_builder(&mut self) -> &mut FilterBuilder<T> {
169        &mut self.filter_builder
170    }
171    fn add_group(&mut self, filter: Filter<T>) {
172        let base = self.filter_builder();
173        base.and_filter(filter.extract_filter());
174    }
175}