mik_sql/builder/
delete.rs1use crate::dialect::{Dialect, Postgres, Sqlite};
4use crate::validate::assert_valid_sql_identifier;
5
6use super::filter::{build_condition_impl, build_filter_expr_impl};
7use super::types::{Filter, FilterExpr, Operator, QueryResult, Value};
8
9#[derive(Debug)]
11#[must_use = "builder does nothing until .build() is called"]
12pub struct DeleteBuilder<D: Dialect> {
13 dialect: D,
14 table: String,
15 filters: Vec<Filter>,
16 filter_expr: Option<FilterExpr>,
17 returning: Vec<String>,
18}
19
20impl<D: Dialect> DeleteBuilder<D> {
21 pub fn new(dialect: D, table: impl Into<String>) -> Self {
27 let table = table.into();
28 assert_valid_sql_identifier(&table, "table");
29 Self {
30 dialect,
31 table,
32 filters: Vec::new(),
33 filter_expr: None,
34 returning: Vec::new(),
35 }
36 }
37
38 pub fn filter(mut self, field: impl Into<String>, op: Operator, value: Value) -> Self {
44 let field = field.into();
45 assert_valid_sql_identifier(&field, "filter field");
46 self.filters.push(Filter { field, op, value });
47 self
48 }
49
50 pub fn filter_expr(mut self, expr: FilterExpr) -> Self {
53 self.filter_expr = Some(expr);
54 self
55 }
56
57 pub fn returning(mut self, columns: &[&str]) -> Self {
63 for col in columns {
64 assert_valid_sql_identifier(col, "returning column");
65 }
66 self.returning = columns.iter().map(|s| (*s).to_string()).collect();
67 self
68 }
69
70 pub fn build(self) -> QueryResult {
72 let mut sql = String::new();
73 let mut params = Vec::new();
74 let mut param_idx = 1usize;
75
76 sql.push_str(&format!("DELETE FROM {}", self.table));
78
79 let has_filter_expr = self.filter_expr.is_some();
81 let has_simple_filters = !self.filters.is_empty();
82
83 if has_filter_expr || has_simple_filters {
84 sql.push_str(" WHERE ");
85 let mut all_conditions = Vec::new();
86
87 if let Some(ref expr) = self.filter_expr {
88 let (condition, new_params, new_idx) =
89 build_filter_expr_impl(&self.dialect, expr, param_idx);
90 all_conditions.push(condition);
91 params.extend(new_params);
92 param_idx = new_idx;
93 }
94
95 for filter in &self.filters {
96 let (condition, new_params, new_idx) =
97 build_condition_impl(&self.dialect, filter, param_idx);
98 all_conditions.push(condition);
99 params.extend(new_params);
100 param_idx = new_idx;
101 }
102
103 sql.push_str(&all_conditions.join(" AND "));
104 }
105
106 if !self.returning.is_empty() {
108 sql.push_str(&format!(" RETURNING {}", self.returning.join(", ")));
109 }
110
111 QueryResult { sql, params }
112 }
113}
114
115pub fn delete(table: impl Into<String>) -> DeleteBuilder<Postgres> {
117 DeleteBuilder::new(Postgres, table)
118}
119
120pub fn delete_sqlite(table: impl Into<String>) -> DeleteBuilder<Sqlite> {
122 DeleteBuilder::new(Sqlite, table)
123}