easy_sqlx_core/sql/builder/
update_builder.rs

1use 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.r#where()
39        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}