1use crate::column::ColumnMarker;
4use crate::error::{Error, Result};
5use crate::value::Value;
6
7#[derive(Debug, Clone, PartialEq)]
9pub struct Insert {
10 pub table: String,
12 pub columns: Vec<ColumnMarker>,
14 pub values: Vec<Vec<Value>>,
16 pub returning: Vec<ColumnMarker>,
18}
19
20impl Insert {
21 pub fn into_table(table: impl Into<String>) -> InsertBuilder {
23 InsertBuilder {
24 table: table.into(),
25 columns: Vec::new(),
26 values: Vec::new(),
27 returning: Vec::new(),
28 }
29 }
30}
31
32#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
34pub struct InsertCapacity {
35 pub columns: usize,
37 pub rows: usize,
39 pub returning: usize,
41}
42
43#[derive(Debug, Clone)]
45pub struct InsertBuilder {
46 table: String,
47 columns: Vec<ColumnMarker>,
48 values: Vec<Vec<Value>>,
49 returning: Vec<ColumnMarker>,
50}
51
52impl InsertBuilder {
53 #[must_use]
55 pub fn with_capacity(mut self, capacity: InsertCapacity) -> Self {
56 self.columns.reserve(capacity.columns);
57 self.values.reserve(capacity.rows);
58 self.returning.reserve(capacity.returning);
59 self
60 }
61
62 #[must_use]
64 pub fn columns(mut self, columns: Vec<ColumnMarker>) -> Self {
65 self.columns = columns;
66 self
67 }
68
69 #[must_use]
71 pub fn column(mut self, column: ColumnMarker) -> Self {
72 self.columns.push(column);
73 self
74 }
75
76 #[must_use]
81 pub fn values(mut self, row: Vec<Value>) -> Self {
82 self.values.push(row);
83 self
84 }
85
86 #[must_use]
88 pub fn rows(mut self, rows: Vec<Vec<Value>>) -> Self {
89 self.values = rows;
90 self
91 }
92
93 #[must_use]
95 pub fn returning(mut self, columns: Vec<ColumnMarker>) -> Self {
96 self.returning = columns;
97 self
98 }
99
100 pub fn build(self) -> Result<Insert> {
110 if self.table.is_empty() {
111 return Err(Error::MissingField("table".to_string()));
112 }
113
114 if self.columns.is_empty() {
115 return Err(Error::MissingField("columns".to_string()));
116 }
117
118 if self.values.is_empty() {
119 return Err(Error::MissingField("values".to_string()));
120 }
121
122 let col_count = self.columns.len();
123 for (i, row) in self.values.iter().enumerate() {
124 if row.len() != col_count {
125 return Err(Error::InvalidQuery(format!(
126 "row {} has {} values but {} columns were specified",
127 i,
128 row.len(),
129 col_count
130 )));
131 }
132 }
133
134 Ok(Insert {
135 table: self.table,
136 columns: self.columns,
137 values: self.values,
138 returning: self.returning,
139 })
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146
147 #[test]
148 fn test_simple_insert() {
149 let insert = Insert::into_table("users")
150 .column(ColumnMarker::new("users", "email"))
151 .values(vec![Value::String("alice@example.com".to_string())])
152 .build()
153 .unwrap();
154
155 assert_eq!(insert.table, "users");
156 assert_eq!(insert.columns.len(), 1);
157 assert_eq!(insert.columns[0].name, "email");
158 assert_eq!(insert.values.len(), 1);
159 assert!(insert.returning.is_empty());
160 }
161
162 #[test]
163 fn test_multi_column_insert() {
164 let insert = Insert::into_table("users")
165 .columns(vec![
166 ColumnMarker::new("users", "email"),
167 ColumnMarker::new("users", "name"),
168 ])
169 .values(vec![
170 Value::String("alice@example.com".to_string()),
171 Value::String("Alice".to_string()),
172 ])
173 .build()
174 .unwrap();
175
176 assert_eq!(insert.columns.len(), 2);
177 assert_eq!(insert.values.len(), 1);
178 assert_eq!(insert.values[0].len(), 2);
179 }
180
181 #[test]
182 fn test_batch_insert() {
183 let insert = Insert::into_table("users")
184 .column(ColumnMarker::new("users", "email"))
185 .values(vec![Value::String("alice@example.com".to_string())])
186 .values(vec![Value::String("bob@example.com".to_string())])
187 .values(vec![Value::String("charlie@example.com".to_string())])
188 .build()
189 .unwrap();
190
191 assert_eq!(insert.values.len(), 3);
192 }
193
194 #[test]
195 fn test_insert_with_returning() {
196 let insert = Insert::into_table("users")
197 .column(ColumnMarker::new("users", "email"))
198 .values(vec![Value::String("alice@example.com".to_string())])
199 .returning(vec![
200 ColumnMarker::new("users", "id"),
201 ColumnMarker::new("users", "email"),
202 ])
203 .build()
204 .unwrap();
205
206 assert_eq!(insert.returning.len(), 2);
207 assert_eq!(insert.returning[0].name, "id");
208 assert_eq!(insert.returning[1].name, "email");
209 }
210
211 #[test]
212 fn test_missing_table() {
213 let result = Insert::into_table("")
214 .column(ColumnMarker::new("users", "email"))
215 .values(vec![Value::String("test".to_string())])
216 .build();
217
218 assert!(result.is_err());
219 }
220
221 #[test]
222 fn test_missing_columns() {
223 let result = Insert::into_table("users")
224 .values(vec![Value::String("test".to_string())])
225 .build();
226
227 assert!(result.is_err());
228 }
229
230 #[test]
231 fn test_missing_values() {
232 let result = Insert::into_table("users")
233 .column(ColumnMarker::new("users", "email"))
234 .build();
235
236 assert!(result.is_err());
237 }
238
239 #[test]
240 fn test_mismatched_values_count() {
241 let result = Insert::into_table("users")
242 .columns(vec![
243 ColumnMarker::new("users", "email"),
244 ColumnMarker::new("users", "name"),
245 ])
246 .values(vec![Value::String("alice@example.com".to_string())])
247 .build();
248
249 assert!(result.is_err());
250 let err = result.unwrap_err();
251 assert!(matches!(err, Error::InvalidQuery(_)));
252 }
253}