toolu_orm_query/
update.rs1use toolu_orm_core::dialect::Dialect;
4use toolu_orm_core::expr::Expr;
5use toolu_orm_core::query_column::Column;
6use toolu_orm_core::value::Value;
7
8use crate::where_clause::{append_where_for, cfg_single_backend, impl_filter};
9
10cfg_single_backend! {
11 use crate::exec_helpers::impl_execute;
12}
13
14enum SetClause {
17 Value { column: String, value: Value },
18 Expr { column: String, sql: String },
19}
20
21pub struct UpdateBuilder {
24 table: String,
25 sets: Vec<SetClause>,
26 filters: Vec<Expr>,
27}
28
29impl_filter!(UpdateBuilder);
30
31impl UpdateBuilder {
32 pub fn new(table: &str) -> Self {
33 Self {
34 table: table.to_owned(),
35 sets: Vec::new(),
36 filters: Vec::new(),
37 }
38 }
39
40 pub fn set<T>(mut self, col: &Column<T>, val: impl Into<Value>) -> Self {
41 self.sets.push(SetClause::Value {
42 column: col.name.to_owned(),
43 value: val.into(),
44 });
45 self
46 }
47
48 pub fn set_expr<T>(mut self, col: &Column<T>, expr: &str) -> Self {
49 self.sets.push(SetClause::Expr {
50 column: col.name.to_owned(),
51 sql: expr.to_owned(),
52 });
53 self
54 }
55
56 pub fn to_sql_for(&self, dialect: Dialect) -> (String, Vec<Value>) {
57 let mut sql = String::new();
58 let mut params: Vec<Value> = Vec::new();
59
60 let mut set_params: Vec<Value> = Vec::new();
61 for clause in &self.sets {
62 if let SetClause::Value { value, .. } = clause {
63 set_params.push(value.clone());
64 }
65 }
66
67 sql.push_str(&format!(r#"UPDATE "{}""#, self.table));
68 sql.push_str(" SET ");
69
70 let mut set_idx = 1usize;
71 let set_parts: Vec<String> = self
72 .sets
73 .iter()
74 .map(|clause| match clause {
75 SetClause::Value { column, .. } => {
76 let part = format!(r#""{column}" = {}"#, dialect.param(set_idx));
77 set_idx += 1;
78 part
79 },
80 SetClause::Expr {
81 column,
82 sql: expr_sql,
83 } => {
84 format!(r#""{column}" = {expr_sql}"#)
85 },
86 })
87 .collect();
88
89 sql.push_str(&set_parts.join(", "));
90 params.extend(set_params);
91
92 append_where_for(&self.filters, &mut sql, &mut params, dialect);
93
94 (sql, params)
95 }
96
97 pub fn to_sql(&self) -> (String, Vec<Value>) {
98 self.to_sql_for(Dialect::CURRENT)
99 }
100}
101
102cfg_single_backend! {
103 impl_execute!(UpdateBuilder, "UPDATE");
104}