1use crate::column::ColumnMarker;
4use crate::error::{Error, Result};
5use crate::expr::Expr;
6use crate::value::Value;
7
8#[derive(Debug, Clone, PartialEq)]
10pub struct Update {
11 pub table: String,
13 pub assignments: Vec<(ColumnMarker, Value)>,
15 pub filter: Option<Expr>,
17 pub returning: Vec<ColumnMarker>,
19}
20
21impl Update {
22 pub fn table(table: impl Into<String>) -> UpdateBuilder {
24 UpdateBuilder {
25 table: table.into(),
26 assignments: Vec::new(),
27 filter: None,
28 returning: Vec::new(),
29 }
30 }
31}
32
33#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
35pub struct UpdateCapacity {
36 pub assignments: usize,
38 pub returning: usize,
40}
41
42#[derive(Debug, Clone)]
44pub struct UpdateBuilder {
45 table: String,
46 assignments: Vec<(ColumnMarker, Value)>,
47 filter: Option<Expr>,
48 returning: Vec<ColumnMarker>,
49}
50
51impl UpdateBuilder {
52 #[must_use]
54 pub fn with_capacity(mut self, capacity: UpdateCapacity) -> Self {
55 self.assignments.reserve(capacity.assignments);
56 self.returning.reserve(capacity.returning);
57 self
58 }
59
60 #[must_use]
62 pub fn set(mut self, column: ColumnMarker, value: Value) -> Self {
63 self.assignments.push((column, value));
64 self
65 }
66
67 #[must_use]
69 pub fn assignments(mut self, assignments: Vec<(ColumnMarker, Value)>) -> Self {
70 self.assignments = assignments;
71 self
72 }
73
74 #[must_use]
76 pub fn filter(mut self, expr: Expr) -> Self {
77 self.filter = Some(expr);
78 self
79 }
80
81 #[must_use]
83 pub fn returning(mut self, columns: Vec<ColumnMarker>) -> Self {
84 self.returning = columns;
85 self
86 }
87
88 pub fn build(self) -> Result<Update> {
96 if self.table.is_empty() {
97 return Err(Error::MissingField("table".to_string()));
98 }
99
100 if self.assignments.is_empty() {
101 return Err(Error::MissingField("assignments".to_string()));
102 }
103
104 Ok(Update {
105 table: self.table,
106 assignments: self.assignments,
107 filter: self.filter,
108 returning: self.returning,
109 })
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn test_simple_update() {
119 let update = Update::table("users")
120 .set(
121 ColumnMarker::new("users", "email"),
122 Value::String("new@example.com".to_string()),
123 )
124 .build()
125 .unwrap();
126
127 assert_eq!(update.table, "users");
128 assert_eq!(update.assignments.len(), 1);
129 assert_eq!(update.assignments[0].0.name, "email");
130 assert!(update.filter.is_none());
131 assert!(update.returning.is_empty());
132 }
133
134 #[test]
135 fn test_multi_set_update() {
136 let update = Update::table("users")
137 .set(
138 ColumnMarker::new("users", "email"),
139 Value::String("new@example.com".to_string()),
140 )
141 .set(
142 ColumnMarker::new("users", "name"),
143 Value::String("Alice".to_string()),
144 )
145 .build()
146 .unwrap();
147
148 assert_eq!(update.assignments.len(), 2);
149 assert_eq!(update.assignments[0].0.name, "email");
150 assert_eq!(update.assignments[1].0.name, "name");
151 }
152
153 #[test]
154 fn test_update_with_filter() {
155 let update = Update::table("users")
156 .set(
157 ColumnMarker::new("users", "email"),
158 Value::String("new@example.com".to_string()),
159 )
160 .filter(Expr::column("id").eq(Expr::param(Value::I64(1))))
161 .build()
162 .unwrap();
163
164 assert!(update.filter.is_some());
165 }
166
167 #[test]
168 fn test_update_with_returning() {
169 let update = Update::table("users")
170 .set(
171 ColumnMarker::new("users", "email"),
172 Value::String("new@example.com".to_string()),
173 )
174 .returning(vec![
175 ColumnMarker::new("users", "id"),
176 ColumnMarker::new("users", "email"),
177 ])
178 .build()
179 .unwrap();
180
181 assert_eq!(update.returning.len(), 2);
182 assert_eq!(update.returning[0].name, "id");
183 assert_eq!(update.returning[1].name, "email");
184 }
185
186 #[test]
187 fn test_update_with_null() {
188 let update = Update::table("users")
189 .set(ColumnMarker::new("users", "name"), Value::Null)
190 .build()
191 .unwrap();
192
193 assert_eq!(update.assignments[0].1, Value::Null);
194 }
195
196 #[test]
197 fn test_missing_table() {
198 let result = Update::table("")
199 .set(
200 ColumnMarker::new("users", "email"),
201 Value::String("test".to_string()),
202 )
203 .build();
204
205 assert!(result.is_err());
206 }
207
208 #[test]
209 fn test_missing_assignments() {
210 let result = Update::table("users").build();
211
212 assert!(result.is_err());
213 }
214}