postgres_querybuilder/
update_builder.rs

1use crate::bucket::Bucket;
2use crate::prelude::*;
3use postgres_types::ToSql;
4
5pub struct UpdateBuilder {
6    with_queries: Vec<(String, String)>,
7    table: String,
8    fields: Vec<String>,
9    conditions: Vec<String>,
10    params: Bucket,
11}
12
13impl UpdateBuilder {
14    /// Create a new update builder for a given table
15    ///
16    /// # Examples
17    ///
18    /// ```
19    /// use postgres_querybuilder::UpdateBuilder;
20    /// use postgres_querybuilder::prelude::{QueryBuilder, QueryBuilderWithSet, QueryBuilderWithWhere};
21    ///
22    /// let user_password = "password".to_string();
23    /// let mut builder = UpdateBuilder::new("users");
24    /// builder.set("username", "rick".to_string());
25    /// builder.where_eq("id", 42);
26    ///
27    /// assert_eq!(builder.get_query(), "UPDATE users SET username = $1 WHERE id = $2");
28    /// ```
29    pub fn new(from: &str) -> Self {
30        UpdateBuilder {
31            with_queries: vec![],
32            table: from.into(),
33            fields: vec![],
34            conditions: vec![],
35            params: Bucket::new(),
36        }
37    }
38}
39
40impl UpdateBuilder {
41    fn with_queries_to_query(&self) -> Option<String> {
42        if self.with_queries.len() > 0 {
43            let result: Vec<String> = self
44                .with_queries
45                .iter()
46                .map(|item| format!("{} AS ({})", item.0, item.1))
47                .collect();
48            Some(format!("WITH {}", result.join(", ")))
49        } else {
50            None
51        }
52    }
53
54    fn from_to_query(&self) -> String {
55        format!("UPDATE {}", self.table)
56    }
57
58    fn set_to_query(&self) -> Option<String> {
59        if self.fields.len() > 0 {
60            let fields_query = self.fields.join(", ");
61            Some(format!("SET {}", fields_query))
62        } else {
63            None
64        }
65    }
66
67    fn where_to_query(&self) -> Option<String> {
68        if self.conditions.len() > 0 {
69            let where_query = self.conditions.join(" AND ");
70            Some(format!("WHERE {}", where_query))
71        } else {
72            None
73        }
74    }
75}
76
77impl QueryBuilder for UpdateBuilder {
78    fn add_param<T: 'static + ToSql + Sync + Clone>(&mut self, value: T) -> usize {
79        self.params.push(value)
80    }
81
82    fn get_query(&self) -> String {
83        let mut result: Vec<String> = vec![];
84        match self.with_queries_to_query() {
85            Some(value) => result.push(value),
86            None => (),
87        };
88        result.push(self.from_to_query());
89        match self.set_to_query() {
90            Some(value) => result.push(value),
91            None => (),
92        };
93        match self.where_to_query() {
94            Some(value) => result.push(value),
95            None => (),
96        };
97        result.join(" ")
98    }
99
100    fn get_ref_params(self) -> Vec<&'static (dyn ToSql + Sync)> {
101        self.params.get_refs()
102    }
103}
104
105impl QueryBuilderWithWhere for UpdateBuilder {
106    fn where_condition(&mut self, raw: &str) -> &mut Self {
107        self.conditions.push(raw.to_string());
108        self
109    }
110}
111
112impl QueryBuilderWithSet for UpdateBuilder {
113    fn set<T: 'static + ToSql + Sync + Clone>(&mut self, field: &str, value: T) -> &mut Self {
114        let index = self.params.push(value);
115        self.fields.push(format!("{} = ${}", field, index));
116        self
117    }
118
119    fn set_computed(&mut self, field: &str, value: &str) -> &mut Self {
120        self.fields.push(format!("{} = {}", field, value));
121        self
122    }
123}
124
125impl QueryBuilderWithQueries for UpdateBuilder {
126    fn with_query(&mut self, name: &str, query: &str) -> &mut Self {
127        self.with_queries.push((name.into(), query.into()));
128        self
129    }
130}
131
132#[cfg(test)]
133pub mod test {
134    use super::*;
135
136    #[test]
137    fn from_scratch() {
138        let builder = UpdateBuilder::new("publishers");
139        assert_eq!(builder.get_query(), "UPDATE publishers");
140    }
141
142    #[test]
143    fn with_fields_and_where() {
144        let mut builder = UpdateBuilder::new("publishers");
145        builder.where_eq("trololo", 42);
146        builder.set("id", 5);
147        assert_eq!(
148            builder.get_query(),
149            "UPDATE publishers SET id = $2 WHERE trololo = $1"
150        );
151    }
152
153    #[test]
154    fn with_computed_fields_and_where() {
155        let mut builder = UpdateBuilder::new("publishers");
156        builder.where_eq("trololo", 42);
157        builder.set("id", 5);
158        builder.set_computed("trololo", "md5(42)");
159        assert_eq!(
160            builder.get_query(),
161            "UPDATE publishers SET id = $2, trololo = md5(42) WHERE trololo = $1"
162        );
163    }
164}