Skip to main content

diesel/
insertable.rs

1use crate::backend::{Backend, DieselReserveSpecialization, SqlDialect, sql_dialect};
2use crate::expression::grouped::Grouped;
3use crate::expression::{AppearsOnTable, Expression};
4use crate::query_builder::{
5    AstPass, BatchInsert, InsertStatement, NoFromClause, QueryFragment, QueryId,
6    UndecoratedInsertRecord, ValuesClause,
7};
8use crate::query_source::{Column, Table};
9use crate::result::QueryResult;
10use alloc::boxed::Box;
11use alloc::vec::Vec;
12use core::marker::PhantomData;
13
14/// Represents that a structure can be used to insert a new row into the
15/// database. This is automatically implemented for `&[T]` and `&Vec<T>` for
16/// inserting more than one record.
17///
18/// This trait can be [derived](derive@Insertable)
19pub trait Insertable<T> {
20    /// The `VALUES` clause to insert these records
21    ///
22    /// The types used here are generally internal to Diesel.
23    /// Implementations of this trait should use the `Values`
24    /// type of other `Insertable` types.
25    /// For example `<diesel::dsl::Eq<column, &str> as Insertable<table>>::Values`.
26    type Values;
27
28    /// Construct `Self::Values`
29    ///
30    /// Implementations of this trait typically call `.values`
31    /// on other `Insertable` types.
32    fn values(self) -> Self::Values;
33
34    /// Insert `self` into a given table.
35    ///
36    /// `foo.insert_into(table)` is identical to `insert_into(table).values(foo)`.
37    /// However, when inserting from a select statement,
38    /// this form is generally preferred.
39    ///
40    /// # Example
41    ///
42    /// ```rust
43    /// # include!("doctest_setup.rs");
44    /// #
45    /// # fn main() {
46    /// #     run_test().unwrap();
47    /// # }
48    /// #
49    /// # fn run_test() -> QueryResult<()> {
50    /// #     use schema::{posts, users};
51    /// #     let conn = &mut establish_connection();
52    /// #     diesel::delete(posts::table).execute(conn)?;
53    /// users::table
54    ///     .select((users::name.concat("'s First Post"), users::id))
55    ///     .insert_into(posts::table)
56    ///     .into_columns((posts::title, posts::user_id))
57    ///     .execute(conn)?;
58    ///
59    /// let inserted_posts = posts::table.select(posts::title).load::<String>(conn)?;
60    /// let expected = vec!["Sean's First Post", "Tess's First Post"];
61    /// assert_eq!(expected, inserted_posts);
62    /// #     Ok(())
63    /// # }
64    /// ```
65    fn insert_into(self, table: T) -> InsertStatement<T, Self::Values>
66    where
67        T: Table,
68        Self: Sized,
69    {
70        crate::insert_into(table).values(self)
71    }
72}
73
74#[doc(inline)]
75pub use diesel_derives::Insertable;
76
77pub trait CanInsertInSingleQuery<DB: Backend> {
78    /// How many rows will this query insert?
79    ///
80    /// This function should only return `None` when the query is valid on all
81    /// backends, regardless of how many rows get inserted.
82    fn rows_to_insert(&self) -> Option<usize>;
83}
84
85impl<T, DB> CanInsertInSingleQuery<DB> for &T
86where
87    T: ?Sized + CanInsertInSingleQuery<DB>,
88    DB: Backend,
89{
90    fn rows_to_insert(&self) -> Option<usize> {
91        (*self).rows_to_insert()
92    }
93}
94
95impl<T, U, DB> CanInsertInSingleQuery<DB> for ColumnInsertValue<T, U>
96where
97    DB: Backend,
98{
99    fn rows_to_insert(&self) -> Option<usize> {
100        Some(1)
101    }
102}
103
104impl<V, DB> CanInsertInSingleQuery<DB> for DefaultableColumnInsertValue<V>
105where
106    DB: Backend,
107    V: CanInsertInSingleQuery<DB>,
108{
109    fn rows_to_insert(&self) -> Option<usize> {
110        Some(1)
111    }
112}
113
114pub trait InsertValues<DB: Backend, T: Table>: QueryFragment<DB> {
115    fn column_names(&self, out: AstPass<'_, '_, DB>) -> QueryResult<()>;
116}
117
118#[derive(#[automatically_derived]
impl<Col: ::core::fmt::Debug, Expr: ::core::fmt::Debug> ::core::fmt::Debug for
    ColumnInsertValue<Col, Expr> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "ColumnInsertValue", "expr", &self.expr, "p", &&self.p)
    }
}Debug, #[automatically_derived]
impl<Col: ::core::marker::Copy, Expr: ::core::marker::Copy>
    ::core::marker::Copy for ColumnInsertValue<Col, Expr> {
}Copy, #[automatically_derived]
impl<Col: ::core::clone::Clone, Expr: ::core::clone::Clone>
    ::core::clone::Clone for ColumnInsertValue<Col, Expr> {
    #[inline]
    fn clone(&self) -> ColumnInsertValue<Col, Expr> {
        ColumnInsertValue {
            expr: ::core::clone::Clone::clone(&self.expr),
            p: ::core::clone::Clone::clone(&self.p),
        }
    }
}Clone, const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl<Col: diesel::query_builder::QueryId,
            Expr: diesel::query_builder::QueryId>
            diesel::query_builder::QueryId for ColumnInsertValue<Col, Expr> {
            type QueryId =
                ColumnInsertValue<<Col as
                diesel::query_builder::QueryId>::QueryId,
                <Expr as diesel::query_builder::QueryId>::QueryId>;
            const HAS_STATIC_QUERY_ID: bool =
                <Col as diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID
                        &&
                        <Expr as
                            diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                    true;
            const IS_WINDOW_FUNCTION: bool =
                <Col as diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION ||
                        <Expr as diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION
                    || false;
        }
    };QueryId)]
119#[doc(hidden)]
120pub struct ColumnInsertValue<Col, Expr> {
121    pub(crate) expr: Expr,
122    p: PhantomData<Col>,
123}
124
125impl<Col, Expr> ColumnInsertValue<Col, Expr> {
126    pub(crate) fn new(expr: Expr) -> Self {
127        Self {
128            expr,
129            p: PhantomData,
130        }
131    }
132}
133
134#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for
    DefaultableColumnInsertValue<T> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            DefaultableColumnInsertValue::Expression(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Expression", &__self_0),
            DefaultableColumnInsertValue::Default =>
                ::core::fmt::Formatter::write_str(f, "Default"),
        }
    }
}Debug, #[automatically_derived]
impl<T> ::core::default::Default for DefaultableColumnInsertValue<T> {
    #[inline]
    fn default() -> DefaultableColumnInsertValue<T> { Self::Default }
}Default, #[automatically_derived]
impl<T: ::core::marker::Copy> ::core::marker::Copy for
    DefaultableColumnInsertValue<T> {
}Copy, #[automatically_derived]
impl<T: ::core::clone::Clone> ::core::clone::Clone for
    DefaultableColumnInsertValue<T> {
    #[inline]
    fn clone(&self) -> DefaultableColumnInsertValue<T> {
        match self {
            DefaultableColumnInsertValue::Expression(__self_0) =>
                DefaultableColumnInsertValue::Expression(::core::clone::Clone::clone(__self_0)),
            DefaultableColumnInsertValue::Default =>
                DefaultableColumnInsertValue::Default,
        }
    }
}Clone)]
135#[doc(hidden)]
136pub enum DefaultableColumnInsertValue<T> {
137    Expression(T),
138    #[default]
139    Default,
140}
141
142impl<T> QueryId for DefaultableColumnInsertValue<T> {
143    type QueryId = ();
144    const HAS_STATIC_QUERY_ID: bool = false;
145}
146
147impl<Col, Expr, DB> InsertValues<DB, Col::Table>
148    for DefaultableColumnInsertValue<ColumnInsertValue<Col, Expr>>
149where
150    DB: Backend + SqlDialect<InsertWithDefaultKeyword = sql_dialect::default_keyword_for_insert::IsoSqlDefaultKeyword>,
151    Col: Column,
152    Expr: Expression<SqlType = Col::SqlType> + AppearsOnTable<NoFromClause>,
153    Self: QueryFragment<DB>,
154{
155    fn column_names(&self, mut out: AstPass<'_, '_, DB>) -> QueryResult<()> {
156        out.push_identifier(Col::NAME)?;
157        Ok(())
158    }
159}
160
161impl<Col, Expr, DB> InsertValues<DB, Col::Table> for ColumnInsertValue<Col, Expr>
162where
163    DB: Backend,
164    Col: Column,
165    Expr: Expression<SqlType = Col::SqlType> + AppearsOnTable<NoFromClause>,
166    Self: QueryFragment<DB>,
167{
168    fn column_names(&self, mut out: AstPass<'_, '_, DB>) -> QueryResult<()> {
169        out.push_identifier(Col::NAME)?;
170        Ok(())
171    }
172}
173
174impl<Expr, DB> QueryFragment<DB> for DefaultableColumnInsertValue<Expr>
175where
176    DB: Backend,
177    Self: QueryFragment<DB, DB::InsertWithDefaultKeyword>,
178{
179    fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
180        <Self as QueryFragment<DB, DB::InsertWithDefaultKeyword>>::walk_ast(self, pass)
181    }
182}
183
184impl<Expr, DB> QueryFragment<DB, sql_dialect::default_keyword_for_insert::IsoSqlDefaultKeyword> for DefaultableColumnInsertValue<Expr>
185where
186    DB: Backend + SqlDialect<InsertWithDefaultKeyword = sql_dialect::default_keyword_for_insert::IsoSqlDefaultKeyword>,
187    Expr: QueryFragment<DB>,
188{
189    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
190        out.unsafe_to_cache_prepared();
191        if let Self::Expression(ref inner) = *self {
192            inner.walk_ast(out.reborrow())?;
193        } else {
194            out.push_sql("DEFAULT");
195        }
196        Ok(())
197    }
198}
199
200impl<Col, Expr, DB> QueryFragment<DB> for ColumnInsertValue<Col, Expr>
201where
202    DB: Backend + DieselReserveSpecialization,
203    Expr: QueryFragment<DB>,
204{
205    fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
206        self.expr.walk_ast(pass)
207    }
208}
209
210#[cfg(feature = "__sqlite-shared")]
211impl<Col, Expr> InsertValues<crate::sqlite::Sqlite, Col::Table>
212    for DefaultableColumnInsertValue<ColumnInsertValue<Col, Expr>>
213where
214    Col: Column,
215    Expr: Expression<SqlType = Col::SqlType> + AppearsOnTable<NoFromClause>,
216    Self: QueryFragment<crate::sqlite::Sqlite>,
217{
218    fn column_names(&self, mut out: AstPass<'_, '_, crate::sqlite::Sqlite>) -> QueryResult<()> {
219        if let Self::Expression(..) = *self {
220            out.push_identifier(Col::NAME)?;
221        }
222        Ok(())
223    }
224}
225
226#[cfg(feature = "__sqlite-shared")]
227impl<Col, Expr>
228    QueryFragment<
229        crate::sqlite::Sqlite,
230        crate::backend::sql_dialect::default_keyword_for_insert::DoesNotSupportDefaultKeyword,
231    > for DefaultableColumnInsertValue<ColumnInsertValue<Col, Expr>>
232where
233    Expr: QueryFragment<crate::sqlite::Sqlite>,
234{
235    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, crate::sqlite::Sqlite>) -> QueryResult<()> {
236        if let Self::Expression(ref inner) = *self {
237            inner.walk_ast(out.reborrow())?;
238        }
239        Ok(())
240    }
241}
242
243impl<'a, T, Tab> Insertable<Tab> for &'a [T]
244where
245    &'a T: UndecoratedInsertRecord<Tab> + Insertable<Tab>,
246{
247    type Values = BatchInsert<Vec<<&'a T as Insertable<Tab>>::Values>, Tab, (), false>;
248
249    fn values(self) -> Self::Values {
250        let values = self.iter().map(Insertable::values).collect::<Vec<_>>();
251        BatchInsert::new(values)
252    }
253}
254
255impl<'a, T, Tab> Insertable<Tab> for &'a Vec<T>
256where
257    &'a [T]: Insertable<Tab>,
258{
259    type Values = <&'a [T] as Insertable<Tab>>::Values;
260
261    fn values(self) -> Self::Values {
262        (&**self).values()
263    }
264}
265
266impl<T, Tab> Insertable<Tab> for Vec<T>
267where
268    T: Insertable<Tab> + UndecoratedInsertRecord<Tab>,
269{
270    type Values = BatchInsert<Vec<T::Values>, Tab, (), false>;
271
272    fn values(self) -> Self::Values {
273        let values = self.into_iter().map(Insertable::values).collect::<Vec<_>>();
274        BatchInsert::new(values)
275    }
276}
277
278impl<T, Tab, const N: usize> Insertable<Tab> for [T; N]
279where
280    T: Insertable<Tab>,
281{
282    type Values = BatchInsert<Vec<T::Values>, Tab, [T::Values; N], true>;
283
284    fn values(self) -> Self::Values {
285        let values = self.into_iter().map(Insertable::values).collect::<Vec<_>>();
286        BatchInsert::new(values)
287    }
288}
289
290impl<'a, T, Tab, const N: usize> Insertable<Tab> for &'a [T; N]
291where
292    T: Insertable<Tab>,
293    &'a T: Insertable<Tab>,
294{
295    // We can reuse the query id for [T; N] here as this
296    // compiles down to the same query
297    type Values = BatchInsert<Vec<<&'a T as Insertable<Tab>>::Values>, Tab, [T::Values; N], true>;
298
299    fn values(self) -> Self::Values {
300        let values = self.iter().map(Insertable::values).collect();
301        BatchInsert::new(values)
302    }
303}
304
305impl<T, Tab, const N: usize> Insertable<Tab> for Box<[T; N]>
306where
307    T: Insertable<Tab>,
308{
309    // We can reuse the query id for [T; N] here as this
310    // compiles down to the same query
311    type Values = BatchInsert<Vec<T::Values>, Tab, [T::Values; N], true>;
312
313    fn values(self) -> Self::Values {
314        let v = Vec::from(self as Box<[T]>);
315        let values = v.into_iter().map(Insertable::values).collect::<Vec<_>>();
316        BatchInsert::new(values)
317    }
318}
319
320mod private {
321    // This helper exists to differentiate between
322    // Insertable implementations for tuples and for single values
323    #[allow(missing_debug_implementations)]
324    pub struct InsertableOptionHelper<T, V>(
325        pub(crate) Option<T>,
326        pub(crate) core::marker::PhantomData<V>,
327    );
328}
329
330pub(crate) use self::private::InsertableOptionHelper;
331
332impl<T, Tab, V> Insertable<Tab> for Option<T>
333where
334    T: Insertable<Tab, Values = ValuesClause<V, Tab>>,
335    InsertableOptionHelper<T, V>: Insertable<Tab>,
336{
337    type Values = <InsertableOptionHelper<T, V> as Insertable<Tab>>::Values;
338
339    fn values(self) -> Self::Values {
340        InsertableOptionHelper(self, PhantomData).values()
341    }
342}
343
344impl<T, Tab, Expr, Col> Insertable<Tab> for InsertableOptionHelper<T, ColumnInsertValue<Col, Expr>>
345where
346    T: Insertable<Tab, Values = ValuesClause<ColumnInsertValue<Col, Expr>, Tab>>,
347{
348    type Values = ValuesClause<DefaultableColumnInsertValue<ColumnInsertValue<Col, Expr>>, Tab>;
349
350    fn values(self) -> Self::Values {
351        ValuesClause::new(
352            self.0
353                .map(|v| DefaultableColumnInsertValue::Expression(Insertable::values(v).values))
354                .unwrap_or_default(),
355        )
356    }
357}
358
359impl<'a, T, Tab> Insertable<Tab> for &'a Option<T>
360where
361    Option<&'a T>: Insertable<Tab>,
362{
363    type Values = <Option<&'a T> as Insertable<Tab>>::Values;
364
365    fn values(self) -> Self::Values {
366        self.as_ref().values()
367    }
368}
369
370impl<L, R, Tab> Insertable<Tab> for Grouped<crate::expression::operators::Eq<L, R>>
371where
372    crate::expression::operators::Eq<L, R>: Insertable<Tab>,
373{
374    type Values = <crate::expression::operators::Eq<L, R> as Insertable<Tab>>::Values;
375
376    fn values(self) -> Self::Values {
377        self.0.values()
378    }
379}
380
381impl<'a, L, R, Tab> Insertable<Tab> for &'a Grouped<crate::expression::operators::Eq<L, R>>
382where
383    &'a crate::expression::operators::Eq<L, R>: Insertable<Tab>,
384{
385    type Values = <&'a crate::expression::operators::Eq<L, R> as Insertable<Tab>>::Values;
386
387    fn values(self) -> Self::Values {
388        self.0.values()
389    }
390}