icydb_core/db/executor/
delete.rs1use crate::{
2 Error, Key,
3 db::{
4 Db,
5 executor::FilterEvaluator,
6 primitives::{FilterDsl, FilterExt, IntoFilterExpr},
7 query::{DeleteQuery, QueryPlan, QueryValidate},
8 response::Response,
9 },
10 deserialize,
11 obs::metrics,
12 traits::{EntityKind, FieldValue},
13 view::View,
14};
15use std::marker::PhantomData;
16
17#[derive(Clone, Copy)]
22pub struct DeleteExecutor<E: EntityKind> {
23 db: Db<E::Canister>,
24 debug: bool,
25 _marker: PhantomData<E>,
26}
27
28impl<E: EntityKind> DeleteExecutor<E> {
29 #[must_use]
30 pub const fn new(db: Db<E::Canister>, debug: bool) -> Self {
31 Self {
32 db,
33 debug,
34 _marker: PhantomData,
35 }
36 }
37
38 #[must_use]
40 pub const fn debug(mut self) -> Self {
41 self.debug = true;
42 self
43 }
44
45 pub fn one_key(self, value: impl FieldValue) -> Result<Key, Error> {
51 self.one(value)?.try_key()
52 }
53
54 pub fn one_entity(self, value: impl FieldValue) -> Result<E, Error> {
56 self.one(value)?.try_entity()
57 }
58
59 pub fn one_view(self, value: impl FieldValue) -> Result<View<E>, Error> {
61 self.one(value)?.try_view()
62 }
63
64 pub fn one(self, value: impl FieldValue) -> Result<Response<E>, Error> {
70 let query = DeleteQuery::new().one::<E>(value);
71 self.execute(query)
72 }
73
74 pub fn only(self) -> Result<Response<E>, Error> {
76 let query = DeleteQuery::new().one::<E>(());
77 self.execute(query)
78 }
79
80 pub fn many(
82 self,
83 values: impl IntoIterator<Item = impl FieldValue>,
84 ) -> Result<Response<E>, Error> {
85 let query = DeleteQuery::new().many::<E>(values);
86 self.execute(query)
87 }
88
89 pub fn all(self) -> Result<Response<E>, Error> {
91 let query = DeleteQuery::new();
92 self.execute(query)
93 }
94
95 pub fn filter<F, I>(self, f: F) -> Result<Response<E>, Error>
97 where
98 F: FnOnce(FilterDsl) -> I,
99 I: IntoFilterExpr,
100 {
101 let query = DeleteQuery::new().filter(f);
102 self.execute(query)
103 }
104
105 pub fn explain(self, query: DeleteQuery) -> Result<QueryPlan, Error> {
112 QueryValidate::<E>::validate(&query)?;
113
114 Ok(crate::db::executor::plan_for::<E>(query.filter.as_ref()))
115 }
116
117 pub fn execute(self, query: DeleteQuery) -> Result<Response<E>, Error> {
120 let mut span = metrics::Span::<E>::new(metrics::ExecKind::Delete);
121 QueryValidate::<E>::validate(&query)?;
122
123 let ctx = self.db.context::<E>();
124 let plan = crate::db::executor::plan_for::<E>(query.filter.as_ref());
125 let keys = ctx.candidates_from_plan(plan)?; let limit = query
129 .limit
130 .as_ref()
131 .and_then(|l| l.limit)
132 .map(|l| l as usize);
133 let filter_simplified = query.filter.as_ref().map(|f| f.clone().simplify());
134
135 let mut res: Vec<(Key, E)> = Vec::with_capacity(limit.unwrap_or(0));
136 ctx.with_store_mut(|s| {
137 for dk in keys {
138 if let Some(max) = limit
140 && res.len() >= max
141 {
142 break;
143 }
144
145 let Some(bytes) = s.get(&dk) else {
147 continue;
148 };
149
150 let Ok(entity) = deserialize::<E>(&bytes) else {
152 continue;
153 };
154
155 if let Some(ref f) = filter_simplified
157 && !FilterEvaluator::new(&entity).eval(f)
158 {
159 continue;
160 }
161
162 s.remove(&dk);
164 if !E::INDEXES.is_empty() {
165 self.remove_indexes(&entity)?;
166 }
167
168 res.push((dk.key(), entity));
170 }
171
172 Ok::<_, Error>(())
173 })??;
174
175 crate::db::executor::set_rows_from_len(&mut span, res.len());
178
179 Ok(Response(res))
180 }
181
182 fn remove_indexes(&self, entity: &E) -> Result<(), Error> {
184 for index in E::INDEXES {
185 let store = self.db.with_index(|reg| reg.try_get_store(index.store))?;
186
187 store.with_borrow_mut(|this| {
188 this.remove_index_entry(entity, index);
189 });
190 }
191
192 Ok(())
193 }
194}