diesel/query_builder/insert_statement/
mod.rs

1mod column_list;
2mod insert_from_select;
3
4pub(crate) use self::column_list::ColumnList;
5pub(crate) use self::insert_from_select::InsertFromSelect;
6
7use std::any::*;
8use std::marker::PhantomData;
9
10use super::returning_clause::*;
11use backend::Backend;
12use expression::operators::Eq;
13use expression::{Expression, NonAggregate, SelectableExpression};
14use insertable::*;
15#[cfg(feature = "mysql")]
16use mysql::Mysql;
17use query_builder::*;
18#[cfg(feature = "sqlite")]
19use query_dsl::methods::ExecuteDsl;
20use query_dsl::RunQueryDsl;
21use query_source::{Column, Table};
22use result::QueryResult;
23#[cfg(feature = "sqlite")]
24use sqlite::{Sqlite, SqliteConnection};
25
26/// The structure returned by [`insert_into`].
27///
28/// The provided methods [`values`] and [`default_values`] will insert
29/// data into the targeted table.
30///
31/// [`insert_into`]: ../fn.insert_into.html
32/// [`values`]: #method.values
33/// [`default_values`]: #method.default_values
34#[derive(Debug, Clone, Copy)]
35#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
36pub struct IncompleteInsertStatement<T, Op> {
37    target: T,
38    operator: Op,
39}
40
41impl<T, Op> IncompleteInsertStatement<T, Op> {
42    pub(crate) fn new(target: T, operator: Op) -> Self {
43        IncompleteInsertStatement { target, operator }
44    }
45
46    /// Inserts `DEFAULT VALUES` into the targeted table.
47    ///
48    /// ```rust
49    /// # #[macro_use] extern crate diesel;
50    /// # include!("../../doctest_setup.rs");
51    /// #
52    /// # table! {
53    /// #     users (name) {
54    /// #         name -> Text,
55    /// #         hair_color -> Text,
56    /// #     }
57    /// # }
58    /// #
59    /// # fn main() {
60    /// #     run_test();
61    /// # }
62    /// #
63    /// # fn run_test() -> QueryResult<()> {
64    /// #     use diesel::insert_into;
65    /// #     use users::dsl::*;
66    /// #     let connection = connection_no_data();
67    /// connection.execute("CREATE TABLE users (
68    ///     name VARCHAR(255) NOT NULL DEFAULT 'Sean',
69    ///     hair_color VARCHAR(255) NOT NULL DEFAULT 'Green'
70    /// )")?;
71    ///
72    /// insert_into(users)
73    ///     .default_values()
74    ///     .execute(&connection)
75    ///     .unwrap();
76    /// let inserted_user = users.first(&connection)?;
77    /// let expected_data = (String::from("Sean"), String::from("Green"));
78    ///
79    /// assert_eq!(expected_data, inserted_user);
80    /// #     Ok(())
81    /// # }
82    /// ```
83    pub fn default_values(self) -> InsertStatement<T, DefaultValues, Op> {
84        static STATIC_DEFAULT_VALUES: &DefaultValues = &DefaultValues;
85        self.values(STATIC_DEFAULT_VALUES)
86    }
87
88    /// Inserts the given values into the table passed to `insert_into`.
89    ///
90    /// See the documentation of [`insert_into`] for
91    /// usage examples.
92    ///
93    /// This method can sometimes produce extremely opaque error messages due to
94    /// limitations of the Rust language. If you receive an error about
95    /// "overflow evaluating requirement" as a result of calling this method,
96    /// you may need an `&` in front of the argument to this method.
97    ///
98    /// [`insert_into`]: ../fn.insert_into.html
99    pub fn values<U>(self, records: U) -> InsertStatement<T, U::Values, Op>
100    where
101        U: Insertable<T>,
102    {
103        InsertStatement::new(
104            self.target,
105            records.values(),
106            self.operator,
107            NoReturningClause,
108        )
109    }
110}
111
112#[derive(Debug, Copy, Clone)]
113#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
114/// A fully constructed insert statement.
115///
116/// The parameters of this struct represent:
117///
118/// - `T`: The table we are inserting into
119/// - `U`: The data being inserted
120/// - `Op`: The operation being performed. The specific types used to represent
121///   this are private, but correspond to SQL such as `INSERT` or `REPLACE`.
122///   You can safely rely on the default type representing `INSERT`
123/// - `Ret`: The `RETURNING` clause of the query. The specific types used to
124///   represent this are private. You can safely rely on the default type
125///   representing a query without a `RETURNING` clause.
126pub struct InsertStatement<T, U, Op = Insert, Ret = NoReturningClause> {
127    operator: Op,
128    target: T,
129    records: U,
130    returning: Ret,
131}
132
133impl<T, U, Op, Ret> InsertStatement<T, U, Op, Ret> {
134    fn new(target: T, records: U, operator: Op, returning: Ret) -> Self {
135        InsertStatement {
136            operator: operator,
137            target: target,
138            records: records,
139            returning: returning,
140        }
141    }
142
143    #[cfg(feature = "postgres")]
144    pub(crate) fn replace_values<F, V>(self, f: F) -> InsertStatement<T, V, Op, Ret>
145    where
146        F: FnOnce(U) -> V,
147    {
148        InsertStatement::new(self.target, f(self.records), self.operator, self.returning)
149    }
150}
151
152impl<T, U, C, Op, Ret> InsertStatement<T, InsertFromSelect<U, C>, Op, Ret> {
153    /// Set the column list when inserting from a select statement
154    ///
155    /// See the documentation for [`insert_into`] for usage examples.
156    ///
157    /// [`insert_into`]: ../fn.insert_into.html
158    pub fn into_columns<C2>(
159        self,
160        columns: C2,
161    ) -> InsertStatement<T, InsertFromSelect<U, C2>, Op, Ret>
162    where
163        C2: ColumnList<Table = T> + Expression<SqlType = U::SqlType>,
164        U: Query,
165    {
166        InsertStatement::new(
167            self.target,
168            self.records.with_columns(columns),
169            self.operator,
170            self.returning,
171        )
172    }
173}
174
175impl<T, U, Op, Ret, DB> QueryFragment<DB> for InsertStatement<T, U, Op, Ret>
176where
177    DB: Backend,
178    T: Table,
179    T::FromClause: QueryFragment<DB>,
180    U: QueryFragment<DB> + CanInsertInSingleQuery<DB>,
181    Op: QueryFragment<DB>,
182    Ret: QueryFragment<DB>,
183{
184    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
185        out.unsafe_to_cache_prepared();
186
187        if self.records.rows_to_insert() == Some(0) {
188            out.push_sql("SELECT 1 FROM ");
189            self.target.from_clause().walk_ast(out.reborrow())?;
190            out.push_sql(" WHERE 1=0");
191            return Ok(());
192        }
193
194        self.operator.walk_ast(out.reborrow())?;
195        out.push_sql(" INTO ");
196        self.target.from_clause().walk_ast(out.reborrow())?;
197        out.push_sql(" ");
198        self.records.walk_ast(out.reborrow())?;
199        self.returning.walk_ast(out.reborrow())?;
200        Ok(())
201    }
202}
203
204#[cfg(feature = "sqlite")]
205impl<'a, T, U, Op> ExecuteDsl<SqliteConnection> for InsertStatement<T, &'a [U], Op>
206where
207    &'a U: Insertable<T>,
208    InsertStatement<T, <&'a U as Insertable<T>>::Values, Op>: QueryFragment<Sqlite>,
209    T: Copy,
210    Op: Copy,
211{
212    fn execute(query: Self, conn: &SqliteConnection) -> QueryResult<usize> {
213        use connection::Connection;
214        conn.transaction(|| {
215            let mut result = 0;
216            for record in query.records {
217                result += InsertStatement::new(
218                    query.target,
219                    record.values(),
220                    query.operator,
221                    query.returning,
222                )
223                .execute(conn)?;
224            }
225            Ok(result)
226        })
227    }
228}
229
230#[cfg(feature = "sqlite")]
231impl<'a, T, U, Op> ExecuteDsl<SqliteConnection> for InsertStatement<T, BatchInsert<'a, U, T>, Op>
232where
233    InsertStatement<T, &'a [U], Op>: ExecuteDsl<SqliteConnection>,
234{
235    fn execute(query: Self, conn: &SqliteConnection) -> QueryResult<usize> {
236        InsertStatement::new(
237            query.target,
238            query.records.records,
239            query.operator,
240            query.returning,
241        )
242        .execute(conn)
243    }
244}
245
246#[cfg(feature = "sqlite")]
247impl<T, U, Op> ExecuteDsl<SqliteConnection>
248    for InsertStatement<T, OwnedBatchInsert<ValuesClause<U, T>, T>, Op>
249where
250    InsertStatement<T, ValuesClause<U, T>, Op>: QueryFragment<Sqlite>,
251    T: Copy,
252    Op: Copy,
253{
254    fn execute(query: Self, conn: &SqliteConnection) -> QueryResult<usize> {
255        use connection::Connection;
256        conn.transaction(|| {
257            let mut result = 0;
258            for value in query.records.values {
259                result +=
260                    InsertStatement::new(query.target, value, query.operator, query.returning)
261                        .execute(conn)?;
262            }
263            Ok(result)
264        })
265    }
266}
267
268impl<T, U, Op, Ret> QueryId for InsertStatement<T, U, Op, Ret> {
269    type QueryId = ();
270
271    const HAS_STATIC_QUERY_ID: bool = false;
272}
273
274impl<T, U, Op> AsQuery for InsertStatement<T, U, Op, NoReturningClause>
275where
276    T: Table,
277    InsertStatement<T, U, Op, ReturningClause<T::AllColumns>>: Query,
278{
279    type SqlType = <Self::Query as Query>::SqlType;
280    type Query = InsertStatement<T, U, Op, ReturningClause<T::AllColumns>>;
281
282    fn as_query(self) -> Self::Query {
283        self.returning(T::all_columns())
284    }
285}
286
287impl<T, U, Op, Ret> Query for InsertStatement<T, U, Op, ReturningClause<Ret>>
288where
289    Ret: Expression + SelectableExpression<T> + NonAggregate,
290{
291    type SqlType = Ret::SqlType;
292}
293
294impl<T, U, Op, Ret, Conn> RunQueryDsl<Conn> for InsertStatement<T, U, Op, Ret> {}
295
296impl<T, U, Op> InsertStatement<T, U, Op> {
297    /// Specify what expression is returned after execution of the `insert`.
298    /// # Examples
299    ///
300    /// ### Inserting records:
301    ///
302    /// ```rust
303    /// # #[macro_use] extern crate diesel;
304    /// # include!("../../doctest_setup.rs");
305    /// #
306    /// # #[cfg(feature = "postgres")]
307    /// # fn main() {
308    /// #     use schema::users::dsl::*;
309    /// #     let connection = establish_connection();
310    /// let inserted_names = diesel::insert_into(users)
311    ///     .values(&vec![name.eq("Timmy"), name.eq("Jimmy")])
312    ///     .returning(name)
313    ///     .get_results(&connection);
314    /// assert_eq!(Ok(vec!["Timmy".to_string(), "Jimmy".to_string()]), inserted_names);
315    /// # }
316    /// # #[cfg(not(feature = "postgres"))]
317    /// # fn main() {}
318    /// ```
319    pub fn returning<E>(self, returns: E) -> InsertStatement<T, U, Op, ReturningClause<E>>
320    where
321        InsertStatement<T, U, Op, ReturningClause<E>>: Query,
322    {
323        InsertStatement::new(
324            self.target,
325            self.records,
326            self.operator,
327            ReturningClause(returns),
328        )
329    }
330}
331
332#[derive(Debug, Copy, Clone, QueryId)]
333#[doc(hidden)]
334pub struct Insert;
335
336impl<DB: Backend> QueryFragment<DB> for Insert {
337    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
338        out.push_sql("INSERT");
339        Ok(())
340    }
341}
342
343#[derive(Debug, Copy, Clone, QueryId)]
344#[doc(hidden)]
345pub struct InsertOrIgnore;
346
347#[cfg(feature = "sqlite")]
348impl QueryFragment<Sqlite> for InsertOrIgnore {
349    fn walk_ast(&self, mut out: AstPass<Sqlite>) -> QueryResult<()> {
350        out.push_sql("INSERT OR IGNORE");
351        Ok(())
352    }
353}
354
355#[cfg(feature = "mysql")]
356impl QueryFragment<Mysql> for InsertOrIgnore {
357    fn walk_ast(&self, mut out: AstPass<Mysql>) -> QueryResult<()> {
358        out.push_sql("INSERT IGNORE");
359        Ok(())
360    }
361}
362
363#[derive(Debug, Copy, Clone)]
364#[doc(hidden)]
365pub struct Replace;
366
367#[cfg(feature = "sqlite")]
368impl QueryFragment<Sqlite> for Replace {
369    fn walk_ast(&self, mut out: AstPass<Sqlite>) -> QueryResult<()> {
370        out.push_sql("REPLACE");
371        Ok(())
372    }
373}
374
375#[cfg(feature = "mysql")]
376impl QueryFragment<Mysql> for Replace {
377    fn walk_ast(&self, mut out: AstPass<Mysql>) -> QueryResult<()> {
378        out.push_sql("REPLACE");
379        Ok(())
380    }
381}
382
383/// Marker trait to indicate that no additional operations have been added
384/// to a record for insert.
385///
386/// This is used to prevent things like
387/// `.on_conflict_do_nothing().on_conflict_do_nothing()`
388/// from compiling.
389pub trait UndecoratedInsertRecord<Table> {}
390
391impl<'a, T, Tab> UndecoratedInsertRecord<Tab> for &'a T where
392    T: ?Sized + UndecoratedInsertRecord<Tab>
393{
394}
395
396impl<T, U> UndecoratedInsertRecord<T::Table> for ColumnInsertValue<T, U> where T: Column {}
397
398impl<T, Table> UndecoratedInsertRecord<Table> for [T] where T: UndecoratedInsertRecord<Table> {}
399
400impl<'a, T, Table> UndecoratedInsertRecord<Table> for BatchInsert<'a, T, Table> where
401    T: UndecoratedInsertRecord<Table>
402{
403}
404
405impl<T, Table> UndecoratedInsertRecord<Table> for OwnedBatchInsert<T, Table> where
406    T: UndecoratedInsertRecord<Table>
407{
408}
409
410impl<T, Table> UndecoratedInsertRecord<Table> for Vec<T> where [T]: UndecoratedInsertRecord<Table> {}
411
412impl<Lhs, Rhs> UndecoratedInsertRecord<Lhs::Table> for Eq<Lhs, Rhs> where Lhs: Column {}
413
414impl<Lhs, Rhs, Tab> UndecoratedInsertRecord<Tab> for Option<Eq<Lhs, Rhs>> where
415    Eq<Lhs, Rhs>: UndecoratedInsertRecord<Tab>
416{
417}
418
419impl<T, Table> UndecoratedInsertRecord<Table> for ValuesClause<T, Table> where
420    T: UndecoratedInsertRecord<Table>
421{
422}
423
424#[derive(Debug, Clone, Copy)]
425#[doc(hidden)]
426pub struct DefaultValues;
427
428impl<DB: Backend> CanInsertInSingleQuery<DB> for DefaultValues {
429    fn rows_to_insert(&self) -> Option<usize> {
430        Some(1)
431    }
432}
433
434impl<'a, Tab> Insertable<Tab> for &'a DefaultValues {
435    type Values = DefaultValues;
436
437    fn values(self) -> Self::Values {
438        *self
439    }
440}
441
442impl<DB> QueryFragment<DB> for DefaultValues
443where
444    DB: Backend + Any,
445{
446    #[cfg(feature = "mysql")]
447    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
448        // This can be less hacky once stabilization lands
449        if TypeId::of::<DB>() == TypeId::of::<::mysql::Mysql>() {
450            out.push_sql("() VALUES ()");
451        } else {
452            out.push_sql("DEFAULT VALUES");
453        }
454        Ok(())
455    }
456
457    #[cfg(not(feature = "mysql"))]
458    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
459        out.push_sql("DEFAULT VALUES");
460        Ok(())
461    }
462}
463
464#[doc(hidden)]
465#[derive(Debug, Clone, Copy)]
466pub struct ValuesClause<T, Tab> {
467    pub(crate) values: T,
468    _marker: PhantomData<Tab>,
469}
470
471impl<T: Default, Tab> Default for ValuesClause<T, Tab> {
472    fn default() -> Self {
473        Self::new(T::default())
474    }
475}
476
477impl<T, Tab> ValuesClause<T, Tab> {
478    pub(crate) fn new(values: T) -> Self {
479        Self {
480            values,
481            _marker: PhantomData,
482        }
483    }
484}
485
486impl<T, Tab, DB> CanInsertInSingleQuery<DB> for ValuesClause<T, Tab>
487where
488    DB: Backend,
489    T: CanInsertInSingleQuery<DB>,
490{
491    fn rows_to_insert(&self) -> Option<usize> {
492        self.values.rows_to_insert()
493    }
494}
495
496impl<T, Tab, DB> QueryFragment<DB> for ValuesClause<T, Tab>
497where
498    DB: Backend,
499    Tab: Table,
500    T: InsertValues<Tab, DB>,
501    DefaultValues: QueryFragment<DB>,
502{
503    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
504        if self.values.is_noop()? {
505            DefaultValues.walk_ast(out)?;
506        } else {
507            out.push_sql("(");
508            self.values.column_names(out.reborrow())?;
509            out.push_sql(") VALUES (");
510            self.values.walk_ast(out.reborrow())?;
511            out.push_sql(")");
512        }
513        Ok(())
514    }
515}