quaint_forked/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 quaint::{ast::*, visitor::{Visitor, Sqlite}};
40    /// # fn main() -> Result<(), quaint::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 quaint::{ast::*, visitor::{Visitor, Mssql}};
56    /// # use indoc::indoc;
57    /// # fn main() -> Result<(), quaint::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 = if insert.values.is_empty() {
103            Expression::from(Row::new())
104        } else {
105            Expression::from(insert.values)
106        };
107
108        Insert {
109            table: insert.table,
110            columns: insert.columns,
111            values,
112            on_conflict: None,
113            returning: None,
114            comment: None,
115        }
116    }
117}
118
119impl<'a> From<MultiRowInsert<'a>> for Insert<'a> {
120    fn from(insert: MultiRowInsert<'a>) -> Self {
121        let values = Expression::from(Values::new(insert.values));
122
123        Insert {
124            table: insert.table,
125            columns: insert.columns,
126            values,
127            on_conflict: None,
128            returning: None,
129            comment: None,
130        }
131    }
132}
133
134impl<'a> From<SingleRowInsert<'a>> for Query<'a> {
135    fn from(insert: SingleRowInsert<'a>) -> Query<'a> {
136        Query::from(Insert::from(insert))
137    }
138}
139
140impl<'a> From<MultiRowInsert<'a>> for Query<'a> {
141    fn from(insert: MultiRowInsert<'a>) -> Query<'a> {
142        Query::from(Insert::from(insert))
143    }
144}
145
146impl<'a> Insert<'a> {
147    /// Creates a new single row `INSERT` statement for the given table.
148    ///
149    /// ```rust
150    /// # use quaint::{ast::*, visitor::{Visitor, Sqlite}};
151    /// # fn main() -> Result<(), quaint::error::Error> {
152    /// let query = Insert::single_into("users");
153    /// let (sql, _) = Sqlite::build(query)?;
154    ///
155    /// assert_eq!("INSERT INTO `users` DEFAULT VALUES", sql);
156    /// # Ok(())
157    /// # }
158    /// ```
159    pub fn single_into<T>(table: T) -> SingleRowInsert<'a>
160    where
161        T: Into<Table<'a>>,
162    {
163        SingleRowInsert {
164            table: Some(table.into()),
165            columns: Vec::new(),
166            values: Row::new(),
167        }
168    }
169
170    pub fn single() -> SingleRowInsert<'a> {
171        SingleRowInsert {
172            table: None,
173            columns: Vec::new(),
174            values: Row::new(),
175        }
176    }
177
178    /// Creates a new multi row `INSERT` statement for the given table.
179    pub fn multi_into<T, K, I>(table: T, columns: I) -> MultiRowInsert<'a>
180    where
181        T: Into<Table<'a>>,
182        K: Into<Column<'a>>,
183        I: IntoIterator<Item = K>,
184    {
185        MultiRowInsert {
186            table: Some(table.into()),
187            columns: columns.into_iter().map(|c| c.into()).collect(),
188            values: Vec::new(),
189        }
190    }
191
192    pub fn multi<K, I>(columns: I) -> MultiRowInsert<'a>
193    where
194        K: Into<Column<'a>>,
195        I: IntoIterator<Item = K>,
196    {
197        MultiRowInsert {
198            table: None,
199            columns: columns.into_iter().map(|c| c.into()).collect(),
200            values: Vec::new(),
201        }
202    }
203
204    pub fn expression_into<T, I, K, E>(table: T, columns: I, expression: E) -> Self
205    where
206        T: Into<Table<'a>>,
207        I: IntoIterator<Item = K>,
208        K: Into<Column<'a>>,
209        E: Into<Expression<'a>>,
210    {
211        Insert {
212            table: Some(table.into()),
213            columns: columns.into_iter().map(|c| c.into()).collect(),
214            values: expression.into(),
215            on_conflict: None,
216            returning: None,
217            comment: None,
218        }
219    }
220
221    /// Sets the conflict resolution strategy.
222    pub fn on_conflict(mut self, on_conflict: OnConflict<'a>) -> Self {
223        self.on_conflict = Some(on_conflict);
224        self
225    }
226
227    /// Adds a comment to the insert.
228    ///
229    /// ```rust
230    /// # use quaint::{ast::*, visitor::{Visitor, Sqlite}};
231    /// # fn main() -> Result<(), quaint::error::Error> {
232    /// let query = Insert::single_into("users");
233    /// let insert = Insert::from(query).comment("trace_id='5bd66ef5095369c7b0d1f8f4bd33716a', parent_id='c532cb4098ac3dd2'");
234    /// let (sql, _) = Sqlite::build(insert)?;
235    ///
236    /// assert_eq!("INSERT INTO `users` DEFAULT VALUES; /* trace_id='5bd66ef5095369c7b0d1f8f4bd33716a', parent_id='c532cb4098ac3dd2' */", sql);
237    /// # Ok(())
238    /// # }
239    /// ```
240    pub fn comment<C: Into<Cow<'a, str>>>(mut self, comment: C) -> Self {
241        self.comment = Some(comment.into());
242        self
243    }
244
245    /// Sets the returned columns.
246    ///
247    /// ```rust
248    /// # use quaint::{ast::*, visitor::{Visitor, Postgres}};
249    /// # fn main() -> Result<(), quaint::error::Error> {
250    /// let query = Insert::single_into("users");
251    /// let insert = Insert::from(query).returning(vec!["id"]);
252    /// let (sql, _) = Postgres::build(insert)?;
253    ///
254    /// assert_eq!("INSERT INTO \"users\" DEFAULT VALUES RETURNING \"id\"", sql);
255    /// # Ok(())
256    /// # }
257    /// ```
258    #[cfg(any(feature = "postgresql", feature = "mssql", feature = "sqlite"))]
259    pub fn returning<K, I>(mut self, columns: I) -> Self
260    where
261        K: Into<Column<'a>>,
262        I: IntoIterator<Item = K>,
263    {
264        self.returning = Some(columns.into_iter().map(|k| k.into()).collect());
265        self
266    }
267}
268
269impl<'a> SingleRowInsert<'a> {
270    /// Adds a new value to the `INSERT` statement
271    ///
272    /// ```rust
273    /// # use quaint::{ast::*, visitor::{Visitor, Sqlite}};
274    /// # fn main() -> Result<(), quaint::error::Error> {
275    /// let query = Insert::single_into("users").value("foo", 10);
276    /// let (sql, params) = Sqlite::build(query)?;
277    ///
278    /// assert_eq!("INSERT INTO `users` (`foo`) VALUES (?)", sql);
279    /// assert_eq!(vec![Value::from(10)], params);
280    /// # Ok(())
281    /// # }
282    /// ```
283    pub fn value<K, V>(mut self, key: K, val: V) -> SingleRowInsert<'a>
284    where
285        K: Into<Column<'a>>,
286        V: Into<Expression<'a>>,
287    {
288        self.columns.push(key.into());
289        self.values.push(val.into());
290
291        self
292    }
293
294    /// Convert into a common `Insert` statement.
295    pub fn build(self) -> Insert<'a> {
296        Insert::from(self)
297    }
298}
299
300impl<'a> MultiRowInsert<'a> {
301    /// Adds a new row to be inserted.
302    ///
303    /// ```rust
304    /// # use quaint::{ast::*, visitor::{Visitor, Sqlite}};
305    /// # fn main() -> Result<(), quaint::error::Error> {
306    /// let query = Insert::multi_into("users", vec!["foo"])
307    ///     .values(vec![1])
308    ///     .values(vec![2]);
309    ///
310    /// let (sql, params) = Sqlite::build(query)?;
311    ///
312    /// assert_eq!("INSERT INTO `users` (`foo`) VALUES (?), (?)", sql);
313    ///
314    /// assert_eq!(
315    ///     vec![
316    ///         Value::from(1),
317    ///         Value::from(2),
318    ///     ], params);
319    /// # Ok(())
320    /// # }
321    /// ```
322    pub fn values<V>(mut self, values: V) -> Self
323    where
324        V: Into<Row<'a>>,
325    {
326        self.values.push(values.into());
327        self
328    }
329
330    /// Convert into a common `Insert` statement.
331    pub fn build(self) -> Insert<'a> {
332        Insert::from(self)
333    }
334}