halo_space/
delete.rs

1//! DeleteBuilder: build DELETE statements.
2
3use crate::args::Args;
4use crate::cond::{ArgsRef, Cond};
5use crate::cte::CTEBuilder;
6use crate::flavor::Flavor;
7use crate::injection::{Injection, InjectionMarker};
8use crate::macros::{IntoStrings, collect_into_strings};
9use crate::modifiers::{Arg, Builder};
10use crate::string_builder::StringBuilder;
11use crate::where_clause::{WhereClause, WhereClauseBuilder, WhereClauseRef};
12use std::cell::RefCell;
13use std::ops::Deref;
14use std::rc::Rc;
15
16const DELETE_MARKER_INIT: InjectionMarker = 0;
17const DELETE_MARKER_AFTER_WITH: InjectionMarker = 1;
18const DELETE_MARKER_AFTER_DELETE_FROM: InjectionMarker = 2;
19const DELETE_MARKER_AFTER_WHERE: InjectionMarker = 3;
20const DELETE_MARKER_AFTER_ORDER_BY: InjectionMarker = 4;
21const DELETE_MARKER_AFTER_LIMIT: InjectionMarker = 5;
22const DELETE_MARKER_AFTER_RETURNING: InjectionMarker = 6;
23
24#[derive(Debug)]
25pub struct DeleteBuilder {
26    args: ArgsRef,
27    cond: Cond,
28
29    tables: Vec<String>,
30
31    where_clause: Option<WhereClauseRef>,
32    where_var: Option<String>,
33    cte_var: Option<String>,
34    cte: Option<CTEBuilder>,
35
36    order_by_cols: Vec<String>,
37    order: Option<&'static str>,
38    limit_var: Option<String>,
39    returning: Vec<String>,
40
41    injection: Injection,
42    marker: InjectionMarker,
43}
44
45impl Deref for DeleteBuilder {
46    type Target = Cond;
47    fn deref(&self) -> &Self::Target {
48        &self.cond
49    }
50}
51
52impl Default for DeleteBuilder {
53    fn default() -> Self {
54        Self::new()
55    }
56}
57
58impl Clone for DeleteBuilder {
59    fn clone(&self) -> Self {
60        self.clone_builder()
61    }
62}
63
64impl DeleteBuilder {
65    pub fn new() -> Self {
66        let args = Rc::new(RefCell::new(Args::default()));
67        let cond = Cond::with_args(args.clone());
68        Self {
69            args,
70            cond,
71            tables: Vec::new(),
72            where_clause: None,
73            where_var: None,
74            order_by_cols: Vec::new(),
75            order: None,
76            limit_var: None,
77            returning: Vec::new(),
78            cte_var: None,
79            cte: None,
80            injection: Injection::new(),
81            marker: DELETE_MARKER_INIT,
82        }
83    }
84
85    pub fn set_flavor(&mut self, flavor: Flavor) -> Flavor {
86        let mut a = self.args.borrow_mut();
87        let old = a.flavor;
88        a.flavor = flavor;
89        old
90    }
91
92    pub fn flavor(&self) -> Flavor {
93        self.args.borrow().flavor
94    }
95
96    fn table_names(&self) -> Vec<String> {
97        let mut table_names = Vec::new();
98        if !self.tables.is_empty() {
99            table_names.extend(self.tables.clone());
100        }
101        if let Some(cte) = &self.cte {
102            table_names.extend(cte.table_names_for_from());
103        }
104        table_names
105    }
106
107    pub fn with(&mut self, cte: &CTEBuilder) -> &mut Self {
108        let cte_clone = cte.clone();
109        let ph = self.var(Arg::Builder(Box::new(cte.clone())));
110        self.cte = Some(cte_clone);
111        self.cte_var = Some(ph);
112        self.marker = DELETE_MARKER_AFTER_WITH;
113        self
114    }
115
116    pub fn where_clause(&self) -> Option<WhereClauseRef> {
117        self.where_clause.clone()
118    }
119
120    pub fn set_where_clause(&mut self, wc: Option<WhereClauseRef>) -> &mut Self {
121        match wc {
122            None => {
123                self.where_clause = None;
124                self.where_var = None;
125            }
126            Some(wc) => {
127                if let Some(ph) = &self.where_var {
128                    self.args.borrow_mut().replace(
129                        ph,
130                        Arg::Builder(Box::new(WhereClauseBuilder::new(wc.clone()))),
131                    );
132                } else {
133                    let ph = self.var(Arg::Builder(Box::new(WhereClauseBuilder::new(wc.clone()))));
134                    self.where_var = Some(ph);
135                }
136                self.where_clause = Some(wc);
137            }
138        }
139        self
140    }
141
142    pub fn clear_where_clause(&mut self) -> &mut Self {
143        self.set_where_clause(None)
144    }
145
146    pub fn clone_builder(&self) -> Self {
147        let old_args = self.args.borrow().clone();
148        let args = Rc::new(RefCell::new(old_args));
149        let cond = Cond::with_args(args.clone());
150
151        let mut cloned = Self {
152            args,
153            cond,
154            tables: self.tables.clone(),
155            where_clause: self.where_clause.clone(),
156            where_var: self.where_var.clone(),
157            cte_var: self.cte_var.clone(),
158            cte: self.cte.clone(),
159            order_by_cols: self.order_by_cols.clone(),
160            order: self.order,
161            limit_var: self.limit_var.clone(),
162            returning: self.returning.clone(),
163            injection: self.injection.clone(),
164            marker: self.marker,
165        };
166
167        if let (Some(wc), Some(ph)) = (&self.where_clause, &self.where_var) {
168            let new_wc = Rc::new(RefCell::new(wc.borrow().clone()));
169            cloned.where_clause = Some(new_wc.clone());
170            cloned
171                .args
172                .borrow_mut()
173                .replace(ph, Arg::Builder(Box::new(WhereClauseBuilder::new(new_wc))));
174        }
175
176        if let (Some(cte), Some(ph)) = (&self.cte, &self.cte_var) {
177            let cte_for_arg = cte.clone();
178            let cte_for_field = cte_for_arg.clone();
179            cloned.cte = Some(cte_for_field);
180            cloned
181                .args
182                .borrow_mut()
183                .replace(ph, Arg::Builder(Box::new(cte_for_arg)));
184        }
185
186        cloned
187    }
188
189    pub fn build(&self) -> (String, Vec<Arg>) {
190        Builder::build(self)
191    }
192
193    fn var(&self, v: impl Into<Arg>) -> String {
194        self.args.borrow_mut().add(v)
195    }
196
197    pub fn delete_from<T>(&mut self, tables: T) -> &mut Self
198    where
199        T: IntoStrings,
200    {
201        self.tables = collect_into_strings(tables);
202        self.marker = DELETE_MARKER_AFTER_DELETE_FROM;
203        self
204    }
205
206    pub fn where_<T>(&mut self, and_expr: T) -> &mut Self
207    where
208        T: IntoStrings,
209    {
210        let exprs = collect_into_strings(and_expr);
211        if exprs.is_empty() || exprs.iter().all(|s| s.is_empty()) {
212            return self;
213        }
214
215        if self.where_clause.is_none() {
216            let wc = WhereClause::new();
217            let ph = self.var(Arg::Builder(Box::new(WhereClauseBuilder::new(wc.clone()))));
218            self.where_clause = Some(wc);
219            self.where_var = Some(ph);
220        }
221
222        self.where_clause
223            .as_ref()
224            .unwrap()
225            .borrow_mut()
226            .add_where_expr(self.args.clone(), exprs);
227        self.marker = DELETE_MARKER_AFTER_WHERE;
228        self
229    }
230
231    pub fn add_where_expr<T>(&mut self, args: ArgsRef, exprs: T) -> &mut Self
232    where
233        T: IntoStrings,
234    {
235        let exprs = collect_into_strings(exprs);
236        if exprs.is_empty() || exprs.iter().all(|s| s.is_empty()) {
237            return self;
238        }
239
240        if self.where_clause.is_none() {
241            let wc = WhereClause::new();
242            let ph = self.var(Arg::Builder(Box::new(WhereClauseBuilder::new(wc.clone()))));
243            self.where_clause = Some(wc);
244            self.where_var = Some(ph);
245        }
246
247        self.where_clause
248            .as_ref()
249            .unwrap()
250            .borrow_mut()
251            .add_where_expr(args, exprs);
252        self.marker = DELETE_MARKER_AFTER_WHERE;
253        self
254    }
255
256    pub fn add_where_clause(&mut self, other: &WhereClause) -> &mut Self {
257        if self.where_clause.is_none() {
258            let wc = WhereClause::new();
259            let ph = self.var(Arg::Builder(Box::new(WhereClauseBuilder::new(wc.clone()))));
260            self.where_clause = Some(wc);
261            self.where_var = Some(ph);
262        }
263        self.where_clause
264            .as_ref()
265            .unwrap()
266            .borrow_mut()
267            .add_where_clause(other);
268        self
269    }
270
271    pub fn add_where_clause_ref(&mut self, other: &WhereClauseRef) -> &mut Self {
272        if self.where_clause.is_none() {
273            let wc = WhereClause::new();
274            let ph = self.var(Arg::Builder(Box::new(WhereClauseBuilder::new(wc.clone()))));
275            self.where_clause = Some(wc);
276            self.where_var = Some(ph);
277        }
278        self.where_clause
279            .as_ref()
280            .unwrap()
281            .borrow_mut()
282            .add_where_clause(&other.borrow());
283        self
284    }
285
286    pub fn order_by<T>(&mut self, cols: T) -> &mut Self
287    where
288        T: IntoStrings,
289    {
290        self.order_by_cols = collect_into_strings(cols);
291        self.marker = DELETE_MARKER_AFTER_ORDER_BY;
292        self
293    }
294
295    pub fn order_by_asc(&mut self, col: impl Into<String>) -> &mut Self {
296        self.order_by_cols.push(format!("{} ASC", col.into()));
297        self.marker = DELETE_MARKER_AFTER_ORDER_BY;
298        self
299    }
300
301    pub fn order_by_desc(&mut self, col: impl Into<String>) -> &mut Self {
302        self.order_by_cols.push(format!("{} DESC", col.into()));
303        self.marker = DELETE_MARKER_AFTER_ORDER_BY;
304        self
305    }
306
307    pub fn asc(&mut self) -> &mut Self {
308        self.order = Some("ASC");
309        self.marker = DELETE_MARKER_AFTER_ORDER_BY;
310        self
311    }
312
313    pub fn desc(&mut self) -> &mut Self {
314        self.order = Some("DESC");
315        self.marker = DELETE_MARKER_AFTER_ORDER_BY;
316        self
317    }
318
319    pub fn limit(&mut self, limit: i64) -> &mut Self {
320        if limit < 0 {
321            self.limit_var = None;
322            return self;
323        }
324        self.limit_var = Some(self.var(limit));
325        self.marker = DELETE_MARKER_AFTER_LIMIT;
326        self
327    }
328
329    pub fn returning<T>(&mut self, cols: T) -> &mut Self
330    where
331        T: IntoStrings,
332    {
333        self.returning = collect_into_strings(cols);
334        self.marker = DELETE_MARKER_AFTER_RETURNING;
335        self
336    }
337
338    pub fn sql(&mut self, sql: impl Into<String>) -> &mut Self {
339        self.injection.sql(self.marker, sql);
340        self
341    }
342}
343
344impl Builder for DeleteBuilder {
345    fn build_with_flavor(&self, flavor: Flavor, initial_arg: &[Arg]) -> (String, Vec<Arg>) {
346        let mut buf = StringBuilder::new();
347        write_injection(&mut buf, &self.injection, DELETE_MARKER_INIT);
348
349        if let Some(ph) = &self.cte_var {
350            buf.write_leading(ph);
351            write_injection(&mut buf, &self.injection, DELETE_MARKER_AFTER_WITH);
352        }
353
354        let table_names = self.table_names();
355        if !table_names.is_empty() {
356            buf.write_leading("DELETE FROM");
357            buf.write_str(" ");
358            buf.write_str(&table_names.join(", "));
359        }
360        write_injection(&mut buf, &self.injection, DELETE_MARKER_AFTER_DELETE_FROM);
361
362        if flavor == Flavor::SQLServer && !self.returning.is_empty() {
363            buf.write_leading("OUTPUT");
364            buf.write_str(" ");
365            let prefixed: Vec<String> = self
366                .returning
367                .iter()
368                .map(|c| format!("DELETED.{c}"))
369                .collect();
370            buf.write_str(&prefixed.join(", "));
371            write_injection(&mut buf, &self.injection, DELETE_MARKER_AFTER_RETURNING);
372        }
373
374        if let Some(ph) = &self.where_var {
375            buf.write_leading(ph);
376            write_injection(&mut buf, &self.injection, DELETE_MARKER_AFTER_WHERE);
377        }
378
379        if !self.order_by_cols.is_empty() {
380            buf.write_leading("ORDER BY");
381            buf.write_str(" ");
382            buf.write_str(&self.order_by_cols.join(", "));
383            if let Some(order) = self.order {
384                buf.write_str(" ");
385                buf.write_str(order);
386            }
387            write_injection(&mut buf, &self.injection, DELETE_MARKER_AFTER_ORDER_BY);
388        }
389
390        if let Some(lim) = &self.limit_var {
391            buf.write_leading("LIMIT");
392            buf.write_str(" ");
393            buf.write_str(lim);
394            write_injection(&mut buf, &self.injection, DELETE_MARKER_AFTER_LIMIT);
395        }
396
397        if (flavor == Flavor::PostgreSQL || flavor == Flavor::SQLite) && !self.returning.is_empty()
398        {
399            buf.write_leading("RETURNING");
400            buf.write_str(" ");
401            buf.write_str(&self.returning.join(", "));
402            write_injection(&mut buf, &self.injection, DELETE_MARKER_AFTER_RETURNING);
403        }
404
405        self.args
406            .borrow()
407            .compile_with_flavor(&buf.into_string(), flavor, initial_arg)
408    }
409
410    fn flavor(&self) -> Flavor {
411        self.flavor()
412    }
413}
414
415fn write_injection(buf: &mut StringBuilder, inj: &Injection, marker: InjectionMarker) {
416    let sqls = inj.at(marker);
417    if sqls.is_empty() {
418        return;
419    }
420    buf.write_leading("");
421    buf.write_str(&sqls.join(" "));
422}