1use std::fmt;
2
3use keelson_core::Mod;
4use keelson_exec::{ExecError, ExecResult, Execute as _, Executor, FromRow, Row};
5
6use crate::Table;
7use crate::delegate::delegate_clause;
8
9fn decode_rows<T: FromRow>(rows: Vec<Row>) -> Result<Vec<T>, ExecError> {
10 rows.into_iter().map(|mut r| T::from_row(&mut r)).collect()
11}
12
13pub struct ModelInsert<M: Table> {
20 setter: M::Setter,
21 #[allow(clippy::type_complexity)] mods: Vec<Box<dyn FnOnce(&mut M::Insert) + Send>>,
23}
24
25impl<M: Table> fmt::Debug for ModelInsert<M> {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 f.debug_struct("ModelInsert")
28 .field("mods", &self.mods.len())
29 .finish_non_exhaustive()
30 }
31}
32
33impl<M: Table> ModelInsert<M> {
34 pub(crate) fn new(setter: M::Setter) -> Self {
35 ModelInsert {
36 setter,
37 mods: Vec::new(),
38 }
39 }
40
41 #[must_use]
45 pub fn with(mut self, mods: impl Mod<M::Insert> + Send + 'static) -> Self {
46 self.mods.push(Box::new(move |q| mods.apply(q)));
47 self
48 }
49
50 async fn build(self, db: &dyn Executor) -> Result<M::Insert, ExecError> {
51 let ModelInsert { mut setter, mods } = self;
52 M::before_insert(db, &mut setter).await?;
53 let mut q = M::insert_query(setter);
54 for m in mods {
55 m(&mut q);
56 }
57 Ok(q)
58 }
59
60 pub async fn one(self, db: &dyn Executor) -> Result<M::Row, ExecError> {
65 let q = self.build(db).await?;
66 let mut models: Vec<M::Row> = decode_rows(q.fetch_rows(db).await?)?;
67 match models.len() {
68 0 => Err(ExecError::RowNotFound),
69 1 => {
70 M::after_insert(db, &models).await?;
71 Ok(models.pop().expect("len checked"))
72 }
73 _ => Err(ExecError::TooManyRows),
74 }
75 }
76
77 pub async fn exec(self, db: &dyn Executor) -> Result<ExecResult, ExecError> {
80 let q = self.build(db).await?;
81 let done = q.execute(db).await?;
82 M::after_insert(db, &[]).await?;
83 Ok(done)
84 }
85}
86
87pub struct ModelUpdate<M: Table> {
91 setter: M::Setter,
92 query: M::Update,
93}
94
95impl<M: Table> fmt::Debug for ModelUpdate<M> {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 f.debug_struct("ModelUpdate")
98 .field("query", &self.query)
99 .finish_non_exhaustive()
100 }
101}
102
103impl<M: Table> ModelUpdate<M> {
104 pub(crate) fn new(setter: M::Setter, mods: impl Mod<Self>) -> Self {
105 let mut u = ModelUpdate {
106 setter,
107 query: M::update_query(),
108 };
109 mods.apply(&mut u);
110 u
111 }
112
113 pub fn apply(&mut self, mods: impl Mod<M::Update>) {
116 mods.apply(&mut self.query);
117 }
118
119 async fn build(self, db: &dyn Executor) -> Result<M::Update, ExecError> {
120 let ModelUpdate {
121 mut setter,
122 mut query,
123 } = self;
124 M::before_update(db, &mut setter).await?;
125 M::apply_setter(setter, &mut query);
126 Ok(query)
127 }
128
129 pub async fn exec(self, db: &dyn Executor) -> Result<ExecResult, ExecError> {
131 let q = self.build(db).await?;
132 let done = q.execute(db).await?;
133 M::after_update(db, done.rows_affected).await?;
134 Ok(done)
135 }
136
137 pub async fn all(self, db: &dyn Executor) -> Result<Vec<M::Row>, ExecError> {
141 let q = self.build(db).await?;
142 let models: Vec<M::Row> = decode_rows(q.fetch_rows(db).await?)?;
143 M::after_update(db, models.len() as u64).await?;
144 Ok(models)
145 }
146}
147
148pub struct ModelDelete<M: Table> {
150 query: M::Delete,
151}
152
153impl<M: Table> fmt::Debug for ModelDelete<M> {
154 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155 f.debug_struct("ModelDelete")
156 .field("query", &self.query)
157 .finish()
158 }
159}
160
161impl<M: Table> ModelDelete<M> {
162 pub(crate) fn new(mods: impl Mod<Self>) -> Self {
163 let mut d = ModelDelete {
164 query: M::delete_query(),
165 };
166 mods.apply(&mut d);
167 d
168 }
169
170 pub fn apply(&mut self, mods: impl Mod<M::Delete>) {
172 mods.apply(&mut self.query);
173 }
174
175 pub async fn exec(self, db: &dyn Executor) -> Result<ExecResult, ExecError> {
177 M::before_delete(db).await?;
178 let done = self.query.execute(db).await?;
179 M::after_delete(db, done.rows_affected).await?;
180 Ok(done)
181 }
182
183 pub async fn all(self, db: &dyn Executor) -> Result<Vec<M::Row>, ExecError> {
185 M::before_delete(db).await?;
186 let models: Vec<M::Row> = decode_rows(self.query.fetch_rows(db).await?)?;
187 M::after_delete(db, models.len() as u64).await?;
188 Ok(models)
189 }
190}
191
192delegate_clause!(
194 ModelUpdate,
195 Table,
196 Update,
197 HasWith,
198 with_mut,
199 keelson_core::clause::With
200);
201delegate_clause!(
202 ModelUpdate,
203 Table,
204 Update,
205 HasTableRef,
206 table_ref_mut,
207 keelson_core::clause::TableRef
208);
209delegate_clause!(
210 ModelUpdate,
211 Table,
212 Update,
213 HasJoins,
214 joins_mut,
215 Vec<keelson_core::clause::Join>
216);
217delegate_clause!(
218 ModelUpdate,
219 Table,
220 Update,
221 HasWhere,
222 where_mut,
223 keelson_core::clause::Where
224);
225delegate_clause!(
226 ModelUpdate,
227 Table,
228 Update,
229 HasOrderBy,
230 order_by_mut,
231 keelson_core::clause::OrderBy
232);
233delegate_clause!(
234 ModelUpdate,
235 Table,
236 Update,
237 HasLimit,
238 limit_mut,
239 keelson_core::clause::Limit
240);
241delegate_clause!(
242 ModelUpdate,
243 Table,
244 Update,
245 HasSet,
246 set_mut,
247 keelson_core::clause::Set
248);
249delegate_clause!(
250 ModelUpdate,
251 Table,
252 Update,
253 HasReturning,
254 returning_mut,
255 keelson_core::clause::Returning
256);
257
258delegate_clause!(
260 ModelDelete,
261 Table,
262 Delete,
263 HasWith,
264 with_mut,
265 keelson_core::clause::With
266);
267delegate_clause!(
268 ModelDelete,
269 Table,
270 Delete,
271 HasTableRef,
272 table_ref_mut,
273 keelson_core::clause::TableRef
274);
275delegate_clause!(
276 ModelDelete,
277 Table,
278 Delete,
279 HasJoins,
280 joins_mut,
281 Vec<keelson_core::clause::Join>
282);
283delegate_clause!(
284 ModelDelete,
285 Table,
286 Delete,
287 HasWhere,
288 where_mut,
289 keelson_core::clause::Where
290);
291delegate_clause!(
292 ModelDelete,
293 Table,
294 Delete,
295 HasOrderBy,
296 order_by_mut,
297 keelson_core::clause::OrderBy
298);
299delegate_clause!(
300 ModelDelete,
301 Table,
302 Delete,
303 HasLimit,
304 limit_mut,
305 keelson_core::clause::Limit
306);
307delegate_clause!(
308 ModelDelete,
309 Table,
310 Delete,
311 HasReturning,
312 returning_mut,
313 keelson_core::clause::Returning
314);