Skip to main content

ngb_sqlbuilder/
update.rs

1use crate::select::__where;
2use crate::{Clause, Condition, SqlClause, __and_nest, __condition, __or_nest, wrap, LOGIC_CONN_AND, LOGIC_CONN_NONE, LOGIC_CONN_OR};
3use tokio_postgres::types::ToSql;
4
5pub struct Update;
6pub struct UpdateSet;
7pub struct UpdateWhere;
8
9/// Begin `UPDATE` statement
10///
11/// # Arguments
12///
13/// * `table`: table name
14///
15/// returns: `Clause<Update>`
16///
17/// # Examples
18///
19/// ```
20/// use ngb_sqlbuilder::update;
21/// update("Table").set(&[
22///     ("Name", &name),
23///     ("Value", &value),
24///     ("Description", &description)
25/// ]).where_col("Id", eq(&id))
26/// // SQL: UPDATE "Table" SET "Name" = $1, "Value" = $2 WHERE "Id" = $3
27/// ```
28pub fn update<'q>(table: &str) -> Clause<'q, Update> {
29    let mut sql = String::from("UPDATE ");
30    sql.push_str(&wrap(table));
31    Clause::new(sql, vec![])
32}
33
34impl<'q> Clause<'q, Update> {
35    pub fn set(self, map: &[(&str, &'q (dyn ToSql + Sync + 'q))]) -> Clause<'q, UpdateSet> {
36        let (mut sql, mut params) = self.unwrap();
37        sql.push_str(" SET ");
38        let mut not_first = false;
39        for (k, v) in map {
40            if not_first {
41                sql.push_str(", ");
42            } else {
43                not_first = true;
44            }
45            sql.push_str(&wrap(k));
46            sql.push_str(" = $");
47            params.push(*v);
48        }
49        Clause::new(sql, params)
50    }
51}
52
53impl<'q> Clause<'q, UpdateSet> {
54    pub fn where_col(
55        self,
56        name: &str,
57        condition: Clause<'q, Condition>,
58    ) -> Clause<'q, UpdateWhere> {
59        __where(self, name, condition)
60    }
61
62    pub fn where_cond(self, condition: Clause<'q, Condition>) -> Clause<'q, UpdateWhere> {
63        __condition(LOGIC_CONN_NONE, self, condition)
64    }
65}
66
67impl<'q> Clause<'q, UpdateWhere> {
68    pub fn and(self, condition: Clause<'q, Condition>) -> Clause<'q, UpdateWhere> {
69        // __and_cond(self, condition)
70        __condition(LOGIC_CONN_AND, self, condition)
71    }
72    pub fn or(self, condition: Clause<'q, Condition>) -> Clause<'q, UpdateWhere> {
73        // __or_cond(self, condition)
74        __condition(LOGIC_CONN_OR, self, condition)
75    }
76    /// Add `AND` and a nested condition
77    ///
78    /// # Arguments
79    ///
80    /// * `condition`:
81    ///
82    /// returns: `Clause<UpdateWhere>`
83    ///
84    /// # Examples
85    ///
86    /// ```
87    /// where_col("t.Id", eq(&id)).and_wrap(col("t.Date").lt(&date).or_col("t.Status").gt(&status))
88    /// // SQL: ... WHERE t."Id" = $1 AND (t."Date" < $2 OR t."Status > $3)
89    /// ```
90    pub fn and_nest(self, condition: Clause<'q, Condition>) -> Clause<'q, UpdateWhere> {
91        __and_nest(self, condition)
92    }
93    /// Add `OR` and a nested condition
94    ///
95    /// # Arguments
96    ///
97    /// * `condition`:
98    ///
99    /// returns: `Clause<UpdateWhere>`
100    ///
101    /// # Examples
102    ///
103    /// ```
104    /// where_col("t.Id", eq(&id)).or_wrap(col("t.Date").lt(&date).or_col("t.Status").gt(&status))
105    /// // SQL: ... WHERE t."Id" = $1 OR (t."Date" < $2 OR t."Status > $3)
106    /// ```
107    pub fn or_nest(self, condition: Clause<'q, Condition>) -> Clause<'q, UpdateWhere> {
108        __or_nest(self, condition)
109    }
110}
111
112#[cfg(test)]
113mod test {
114    use super::*;
115    use crate::*;
116    #[test]
117    fn test_update() {
118        let name = String::from("test");
119        let (sql, params) = update("Table")
120            .set(&[("Value", &1), ("Name", &name)])
121            .where_col("Id", eq(&123))
122            .and_nest(col("Id").eq(&123).or_col("Test").neq(&name))
123            .build();
124        println!("{}", sql);
125        println!("{:?}", params);
126    }
127}