Skip to main content

icydb_core/db/query/session/
delete.rs

1use crate::{
2    db::{
3        DbSession,
4        query::{
5            Query, QueryError,
6            expr::{FilterExpr, SortExpr},
7            plan::{ExecutablePlan, ExplainPlan},
8            predicate::Predicate,
9        },
10        response::Response,
11    },
12    traits::{CanisterKind, EntityKind, UnitKey},
13};
14
15///
16/// SessionDeleteQuery
17///
18/// Session-bound delete query wrapper.
19/// This type owns *intent construction* and *execution routing only*.
20/// All result projection and cardinality handling lives on `Response<E>`.
21///
22pub struct SessionDeleteQuery<'a, C: CanisterKind, E: EntityKind<Canister = C>> {
23    session: &'a DbSession<C>,
24    query: Query<E>,
25}
26
27impl<'a, C: CanisterKind, E: EntityKind<Canister = C>> SessionDeleteQuery<'a, C, E> {
28    pub(crate) const fn new(session: &'a DbSession<C>, query: Query<E>) -> Self {
29        Self { session, query }
30    }
31
32    // ------------------------------------------------------------------
33    // Intent inspection
34    // ------------------------------------------------------------------
35
36    #[must_use]
37    pub const fn query(&self) -> &Query<E> {
38        &self.query
39    }
40
41    // ------------------------------------------------------------------
42    // Intent builders
43    // ------------------------------------------------------------------
44
45    #[must_use]
46    pub fn by_key(mut self, key: E::PrimaryKey) -> Self {
47        self.query = self.query.by_key(key.into());
48        self
49    }
50
51    #[must_use]
52    pub fn many<I>(mut self, keys: I) -> Self
53    where
54        I: IntoIterator<Item = E::PrimaryKey>,
55    {
56        self.query = self.query.by_keys(keys.into_iter().map(Into::into));
57        self
58    }
59
60    #[must_use]
61    pub fn filter(mut self, predicate: Predicate) -> Self {
62        self.query = self.query.filter(predicate);
63        self
64    }
65
66    pub fn filter_expr(mut self, expr: FilterExpr) -> Result<Self, QueryError> {
67        self.query = self.query.filter_expr(expr)?;
68        Ok(self)
69    }
70
71    pub fn sort_expr(mut self, expr: SortExpr) -> Result<Self, QueryError> {
72        self.query = self.query.sort_expr(expr)?;
73        Ok(self)
74    }
75
76    #[must_use]
77    pub fn order_by(mut self, field: impl AsRef<str>) -> Self {
78        self.query = self.query.order_by(field);
79        self
80    }
81
82    #[must_use]
83    pub fn order_by_desc(mut self, field: impl AsRef<str>) -> Self {
84        self.query = self.query.order_by_desc(field);
85        self
86    }
87
88    #[must_use]
89    pub fn limit(mut self, limit: u32) -> Self {
90        self.query = self.query.limit(limit);
91        self
92    }
93
94    // ------------------------------------------------------------------
95    // Planning / diagnostics
96    // ------------------------------------------------------------------
97
98    pub fn explain(&self) -> Result<ExplainPlan, QueryError> {
99        self.query.explain()
100    }
101
102    pub fn plan(&self) -> Result<ExecutablePlan<E>, QueryError> {
103        self.query.plan()
104    }
105
106    // ------------------------------------------------------------------
107    // Execution (minimal core surface)
108    // ------------------------------------------------------------------
109
110    /// Execute this delete using the session's policy settings.
111    ///
112    /// All result inspection and projection is performed on `Response<E>`.
113    pub fn execute(&self) -> Result<Response<E>, QueryError> {
114        self.session.execute_query(self.query())
115    }
116
117    /// Execute and return whether any rows were affected.
118    pub fn is_empty(&self) -> Result<bool, QueryError> {
119        Ok(self.execute()?.is_empty())
120    }
121
122    /// Execute and return the number of affected rows.
123    pub fn count(&self) -> Result<u32, QueryError> {
124        Ok(self.execute()?.count())
125    }
126
127    /// Execute and require exactly one affected row.
128    pub fn require_one(&self) -> Result<(), QueryError> {
129        self.execute()?.require_one().map_err(QueryError::Response)
130    }
131
132    /// Execute and require at least one affected row.
133    pub fn require_some(&self) -> Result<(), QueryError> {
134        self.execute()?.require_some().map_err(QueryError::Response)
135    }
136}
137
138impl<C: CanisterKind, E: EntityKind<Canister = C>> SessionDeleteQuery<'_, C, E>
139where
140    E::PrimaryKey: UnitKey,
141{
142    /// Delete the singleton entity identified by the unit primary key `()`.
143    #[must_use]
144    pub fn only(mut self) -> Self {
145        self.query = self.query.only();
146        self
147    }
148}