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)]
35pub struct UpdateBuilder {
36 table: String,
37 assignments: Vec<(ColumnMarker, Value)>,
38 filter: Option<Expr>,
39 returning: Vec<ColumnMarker>,
40}
41
42impl UpdateBuilder {
43 #[must_use]
45 pub fn set(mut self, column: ColumnMarker, value: Value) -> Self {
46 self.assignments.push((column, value));
47 self
48 }
49
50 #[must_use]
52 pub fn filter(mut self, expr: Expr) -> Self {
53 self.filter = Some(expr);
54 self
55 }
56
57 #[must_use]
59 pub fn returning(mut self, columns: Vec<ColumnMarker>) -> Self {
60 self.returning = columns;
61 self
62 }
63
64 pub fn build(self) -> Result<Update> {
72 if self.table.is_empty() {
73 return Err(Error::MissingField("table".to_string()));
74 }
75
76 if self.assignments.is_empty() {
77 return Err(Error::MissingField("assignments".to_string()));
78 }
79
80 Ok(Update {
81 table: self.table,
82 assignments: self.assignments,
83 filter: self.filter,
84 returning: self.returning,
85 })
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn test_simple_update() {
95 let update = Update::table("users")
96 .set(
97 ColumnMarker::new("users", "email"),
98 Value::String("new@example.com".to_string()),
99 )
100 .build()
101 .unwrap();
102
103 assert_eq!(update.table, "users");
104 assert_eq!(update.assignments.len(), 1);
105 assert_eq!(update.assignments[0].0.name, "email");
106 assert!(update.filter.is_none());
107 assert!(update.returning.is_empty());
108 }
109
110 #[test]
111 fn test_multi_set_update() {
112 let update = Update::table("users")
113 .set(
114 ColumnMarker::new("users", "email"),
115 Value::String("new@example.com".to_string()),
116 )
117 .set(
118 ColumnMarker::new("users", "name"),
119 Value::String("Alice".to_string()),
120 )
121 .build()
122 .unwrap();
123
124 assert_eq!(update.assignments.len(), 2);
125 assert_eq!(update.assignments[0].0.name, "email");
126 assert_eq!(update.assignments[1].0.name, "name");
127 }
128
129 #[test]
130 fn test_update_with_filter() {
131 let update = Update::table("users")
132 .set(
133 ColumnMarker::new("users", "email"),
134 Value::String("new@example.com".to_string()),
135 )
136 .filter(Expr::column("id").eq(Expr::param(Value::I64(1))))
137 .build()
138 .unwrap();
139
140 assert!(update.filter.is_some());
141 }
142
143 #[test]
144 fn test_update_with_returning() {
145 let update = Update::table("users")
146 .set(
147 ColumnMarker::new("users", "email"),
148 Value::String("new@example.com".to_string()),
149 )
150 .returning(vec![
151 ColumnMarker::new("users", "id"),
152 ColumnMarker::new("users", "email"),
153 ])
154 .build()
155 .unwrap();
156
157 assert_eq!(update.returning.len(), 2);
158 assert_eq!(update.returning[0].name, "id");
159 assert_eq!(update.returning[1].name, "email");
160 }
161
162 #[test]
163 fn test_update_with_null() {
164 let update = Update::table("users")
165 .set(ColumnMarker::new("users", "name"), Value::Null)
166 .build()
167 .unwrap();
168
169 assert_eq!(update.assignments[0].1, Value::Null);
170 }
171
172 #[test]
173 fn test_missing_table() {
174 let result = Update::table("")
175 .set(
176 ColumnMarker::new("users", "email"),
177 Value::String("test".to_string()),
178 )
179 .build();
180
181 assert!(result.is_err());
182 }
183
184 #[test]
185 fn test_missing_assignments() {
186 let result = Update::table("users").build();
187
188 assert!(result.is_err());
189 }
190}