postgres_querybuilder/
update_builder.rs1use 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 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}