diesel/
insertable.rs

1use std::marker::PhantomData;
2
3use backend::{Backend, SupportsDefaultKeyword};
4use expression::{AppearsOnTable, Expression};
5use query_builder::{
6    AstPass, InsertStatement, QueryFragment, UndecoratedInsertRecord, ValuesClause,
7};
8use query_source::{Column, Table};
9use result::QueryResult;
10#[cfg(feature = "sqlite")]
11use sqlite::Sqlite;
12
13/// Represents that a structure can be used to insert a new row into the
14/// database. This is automatically implemented for `&[T]` and `&Vec<T>` for
15/// inserting more than one record.
16///
17/// ### Deriving
18///
19/// This trait can be automatically derived by adding  `#[derive(Insertable)]`
20/// to your struct. Structs which derive this trait must also be annotated
21/// with `#[table_name = "some_table_name"]`. If the field name of your
22/// struct differs from the name of the column, you can annotate the field
23/// with `#[column_name = "some_column_name"]`.
24///
25/// Your struct can also contain fields which implement `Insertable`. This is
26/// useful when you want to have one field map to more than one column (for
27/// example, an enum that maps to a label and a value column). Add
28/// `#[diesel(embed)]` to any such fields.
29pub trait Insertable<T> {
30    /// The `VALUES` clause to insert these records
31    ///
32    /// The types used here are generally internal to Diesel.
33    /// Implementations of this trait should use the `Values`
34    /// type of other `Insertable` types.
35    /// For example `<diesel::dsl::Eq<column, &str> as Insertable<table>>::Values`.
36    type Values;
37
38    /// Construct `Self::Values`
39    ///
40    /// Implementations of this trait typically call `.values`
41    /// on other `Insertable` types.
42    fn values(self) -> Self::Values;
43
44    /// Insert `self` into a given table.
45    ///
46    /// `foo.insert_into(table)` is identical to `insert_into(table).values(foo)`.
47    /// However, when inserting from a select statement,
48    /// this form is generally preferred.
49    ///
50    /// # Example
51    ///
52    /// ```rust
53    /// # #[macro_use] extern crate diesel;
54    /// # include!("doctest_setup.rs");
55    /// #
56    /// # fn main() {
57    /// #     run_test().unwrap();
58    /// # }
59    /// #
60    /// # fn run_test() -> QueryResult<()> {
61    /// #     use schema::{posts, users};
62    /// #     let conn = establish_connection();
63    /// #     diesel::delete(posts::table).execute(&conn)?;
64    /// users::table
65    ///     .select((
66    ///         users::name.concat("'s First Post"),
67    ///         users::id,
68    ///     ))
69    ///     .insert_into(posts::table)
70    ///     .into_columns((posts::title, posts::user_id))
71    ///     .execute(&conn)?;
72    ///
73    /// let inserted_posts = posts::table
74    ///     .select(posts::title)
75    ///     .load::<String>(&conn)?;
76    /// let expected = vec!["Sean's First Post", "Tess's First Post"];
77    /// assert_eq!(expected, inserted_posts);
78    /// #     Ok(())
79    /// # }
80    /// ```
81    fn insert_into(self, table: T) -> InsertStatement<T, Self::Values>
82    where
83        Self: Sized,
84    {
85        ::insert_into(table).values(self)
86    }
87}
88
89pub trait CanInsertInSingleQuery<DB: Backend> {
90    /// How many rows will this query insert?
91    ///
92    /// This function should only return `None` when the query is valid on all
93    /// backends, regardless of how many rows get inserted.
94    fn rows_to_insert(&self) -> Option<usize>;
95}
96
97impl<'a, T, DB> CanInsertInSingleQuery<DB> for &'a T
98where
99    T: ?Sized + CanInsertInSingleQuery<DB>,
100    DB: Backend,
101{
102    fn rows_to_insert(&self) -> Option<usize> {
103        (*self).rows_to_insert()
104    }
105}
106
107impl<'a, T, Tab, DB> CanInsertInSingleQuery<DB> for BatchInsert<'a, T, Tab>
108where
109    DB: Backend + SupportsDefaultKeyword,
110{
111    fn rows_to_insert(&self) -> Option<usize> {
112        Some(self.records.len())
113    }
114}
115
116impl<T, Table, DB> CanInsertInSingleQuery<DB> for OwnedBatchInsert<T, Table>
117where
118    DB: Backend + SupportsDefaultKeyword,
119{
120    fn rows_to_insert(&self) -> Option<usize> {
121        Some(self.values.len())
122    }
123}
124
125impl<T, U, DB> CanInsertInSingleQuery<DB> for ColumnInsertValue<T, U>
126where
127    DB: Backend,
128{
129    fn rows_to_insert(&self) -> Option<usize> {
130        Some(1)
131    }
132}
133
134pub trait InsertValues<T: Table, DB: Backend>: QueryFragment<DB> {
135    fn column_names(&self, out: AstPass<DB>) -> QueryResult<()>;
136}
137
138#[derive(Debug, Copy, Clone)]
139#[doc(hidden)]
140pub enum ColumnInsertValue<Col, Expr> {
141    Expression(Col, Expr),
142    Default,
143}
144
145impl<Col, Expr> Default for ColumnInsertValue<Col, Expr> {
146    fn default() -> Self {
147        ColumnInsertValue::Default
148    }
149}
150
151impl<Col, Expr, DB> InsertValues<Col::Table, DB> for ColumnInsertValue<Col, Expr>
152where
153    DB: Backend + SupportsDefaultKeyword,
154    Col: Column,
155    Expr: Expression<SqlType = Col::SqlType> + AppearsOnTable<()>,
156    Self: QueryFragment<DB>,
157{
158    fn column_names(&self, mut out: AstPass<DB>) -> QueryResult<()> {
159        out.push_identifier(Col::NAME)?;
160        Ok(())
161    }
162}
163
164impl<Col, Expr, DB> QueryFragment<DB> for ColumnInsertValue<Col, Expr>
165where
166    DB: Backend + SupportsDefaultKeyword,
167    Expr: QueryFragment<DB>,
168{
169    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
170        if let ColumnInsertValue::Expression(_, ref value) = *self {
171            value.walk_ast(out.reborrow())?;
172        } else {
173            out.push_sql("DEFAULT");
174        }
175        Ok(())
176    }
177}
178
179#[cfg(feature = "sqlite")]
180impl<Col, Expr> InsertValues<Col::Table, Sqlite> for ColumnInsertValue<Col, Expr>
181where
182    Col: Column,
183    Expr: Expression<SqlType = Col::SqlType> + AppearsOnTable<()>,
184    Self: QueryFragment<Sqlite>,
185{
186    fn column_names(&self, mut out: AstPass<Sqlite>) -> QueryResult<()> {
187        if let ColumnInsertValue::Expression(..) = *self {
188            out.push_identifier(Col::NAME)?;
189        }
190        Ok(())
191    }
192}
193
194#[cfg(feature = "sqlite")]
195impl<Col, Expr> QueryFragment<Sqlite> for ColumnInsertValue<Col, Expr>
196where
197    Expr: QueryFragment<Sqlite>,
198{
199    fn walk_ast(&self, mut out: AstPass<Sqlite>) -> QueryResult<()> {
200        if let ColumnInsertValue::Expression(_, ref value) = *self {
201            value.walk_ast(out.reborrow())?;
202        }
203        Ok(())
204    }
205}
206
207impl<'a, T, Tab> Insertable<Tab> for &'a [T]
208where
209    &'a T: UndecoratedInsertRecord<Tab>,
210{
211    type Values = BatchInsert<'a, T, Tab>;
212
213    fn values(self) -> Self::Values {
214        BatchInsert {
215            records: self,
216            _marker: PhantomData,
217        }
218    }
219}
220
221impl<'a, T, Tab> Insertable<Tab> for &'a Vec<T>
222where
223    &'a [T]: Insertable<Tab>,
224{
225    type Values = <&'a [T] as Insertable<Tab>>::Values;
226
227    fn values(self) -> Self::Values {
228        (&**self).values()
229    }
230}
231
232impl<T, Tab> Insertable<Tab> for Vec<T>
233where
234    T: Insertable<Tab> + UndecoratedInsertRecord<Tab>,
235{
236    type Values = OwnedBatchInsert<T::Values, Tab>;
237
238    fn values(self) -> Self::Values {
239        OwnedBatchInsert {
240            values: self.into_iter().map(Insertable::values).collect(),
241            _marker: PhantomData,
242        }
243    }
244}
245
246impl<T, Tab> Insertable<Tab> for Option<T>
247where
248    T: Insertable<Tab>,
249    T::Values: Default,
250{
251    type Values = T::Values;
252
253    fn values(self) -> Self::Values {
254        self.map(Insertable::values).unwrap_or_default()
255    }
256}
257
258impl<'a, T, Tab> Insertable<Tab> for &'a Option<T>
259where
260    Option<&'a T>: Insertable<Tab>,
261{
262    type Values = <Option<&'a T> as Insertable<Tab>>::Values;
263
264    fn values(self) -> Self::Values {
265        self.as_ref().values()
266    }
267}
268
269#[derive(Debug, Clone, Copy)]
270pub struct BatchInsert<'a, T: 'a, Tab> {
271    pub(crate) records: &'a [T],
272    _marker: PhantomData<Tab>,
273}
274
275impl<'a, T, Tab, Inner, DB> QueryFragment<DB> for BatchInsert<'a, T, Tab>
276where
277    DB: Backend + SupportsDefaultKeyword,
278    &'a T: Insertable<Tab, Values = ValuesClause<Inner, Tab>>,
279    ValuesClause<Inner, Tab>: QueryFragment<DB>,
280    Inner: QueryFragment<DB>,
281{
282    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
283        let mut records = self.records.iter().map(Insertable::values);
284        if let Some(record) = records.next() {
285            record.walk_ast(out.reborrow())?;
286        }
287        for record in records {
288            out.push_sql(", (");
289            record.values.walk_ast(out.reborrow())?;
290            out.push_sql(")");
291        }
292        Ok(())
293    }
294}
295
296#[derive(Debug)]
297pub struct OwnedBatchInsert<V, Tab> {
298    pub(crate) values: Vec<V>,
299    _marker: PhantomData<Tab>,
300}
301
302impl<Tab, DB, Inner> QueryFragment<DB> for OwnedBatchInsert<ValuesClause<Inner, Tab>, Tab>
303where
304    DB: Backend + SupportsDefaultKeyword,
305    ValuesClause<Inner, Tab>: QueryFragment<DB>,
306    Inner: QueryFragment<DB>,
307{
308    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
309        let mut values = self.values.iter();
310        if let Some(value) = values.next() {
311            value.walk_ast(out.reborrow())?;
312        }
313        for value in values {
314            out.push_sql(", (");
315            value.values.walk_ast(out.reborrow())?;
316            out.push_sql(")");
317        }
318        Ok(())
319    }
320}