1use std::borrow::Cow;
2
3use anyhow::anyhow;
4
5use crate::ast::{Column, Expression, Query, Row, Table, Update, Values};
6
7#[derive(Clone, Debug, PartialEq)]
9pub struct Insert<'a> {
10 pub(crate) table: Option<Table<'a>>,
11 pub(crate) columns: Vec<Column<'a>>,
12 pub(crate) values: Expression<'a>,
13 pub(crate) on_conflict: Option<OnConflict<'a>>,
14 pub(crate) returning: Option<Vec<Column<'a>>>,
15 pub(crate) comment: Option<Cow<'a, str>>,
16}
17
18#[derive(Clone, Debug, PartialEq)]
20pub struct SingleRowInsert<'a> {
21 pub(crate) table: Option<Table<'a>>,
22 pub(crate) columns: Vec<Column<'a>>,
23 pub(crate) values: Row<'a>,
24}
25
26#[derive(Clone, Debug, PartialEq)]
28pub struct MultiRowInsert<'a> {
29 pub(crate) table: Option<Table<'a>>,
30 pub(crate) columns: Vec<Column<'a>>,
31 pub(crate) values: Vec<Row<'a>>,
32}
33
34#[allow(clippy::large_enum_variant)]
36#[derive(Clone, Debug, PartialEq)]
37pub enum OnConflict<'a> {
38 DoNothing,
40 Update(Update<'a>, Vec<Column<'a>>),
42}
43
44impl<'a> From<Insert<'a>> for Query<'a> {
45 fn from(insert: Insert<'a>) -> Self {
46 Query::Insert(Box::new(insert))
47 }
48}
49
50impl<'a> From<SingleRowInsert<'a>> for Insert<'a> {
51 fn from(insert: SingleRowInsert<'a>) -> Self {
52 let values = if insert.values.is_empty() {
53 Expression::from(Row::new())
54 } else {
55 Expression::from(insert.values)
56 };
57
58 Insert {
59 table: insert.table,
60 columns: insert.columns,
61 values,
62 on_conflict: None,
63 returning: None,
64 comment: None,
65 }
66 }
67}
68
69impl<'a> From<MultiRowInsert<'a>> for Insert<'a> {
70 fn from(insert: MultiRowInsert<'a>) -> Self {
71 let values = Expression::from(Values::new(insert.values));
72
73 Insert {
74 table: insert.table,
75 columns: insert.columns,
76 values,
77 on_conflict: None,
78 returning: None,
79 comment: None,
80 }
81 }
82}
83
84impl<'a> From<SingleRowInsert<'a>> for Query<'a> {
85 fn from(insert: SingleRowInsert<'a>) -> Query<'a> {
86 Query::from(Insert::from(insert))
87 }
88}
89
90impl<'a> From<MultiRowInsert<'a>> for Query<'a> {
91 fn from(insert: MultiRowInsert<'a>) -> Query<'a> {
92 Query::from(Insert::from(insert))
93 }
94}
95
96impl<'a> Insert<'a> {
97 pub fn single_into<T>(table: T) -> SingleRowInsert<'a>
109 where
110 T: Into<Table<'a>>,
111 {
112 SingleRowInsert {
113 table: Some(table.into()),
114 columns: Vec::new(),
115 values: Row::new(),
116 }
117 }
118
119 pub fn single() -> SingleRowInsert<'a> {
120 SingleRowInsert {
121 table: None,
122 columns: Vec::new(),
123 values: Row::new(),
124 }
125 }
126
127 pub fn multi_into<T, K, I>(table: T, columns: I) -> MultiRowInsert<'a>
129 where
130 T: Into<Table<'a>>,
131 K: Into<Column<'a>>,
132 I: IntoIterator<Item = K>,
133 {
134 MultiRowInsert {
135 table: Some(table.into()),
136 columns: columns.into_iter().map(|c| c.into()).collect(),
137 values: Vec::new(),
138 }
139 }
140
141 pub fn multi<K, I>(columns: I) -> MultiRowInsert<'a>
142 where
143 K: Into<Column<'a>>,
144 I: IntoIterator<Item = K>,
145 {
146 MultiRowInsert {
147 table: None,
148 columns: columns.into_iter().map(|c| c.into()).collect(),
149 values: Vec::new(),
150 }
151 }
152
153 pub fn expression_into<T, I, K, E>(table: T, columns: I, expression: E) -> Self
154 where
155 T: Into<Table<'a>>,
156 I: IntoIterator<Item = K>,
157 K: Into<Column<'a>>,
158 E: Into<Expression<'a>>,
159 {
160 Insert {
161 table: Some(table.into()),
162 columns: columns.into_iter().map(|c| c.into()).collect(),
163 values: expression.into(),
164 on_conflict: None,
165 returning: None,
166 comment: None,
167 }
168 }
169
170 pub fn on_conflict(&mut self, on_conflict: OnConflict<'a>) {
172 self.on_conflict = Some(on_conflict);
173 }
174
175 pub fn comment<C: Into<Cow<'a, str>>>(&mut self, comment: C) {
177 self.comment = Some(comment.into());
178 }
179
180 #[cfg(any(feature = "postgresql", feature = "mssql", feature = "sqlite"))]
182 #[cfg_attr(
183 feature = "docs",
184 doc(cfg(any(feature = "postgresql", feature = "mssql", feature = "sqlite")))
185 )]
186 pub fn returning<K, I>(&mut self, columns: I)
187 where
188 K: Into<Column<'a>>,
189 I: IntoIterator<Item = K>,
190 {
191 self.returning = Some(columns.into_iter().map(|k| k.into()).collect());
192 }
193}
194
195impl<'a> SingleRowInsert<'a> {
196 pub fn value<K, V>(&mut self, key: K, val: V)
211 where
212 K: Into<Column<'a>>,
213 V: Into<Expression<'a>>,
214 {
215 self.columns.push(key.into());
216 self.values.push(val.into());
217 }
218
219 pub fn merge(self, other: SingleRowInsert<'a>) -> anyhow::Result<MultiRowInsert<'a>> {
223 if self.table != other.table {
224 return Err(anyhow!("Merging inserts must be on the same table.",));
225 }
226
227 if self.columns != other.columns {
228 return Err(anyhow!("All insert items must have the same columns."));
229 }
230
231 Ok(MultiRowInsert {
232 table: self.table,
233 columns: self.columns,
234 values: vec![self.values, other.values],
235 })
236 }
237
238 pub fn build(self) -> Insert<'a> {
240 Insert::from(self)
241 }
242}
243
244impl<'a> MultiRowInsert<'a> {
245 pub fn values<V>(&mut self, values: V)
267 where
268 V: Into<Row<'a>>,
269 {
270 self.values.push(values.into());
271 }
272
273 pub fn extend(&mut self, other: SingleRowInsert<'a>) -> anyhow::Result<()> {
277 if self.table != other.table {
278 return Err(anyhow!("Merging inserts must be on the same table.",));
279 }
280
281 if self.columns != other.columns {
282 return Err(anyhow!("All insert items must have the same columns."));
283 }
284
285 self.values.push(other.values);
286
287 Ok(())
288 }
289
290 pub fn build(self) -> Insert<'a> {
292 Insert::from(self)
293 }
294}