1use crate::entity::{IEntitySnapshot, IEntityType, IFromRow, IGetKeyValues, INavigationSetter};
10use crate::error::EFResult;
11use crate::provider::{DbValue, IDatabaseProvider};
12use crate::query::{BoolExpr, IQueryable, QueryBuilder};
13use std::collections::HashMap;
14use std::sync::Arc;
15
16pub struct DbSetEntry<T: IEntityType> {
22 pub entity: T,
23 pub entry_id: u64,
24}
25
26pub trait IDbSet<T: IEntityType>: IQueryable<T> + Send + Sync {
31 fn clear_entries(&mut self);
33
34 fn len(&self) -> usize;
36
37 fn is_empty(&self) -> bool;
39}
40
41pub struct DbSet<T: IEntityType> {
42 pub(crate) entries: Vec<DbSetEntry<T>>,
43 table_name: String,
44 provider: Option<Arc<dyn IDatabaseProvider>>,
45 query_filter: Option<BoolExpr>,
46 filter_map: Option<Arc<HashMap<String, crate::query::CompiledFilter>>>,
47 lazy_loading_enabled: bool,
48}
49
50impl<T: IEntityType + IEntitySnapshot> DbSet<T> {
51 pub fn new(table_name: impl Into<String>) -> Self {
52 Self {
53 entries: Vec::new(),
54 table_name: table_name.into(),
55 provider: None,
56 query_filter: None,
57 filter_map: None,
58 lazy_loading_enabled: false,
59 }
60 }
61
62 pub fn with_provider(
63 table_name: impl Into<String>,
64 provider: Arc<dyn IDatabaseProvider>,
65 ) -> Self {
66 Self {
67 entries: Vec::new(),
68 table_name: table_name.into(),
69 provider: Some(provider),
70 query_filter: None,
71 filter_map: None,
72 lazy_loading_enabled: false,
73 }
74 }
75
76 pub fn set_query_filter(&mut self, filter: BoolExpr) {
77 self.query_filter = Some(filter);
78 }
79
80 pub fn set_filter_map(&mut self, map: Arc<HashMap<String, crate::query::CompiledFilter>>) {
83 self.filter_map = Some(map);
84 }
85
86 pub(crate) fn set_lazy_loading_enabled(&mut self, enabled: bool) {
88 self.lazy_loading_enabled = enabled;
89 }
90
91 pub(crate) fn query_filter(&self) -> Option<&BoolExpr> {
94 self.query_filter.as_ref()
95 }
96
97 pub fn set_provider(&mut self, provider: Arc<dyn IDatabaseProvider>) {
98 self.provider = Some(provider);
99 }
100
101 pub(crate) fn push_entry(&mut self, entity: T, entry_id: u64) {
105 self.entries.push(DbSetEntry { entity, entry_id });
106 }
107
108 pub(crate) fn entry_id_at(&self, idx: usize) -> Option<u64> {
110 self.entries.get(idx).map(|e| e.entry_id)
111 }
112
113 pub fn tracked_entries(&self) -> impl Iterator<Item = &T> {
117 self.entries.iter().map(|e| &e.entity)
118 }
119
120 pub fn tracked_entries_mut(&mut self) -> impl Iterator<Item = &mut T> {
122 self.entries.iter_mut().map(|e| &mut e.entity)
123 }
124
125 pub fn retain(&mut self, f: impl FnMut(&DbSetEntry<T>) -> bool) {
127 self.entries.retain(f);
128 }
129
130 pub fn clear_entries(&mut self) {
132 IDbSet::clear_entries(self);
133 }
134
135 pub fn len(&self) -> usize {
137 IDbSet::len(self)
138 }
139
140 pub fn is_empty(&self) -> bool {
142 IDbSet::is_empty(self)
143 }
144
145 pub fn query(&self) -> QueryBuilder<T> {
149 IQueryable::query(self)
150 }
151
152 pub fn query_ignore_filters(&self) -> QueryBuilder<T> {
155 let qb = match &self.provider {
156 Some(p) => QueryBuilder::with_provider(&self.table_name, p.clone()),
157 None => QueryBuilder::new(&self.table_name),
158 };
159 qb.with_filter_map(self.filter_map.clone())
160 .with_lazy_loading(self.lazy_loading_enabled)
161 }
162
163 pub fn filter<F>(&self, apply: F) -> QueryBuilder<T>
165 where
166 F: FnOnce(QueryBuilder<T>) -> QueryBuilder<T>,
167 {
168 apply(self.query())
169 }
170
171 pub async fn exists_by_id(&self, key_values: HashMap<String, DbValue>) -> EFResult<bool>
173 where
174 T: IFromRow
175 + INavigationSetter
176 + IGetKeyValues
177 + IEntitySnapshot
178 + crate::entity::ILazyInit,
179 {
180 let pairs: Vec<(&str, DbValue)> = key_values
181 .iter()
182 .map(|(k, v)| (k.as_str(), v.clone()))
183 .collect();
184 Ok(self.query().find_by_key(&pairs).await?.is_some())
185 }
186}
187
188impl<T: IEntityType> IQueryable<T> for DbSet<T> {
193 fn query(&self) -> QueryBuilder<T> {
194 let mut qb = match &self.provider {
195 Some(p) => QueryBuilder::with_provider(&self.table_name, p.clone()),
196 None => QueryBuilder::new(&self.table_name),
197 };
198 if let Some(ref filter) = self.query_filter {
199 qb = qb.apply_query_filter(filter.clone());
200 }
201 qb.with_filter_map(self.filter_map.clone())
202 .with_lazy_loading(self.lazy_loading_enabled)
203 }
204}
205
206impl<T: IEntityType + IEntitySnapshot> IDbSet<T> for DbSet<T> {
211 fn clear_entries(&mut self) {
212 self.entries.clear();
213 }
214
215 fn len(&self) -> usize {
216 self.entries.len()
217 }
218
219 fn is_empty(&self) -> bool {
220 self.entries.is_empty()
221 }
222}