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> {
50 self.one(value)?.try_key()
51 }
52
53 pub fn one_entity(self, value: impl FieldValue) -> Result<E, Error> {
54 self.one(value)?.try_entity()
55 }
56
57 pub fn one_view(self, value: impl FieldValue) -> Result<View<E>, Error> {
58 self.one(value)?.try_view()
59 }
60
61 pub fn one(self, value: impl FieldValue) -> Result<Response<E>, Error> {
66 let query = DeleteQuery::new().one::<E>(value);
67 self.execute(query)
68 }
69
70 pub fn only(self) -> Result<Response<E>, Error> {
71 let query = DeleteQuery::new().one::<E>(());
72 self.execute(query)
73 }
74
75 pub fn many(
76 self,
77 values: impl IntoIterator<Item = impl FieldValue>,
78 ) -> Result<Response<E>, Error> {
79 let query = DeleteQuery::new().many::<E>(values);
80 self.execute(query)
81 }
82
83 pub fn all(self) -> Result<Response<E>, Error> {
84 let query = DeleteQuery::new();
85 self.execute(query)
86 }
87
88 pub fn filter<F, I>(self, f: F) -> Result<Response<E>, Error>
89 where
90 F: FnOnce(FilterDsl) -> I,
91 I: IntoFilterExpr,
92 {
93 let query = DeleteQuery::new().filter(f);
94 self.execute(query)
95 }
96
97 pub fn explain(self, query: DeleteQuery) -> Result<QueryPlan, Error> {
103 QueryValidate::<E>::validate(&query)?;
104
105 Ok(crate::db::executor::plan_for::<E>(query.filter.as_ref()))
106 }
107
108 pub fn execute(self, query: DeleteQuery) -> Result<Response<E>, Error> {
110 let mut span = metrics::Span::<E>::new(metrics::ExecKind::Delete);
111 QueryValidate::<E>::validate(&query)?;
112
113 let ctx = self.db.context::<E>();
114 let plan = crate::db::executor::plan_for::<E>(query.filter.as_ref());
115 let keys = ctx.candidates_from_plan(plan)?; let limit = query
119 .limit
120 .as_ref()
121 .and_then(|l| l.limit)
122 .map(|l| l as usize);
123 let filter_simplified = query.filter.as_ref().map(|f| f.clone().simplify());
124
125 let mut res: Vec<(Key, E)> = Vec::with_capacity(limit.unwrap_or(0));
126 ctx.with_store_mut(|s| {
127 for dk in keys {
128 if let Some(max) = limit
130 && res.len() >= max
131 {
132 break;
133 }
134
135 let Some(bytes) = s.get(&dk) else {
137 continue;
138 };
139
140 let Ok(entity) = deserialize::<E>(&bytes) else {
142 continue;
143 };
144
145 if let Some(ref f) = filter_simplified
147 && !FilterEvaluator::new(&entity).eval(f)
148 {
149 continue;
150 }
151
152 s.remove(&dk);
154 if !E::INDEXES.is_empty() {
155 self.remove_indexes(&entity)?;
156 }
157
158 res.push((dk.key(), entity));
160 }
161
162 Ok::<_, Error>(())
163 })??;
164
165 crate::db::executor::set_rows_from_len(&mut span, res.len());
168
169 Ok(Response(res))
170 }
171
172 fn remove_indexes(&self, entity: &E) -> Result<(), Error> {
174 for index in E::INDEXES {
175 let store = self.db.with_index(|reg| reg.try_get_store(index.store))?;
176
177 store.with_borrow_mut(|this| {
178 this.remove_index_entry(entity, index);
179 });
180 }
181
182 Ok(())
183 }
184}