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)]
34pub struct InsertBuilder {
35 table: String,
36 columns: Vec<ColumnMarker>,
37 values: Vec<Vec<Value>>,
38 returning: Vec<ColumnMarker>,
39}
40
41impl InsertBuilder {
42 #[must_use]
44 pub fn columns(mut self, columns: Vec<ColumnMarker>) -> Self {
45 self.columns = columns;
46 self
47 }
48
49 #[must_use]
51 pub fn column(mut self, column: ColumnMarker) -> Self {
52 self.columns.push(column);
53 self
54 }
55
56 #[must_use]
61 pub fn values(mut self, row: Vec<Value>) -> Self {
62 self.values.push(row);
63 self
64 }
65
66 #[must_use]
68 pub fn returning(mut self, columns: Vec<ColumnMarker>) -> Self {
69 self.returning = columns;
70 self
71 }
72
73 pub fn build(self) -> Result<Insert> {
83 if self.table.is_empty() {
84 return Err(Error::MissingField("table".to_string()));
85 }
86
87 if self.columns.is_empty() {
88 return Err(Error::MissingField("columns".to_string()));
89 }
90
91 if self.values.is_empty() {
92 return Err(Error::MissingField("values".to_string()));
93 }
94
95 let col_count = self.columns.len();
96 for (i, row) in self.values.iter().enumerate() {
97 if row.len() != col_count {
98 return Err(Error::InvalidQuery(format!(
99 "row {} has {} values but {} columns were specified",
100 i,
101 row.len(),
102 col_count
103 )));
104 }
105 }
106
107 Ok(Insert {
108 table: self.table,
109 columns: self.columns,
110 values: self.values,
111 returning: self.returning,
112 })
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn test_simple_insert() {
122 let insert = Insert::into_table("users")
123 .column(ColumnMarker::new("users", "email"))
124 .values(vec![Value::String("alice@example.com".to_string())])
125 .build()
126 .unwrap();
127
128 assert_eq!(insert.table, "users");
129 assert_eq!(insert.columns.len(), 1);
130 assert_eq!(insert.columns[0].name, "email");
131 assert_eq!(insert.values.len(), 1);
132 assert!(insert.returning.is_empty());
133 }
134
135 #[test]
136 fn test_multi_column_insert() {
137 let insert = Insert::into_table("users")
138 .columns(vec![
139 ColumnMarker::new("users", "email"),
140 ColumnMarker::new("users", "name"),
141 ])
142 .values(vec![
143 Value::String("alice@example.com".to_string()),
144 Value::String("Alice".to_string()),
145 ])
146 .build()
147 .unwrap();
148
149 assert_eq!(insert.columns.len(), 2);
150 assert_eq!(insert.values.len(), 1);
151 assert_eq!(insert.values[0].len(), 2);
152 }
153
154 #[test]
155 fn test_batch_insert() {
156 let insert = Insert::into_table("users")
157 .column(ColumnMarker::new("users", "email"))
158 .values(vec![Value::String("alice@example.com".to_string())])
159 .values(vec![Value::String("bob@example.com".to_string())])
160 .values(vec![Value::String("charlie@example.com".to_string())])
161 .build()
162 .unwrap();
163
164 assert_eq!(insert.values.len(), 3);
165 }
166
167 #[test]
168 fn test_insert_with_returning() {
169 let insert = Insert::into_table("users")
170 .column(ColumnMarker::new("users", "email"))
171 .values(vec![Value::String("alice@example.com".to_string())])
172 .returning(vec![
173 ColumnMarker::new("users", "id"),
174 ColumnMarker::new("users", "email"),
175 ])
176 .build()
177 .unwrap();
178
179 assert_eq!(insert.returning.len(), 2);
180 assert_eq!(insert.returning[0].name, "id");
181 assert_eq!(insert.returning[1].name, "email");
182 }
183
184 #[test]
185 fn test_missing_table() {
186 let result = Insert::into_table("")
187 .column(ColumnMarker::new("users", "email"))
188 .values(vec![Value::String("test".to_string())])
189 .build();
190
191 assert!(result.is_err());
192 }
193
194 #[test]
195 fn test_missing_columns() {
196 let result = Insert::into_table("users")
197 .values(vec![Value::String("test".to_string())])
198 .build();
199
200 assert!(result.is_err());
201 }
202
203 #[test]
204 fn test_missing_values() {
205 let result = Insert::into_table("users")
206 .column(ColumnMarker::new("users", "email"))
207 .build();
208
209 assert!(result.is_err());
210 }
211
212 #[test]
213 fn test_mismatched_values_count() {
214 let result = Insert::into_table("users")
215 .columns(vec![
216 ColumnMarker::new("users", "email"),
217 ColumnMarker::new("users", "name"),
218 ])
219 .values(vec![Value::String("alice@example.com".to_string())])
220 .build();
221
222 assert!(result.is_err());
223 let err = result.unwrap_err();
224 assert!(matches!(err, Error::InvalidQuery(_)));
225 }
226}