sqlint/ast/insert.rs
1use crate::ast::*;
2use std::borrow::Cow;
3
4/// A builder for an `INSERT` statement.
5#[derive(Clone, Debug, PartialEq)]
6pub struct Insert<'a> {
7 pub(crate) table: Option<Table<'a>>,
8 pub(crate) columns: Vec<Column<'a>>,
9 pub(crate) values: Expression<'a>,
10 pub(crate) on_conflict: Option<OnConflict<'a>>,
11 pub(crate) returning: Option<Vec<Column<'a>>>,
12 pub(crate) comment: Option<Cow<'a, str>>,
13}
14
15/// A builder for an `INSERT` statement for a single row.
16#[derive(Clone, Debug, PartialEq)]
17pub struct SingleRowInsert<'a> {
18 pub(crate) table: Option<Table<'a>>,
19 pub(crate) columns: Vec<Column<'a>>,
20 pub(crate) values: Row<'a>,
21}
22
23/// A builder for an `INSERT` statement for multiple rows.
24#[derive(Clone, Debug, PartialEq)]
25pub struct MultiRowInsert<'a> {
26 pub(crate) table: Option<Table<'a>>,
27 pub(crate) columns: Vec<Column<'a>>,
28 pub(crate) values: Vec<Row<'a>>,
29}
30
31/// `INSERT` conflict resolution strategies.
32#[allow(clippy::large_enum_variant)]
33#[derive(Clone, Debug, PartialEq)]
34pub enum OnConflict<'a> {
35 /// When a row already exists, do nothing. Works with PostgreSQL, MySQL or
36 /// SQLite without schema information.
37 ///
38 /// ```rust
39 /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
40 /// # fn main() -> Result<(), sqlint::error::Error> {
41 /// let query: Insert = Insert::single_into("users").into();
42 /// let (sql, _) = Sqlite::build(query.on_conflict(OnConflict::DoNothing))?;
43 /// assert_eq!("INSERT OR IGNORE INTO `users` DEFAULT VALUES", sql);
44 /// # Ok(())
45 /// # }
46 /// ```
47 ///
48 /// With Microsoft SQL server not supporting `IGNORE` in the `INSERT`
49 /// statement, the `INSERT` is converted to a `MERGE` statement. For it to work
50 /// in a correct way, the table should know all unique indices of the actual table.
51 ///
52 /// In this example our `users` table holds one unique index for the `id` column.
53 ///
54 /// ```rust
55 /// # use sqlint::{ast::*, visitor::{Visitor, Mssql}};
56 /// # use indoc::indoc;
57 /// # fn main() -> Result<(), sqlint::error::Error> {
58 /// let id = Column::from("id").table("users");
59 /// let table = Table::from("users").add_unique_index(id.clone());
60 /// let query: Insert = Insert::single_into(table).value(id, 1).into();
61 /// let (sql, _) = Mssql::build(query.on_conflict(OnConflict::DoNothing))?;
62 ///
63 /// let expected_sql = indoc!(
64 /// "
65 /// MERGE INTO [users]
66 /// USING (SELECT @P1 AS [id]) AS [dual] ([id])
67 /// ON [dual].[id] = [users].[id]
68 /// WHEN NOT MATCHED THEN
69 /// INSERT ([id]) VALUES ([dual].[id]);
70 /// "
71 /// );
72 ///
73 /// assert_eq!(expected_sql.replace('\n', " ").trim(), sql);
74 /// # Ok(())
75 /// # }
76 /// ```
77 ///
78 /// If the `INSERT` statement misses a value for a unique column that does
79 /// not have default value set, the visitor will raise a panic. For compound
80 /// unique indices, the `add_unique_index` takes a vector as a parameter.
81 ///
82 /// If the [column has a default value], it should be added to the `Column`
83 /// definition to allow inserting missing unique values with the `Insert`
84 /// statement. If default is set to [`DefaultValue::Generated`], the value
85 /// is considered to be always unique and not added to the join.
86 ///
87 /// [`DefaultValue::Generated`]: enum.DefaultValue.html#variant.Generated
88 /// [column has a default value]: struct.Column.html#method.default
89 DoNothing,
90 /// ON CONFLICT UPDATE is supported for Sqlite and Postgres
91 Update(Update<'a>, Vec<Column<'a>>),
92}
93
94impl<'a> From<Insert<'a>> for Query<'a> {
95 fn from(insert: Insert<'a>) -> Self {
96 Query::Insert(Box::new(insert))
97 }
98}
99
100impl<'a> From<SingleRowInsert<'a>> for Insert<'a> {
101 fn from(insert: SingleRowInsert<'a>) -> Self {
102 let values =
103 if insert.values.is_empty() { Expression::from(Row::new()) } else { Expression::from(insert.values) };
104
105 Insert {
106 table: insert.table,
107 columns: insert.columns,
108 values,
109 on_conflict: None,
110 returning: None,
111 comment: None,
112 }
113 }
114}
115
116impl<'a> From<MultiRowInsert<'a>> for Insert<'a> {
117 fn from(insert: MultiRowInsert<'a>) -> Self {
118 let values = Expression::from(Values::new(insert.values));
119
120 Insert {
121 table: insert.table,
122 columns: insert.columns,
123 values,
124 on_conflict: None,
125 returning: None,
126 comment: None,
127 }
128 }
129}
130
131impl<'a> From<SingleRowInsert<'a>> for Query<'a> {
132 fn from(insert: SingleRowInsert<'a>) -> Query<'a> {
133 Query::from(Insert::from(insert))
134 }
135}
136
137impl<'a> From<MultiRowInsert<'a>> for Query<'a> {
138 fn from(insert: MultiRowInsert<'a>) -> Query<'a> {
139 Query::from(Insert::from(insert))
140 }
141}
142
143impl<'a> Insert<'a> {
144 /// Creates a new single row `INSERT` statement for the given table.
145 ///
146 /// ```rust
147 /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
148 /// # fn main() -> Result<(), sqlint::error::Error> {
149 /// let query = Insert::single_into("users");
150 /// let (sql, _) = Sqlite::build(query)?;
151 ///
152 /// assert_eq!("INSERT INTO `users` DEFAULT VALUES", sql);
153 /// # Ok(())
154 /// # }
155 /// ```
156 pub fn single_into<T>(table: T) -> SingleRowInsert<'a>
157 where
158 T: Into<Table<'a>>,
159 {
160 SingleRowInsert { table: Some(table.into()), columns: Vec::new(), values: Row::new() }
161 }
162
163 pub fn single() -> SingleRowInsert<'a> {
164 SingleRowInsert { table: None, columns: Vec::new(), values: Row::new() }
165 }
166
167 /// Creates a new multi row `INSERT` statement for the given table.
168 pub fn multi_into<T, K, I>(table: T, columns: I) -> MultiRowInsert<'a>
169 where
170 T: Into<Table<'a>>,
171 K: Into<Column<'a>>,
172 I: IntoIterator<Item = K>,
173 {
174 MultiRowInsert {
175 table: Some(table.into()),
176 columns: columns.into_iter().map(|c| c.into()).collect(),
177 values: Vec::new(),
178 }
179 }
180
181 pub fn multi<K, I>(columns: I) -> MultiRowInsert<'a>
182 where
183 K: Into<Column<'a>>,
184 I: IntoIterator<Item = K>,
185 {
186 MultiRowInsert { table: None, columns: columns.into_iter().map(|c| c.into()).collect(), values: Vec::new() }
187 }
188
189 pub fn expression_into<T, I, K, E>(table: T, columns: I, expression: E) -> Self
190 where
191 T: Into<Table<'a>>,
192 I: IntoIterator<Item = K>,
193 K: Into<Column<'a>>,
194 E: Into<Expression<'a>>,
195 {
196 Insert {
197 table: Some(table.into()),
198 columns: columns.into_iter().map(|c| c.into()).collect(),
199 values: expression.into(),
200 on_conflict: None,
201 returning: None,
202 comment: None,
203 }
204 }
205
206 /// Sets the conflict resolution strategy.
207 pub fn on_conflict(mut self, on_conflict: OnConflict<'a>) -> Self {
208 self.on_conflict = Some(on_conflict);
209 self
210 }
211
212 /// Adds a comment to the insert.
213 ///
214 /// ```rust
215 /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
216 /// # fn main() -> Result<(), sqlint::error::Error> {
217 /// let query = Insert::single_into("users");
218 /// let insert = Insert::from(query).comment("trace_id='5bd66ef5095369c7b0d1f8f4bd33716a', parent_id='c532cb4098ac3dd2'");
219 /// let (sql, _) = Sqlite::build(insert)?;
220 ///
221 /// assert_eq!("INSERT INTO `users` DEFAULT VALUES; /* trace_id='5bd66ef5095369c7b0d1f8f4bd33716a', parent_id='c532cb4098ac3dd2' */", sql);
222 /// # Ok(())
223 /// # }
224 /// ```
225 pub fn comment<C: Into<Cow<'a, str>>>(mut self, comment: C) -> Self {
226 self.comment = Some(comment.into());
227 self
228 }
229
230 /// Sets the returned columns.
231 ///
232 /// ```rust
233 /// # use sqlint::{ast::*, visitor::{Visitor, Postgres}};
234 /// # fn main() -> Result<(), sqlint::error::Error> {
235 /// let query = Insert::single_into("users");
236 /// let insert = Insert::from(query).returning(vec!["id"]);
237 /// let (sql, _) = Postgres::build(insert)?;
238 ///
239 /// assert_eq!("INSERT INTO \"users\" DEFAULT VALUES RETURNING \"id\"", sql);
240 /// # Ok(())
241 /// # }
242 /// ```
243 #[cfg(any(feature = "postgresql", feature = "mssql", feature = "sqlite"))]
244 #[cfg_attr(feature = "docs", doc(cfg(any(feature = "postgresql", feature = "mssql", feature = "sqlite"))))]
245 pub fn returning<K, I>(mut self, columns: I) -> Self
246 where
247 K: Into<Column<'a>>,
248 I: IntoIterator<Item = K>,
249 {
250 self.returning = Some(columns.into_iter().map(|k| k.into()).collect());
251 self
252 }
253}
254
255impl<'a> SingleRowInsert<'a> {
256 /// Adds a new value to the `INSERT` statement
257 ///
258 /// ```rust
259 /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
260 /// # fn main() -> Result<(), sqlint::error::Error> {
261 /// let query = Insert::single_into("users").value("foo", 10);
262 /// let (sql, params) = Sqlite::build(query)?;
263 ///
264 /// assert_eq!("INSERT INTO `users` (`foo`) VALUES (?)", sql);
265 /// assert_eq!(vec![Value::from(10)], params);
266 /// # Ok(())
267 /// # }
268 /// ```
269 pub fn value<K, V>(mut self, key: K, val: V) -> SingleRowInsert<'a>
270 where
271 K: Into<Column<'a>>,
272 V: Into<Expression<'a>>,
273 {
274 self.columns.push(key.into());
275 self.values.push(val.into());
276
277 self
278 }
279
280 /// Convert into a common `Insert` statement.
281 pub fn build(self) -> Insert<'a> {
282 Insert::from(self)
283 }
284}
285
286impl<'a> MultiRowInsert<'a> {
287 /// Adds a new row to be inserted.
288 ///
289 /// ```rust
290 /// # use sqlint::{ast::*, visitor::{Visitor, Sqlite}};
291 /// # fn main() -> Result<(), sqlint::error::Error> {
292 /// let query = Insert::multi_into("users", vec!["foo"])
293 /// .values(vec![1])
294 /// .values(vec![2]);
295 ///
296 /// let (sql, params) = Sqlite::build(query)?;
297 ///
298 /// assert_eq!("INSERT INTO `users` (`foo`) VALUES (?), (?)", sql);
299 ///
300 /// assert_eq!(
301 /// vec![
302 /// Value::from(1),
303 /// Value::from(2),
304 /// ], params);
305 /// # Ok(())
306 /// # }
307 /// ```
308 pub fn values<V>(mut self, values: V) -> Self
309 where
310 V: Into<Row<'a>>,
311 {
312 self.values.push(values.into());
313 self
314 }
315
316 /// Convert into a common `Insert` statement.
317 pub fn build(self) -> Insert<'a> {
318 Insert::from(self)
319 }
320}