easy_sqlx_core/sql/builder/
update_builder.rs1use crate::sql::{
2 dialects::{
3 condition::{Condition, Where, WhereAppend},
4 schema::{self, schema::Schema},
5 },
6 schema::table::TableSchema,
7 utils::pair::Pair,
8};
9
10use super::builder::ExecuteBuilder;
11use sqlx::Database;
12
13#[derive(Debug)]
14pub struct UpdateBuilder<'a> {
15 table: TableSchema,
16 default_schema: &'a str,
17 columns: Vec<Pair>,
18 wh: Option<Where>,
19}
20
21impl<'a> UpdateBuilder<'a> {
22 pub fn new(table: TableSchema) -> Self {
23 Self {
24 table,
25 default_schema: "",
26 columns: vec![],
27 wh: None,
28 }
29 }
30
31 pub fn with_default_schema(mut self, schema: &'a str) -> Self {
32 self.default_schema = schema;
33 self
34 }
35
36 pub fn set(mut self, pair: Pair) -> Self {
37 self.columns.push(pair);
38 self
40 }
41}
42impl<'a> WhereAppend<Condition> for UpdateBuilder<'a> {
43 fn and(mut self, cond: Condition) -> Self {
44 if let Some(w) = self.wh {
45 self.wh = Some(w.and(cond));
46 } else {
47 self.wh = Some(Where::new(cond));
48 }
49 self
50 }
51
52 fn or(mut self, cond: Condition) -> Self {
53 if let Some(w) = self.wh {
54 self.wh = Some(w.or(cond));
55 } else {
56 self.wh = Some(Where::new(cond));
57 }
58 self
59 }
60}
61
62impl<'a> WhereAppend<Where> for UpdateBuilder<'a> {
63 fn and(mut self, wh: Where) -> Self {
64 if let Some(w) = self.wh {
65 self.wh = Some(w.and(wh));
66 } else {
67 self.wh = Some(wh);
68 }
69 self
70 }
71
72 fn or(mut self, wh: Where) -> Self {
73 if let Some(w) = self.wh {
74 self.wh = Some(w.or(wh));
75 } else {
76 self.wh = Some(wh);
77 }
78 self
79 }
80}
81
82#[cfg(feature = "postgres")]
83use sqlx::Postgres;
84
85impl<'a> ExecuteBuilder for UpdateBuilder<'a> {
86 #[cfg(feature = "postgres")]
87 type DB = Postgres;
88
89 async fn execute<C>(
90 &self,
91 conn: &mut C,
92 ) -> Result<<Self::DB as sqlx::Database>::QueryResult, sqlx::Error>
93 where
94 for<'e> &'e mut C: sqlx::Executor<'e, Database = Self::DB>,
95 {
96 let schema = schema::new(self.default_schema.to_string());
97
98 let cols: Vec<String> = self.columns.iter().map(|c| c.name.to_string()).collect();
99 let sql = schema.sql_update_columns(&self.table, &cols, self.wh.clone(), false);
100
101 let mut query: sqlx::query::Query<'_, Self::DB, <Self::DB as Database>::Arguments<'_>> =
102 sqlx::query::<Self::DB>(&sql);
103
104 for col in &self.columns {
105 query = col.value.bind_to_query(query);
106 }
107
108 if let Some(w) = &self.wh {
109 query = w.bind_to_query(query);
110 }
111
112 let result = query.execute(conn).await.map_err(|err| {
113 let sets = &self
114 .columns
115 .iter()
116 .map(|c| c.value.as_string())
117 .collect::<Vec<String>>()
118 .join(",");
119 let wh = if let Some(w) = &self.wh {
120 w.list_params()
121 } else {
122 "".to_string()
123 };
124 tracing::error!(
125 "easy-sqlx: {} set [{}] where [{}]; \n{:?}",
126 sql,
127 sets,
128 wh,
129 err
130 );
131 err
132 })?;
133
134 #[cfg(feature = "logsql")]
135 {
136 let sets = &self
137 .columns
138 .iter()
139 .map(|c| c.value.as_string())
140 .collect::<Vec<String>>()
141 .join(",");
142 let wh = if let Some(w) = &self.wh {
143 w.list_params()
144 } else {
145 "".to_string()
146 };
147 tracing::info!(
148 "easy-sqlx: {sql} set [{sets}] where [{wh}]; \nrows_affected: {}",
149 result.rows_affected()
150 );
151 }
152 Ok(result)
153 }
154
155 #[cfg(feature = "postgres")]
156 async fn execute_return<'e, 'c: 'e, C, O>(&self, executor: C) -> sqlx::Result<Vec<O>>
157 where
158 C: 'e + sqlx::Executor<'c, Database = Self::DB>,
159 O: 'e,
160 for<'r> O: sqlx::FromRow<'r, <Self::DB as Database>::Row>,
161 O: std::marker::Send,
162 O: Unpin,
163 {
164 let schema = schema::new(self.default_schema.to_string());
165
166 let cols: Vec<String> = self.columns.iter().map(|c| c.name.to_string()).collect();
167 let sql = schema.sql_update_columns(&self.table, &cols, self.wh.clone(), true);
168
169 let mut query = sqlx::query_as::<Self::DB, O>(&sql);
170
171 for col in &self.columns {
172 query = col.value.bind_to_query_as(query);
173 }
174
175 if let Some(w) = &self.wh {
176 query = w.bind_to_query_as(query);
177 }
178
179 let result = query.fetch_all(executor).await.map_err(|err| {
180 let sets = &self
181 .columns
182 .iter()
183 .map(|c| c.value.as_string())
184 .collect::<Vec<String>>()
185 .join(",");
186 let wh = if let Some(w) = &self.wh {
187 w.list_params()
188 } else {
189 "".to_string()
190 };
191 tracing::error!(
192 "easy-sqlx: {} set [{}] where [{}]; \n{:?}",
193 sql,
194 sets,
195 wh,
196 err
197 );
198 err
199 });
200
201 #[cfg(feature = "logsql")]
202 {
203 let sets = &self
204 .columns
205 .iter()
206 .map(|c| c.value.as_string())
207 .collect::<Vec<String>>()
208 .join(",");
209 let wh = if let Some(w) = &self.wh {
210 w.list_params()
211 } else {
212 "".to_string()
213 };
214 tracing::info!("easy-sqlx: {sql} set [{sets}] where [{wh}];");
215 }
216 result
217 }
218}