halo/
delete.rs

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