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}