1use std::marker::PhantomData;
2
3use crate::backend::{sql_dialect, Backend, DieselReserveSpecialization, SqlDialect};
4use crate::expression::grouped::Grouped;
5use crate::expression::{AppearsOnTable, Expression};
6use crate::query_builder::{
7 AstPass, BatchInsert, InsertStatement, NoFromClause, QueryFragment, QueryId,
8 UndecoratedInsertRecord, ValuesClause,
9};
10use crate::query_source::{Column, Table};
11use crate::result::QueryResult;
12
13pub trait Insertable<T> {
19 type Values;
26
27 fn values(self) -> Self::Values;
32
33 fn insert_into(self, table: T) -> InsertStatement<T, Self::Values>
70 where
71 T: Table,
72 Self: Sized,
73 {
74 crate::insert_into(table).values(self)
75 }
76}
77
78#[doc(inline)]
79pub use diesel_derives::Insertable;
80
81pub trait CanInsertInSingleQuery<DB: Backend> {
82 fn rows_to_insert(&self) -> Option<usize>;
87}
88
89impl<T, DB> CanInsertInSingleQuery<DB> for &T
90where
91 T: ?Sized + CanInsertInSingleQuery<DB>,
92 DB: Backend,
93{
94 fn rows_to_insert(&self) -> Option<usize> {
95 (*self).rows_to_insert()
96 }
97}
98
99impl<T, U, DB> CanInsertInSingleQuery<DB> for ColumnInsertValue<T, U>
100where
101 DB: Backend,
102{
103 fn rows_to_insert(&self) -> Option<usize> {
104 Some(1)
105 }
106}
107
108impl<V, DB> CanInsertInSingleQuery<DB> for DefaultableColumnInsertValue<V>
109where
110 DB: Backend,
111 V: CanInsertInSingleQuery<DB>,
112{
113 fn rows_to_insert(&self) -> Option<usize> {
114 Some(1)
115 }
116}
117
118pub trait InsertValues<DB: Backend, T: Table>: QueryFragment<DB> {
119 fn column_names(&self, out: AstPass<'_, '_, DB>) -> QueryResult<()>;
120}
121
122#[derive(Debug, Copy, Clone, QueryId)]
123#[doc(hidden)]
124pub struct ColumnInsertValue<Col, Expr> {
125 pub(crate) expr: Expr,
126 p: PhantomData<Col>,
127}
128
129impl<Col, Expr> ColumnInsertValue<Col, Expr> {
130 pub(crate) fn new(expr: Expr) -> Self {
131 Self {
132 expr,
133 p: PhantomData,
134 }
135 }
136}
137
138#[derive(Debug, Copy, Clone)]
139#[doc(hidden)]
140pub enum DefaultableColumnInsertValue<T> {
141 Expression(T),
142 Default,
143}
144
145impl<T> QueryId for DefaultableColumnInsertValue<T> {
146 type QueryId = ();
147 const HAS_STATIC_QUERY_ID: bool = false;
148}
149
150#[allow(clippy::derivable_impls)] impl<T> Default for DefaultableColumnInsertValue<T> {
152 fn default() -> Self {
153 DefaultableColumnInsertValue::Default
154 }
155}
156
157impl<Col, Expr, DB> InsertValues<DB, Col::Table>
158 for DefaultableColumnInsertValue<ColumnInsertValue<Col, Expr>>
159where
160 DB: Backend + SqlDialect<InsertWithDefaultKeyword = sql_dialect::default_keyword_for_insert::IsoSqlDefaultKeyword>,
161 Col: Column,
162 Expr: Expression<SqlType = Col::SqlType> + AppearsOnTable<NoFromClause>,
163 Self: QueryFragment<DB>,
164{
165 fn column_names(&self, mut out: AstPass<'_, '_, DB>) -> QueryResult<()> {
166 out.push_identifier(Col::NAME)?;
167 Ok(())
168 }
169}
170
171impl<Col, Expr, DB> InsertValues<DB, Col::Table> for ColumnInsertValue<Col, Expr>
172where
173 DB: Backend,
174 Col: Column,
175 Expr: Expression<SqlType = Col::SqlType> + AppearsOnTable<NoFromClause>,
176 Self: QueryFragment<DB>,
177{
178 fn column_names(&self, mut out: AstPass<'_, '_, DB>) -> QueryResult<()> {
179 out.push_identifier(Col::NAME)?;
180 Ok(())
181 }
182}
183
184impl<Expr, DB> QueryFragment<DB> for DefaultableColumnInsertValue<Expr>
185where
186 DB: Backend,
187 Self: QueryFragment<DB, DB::InsertWithDefaultKeyword>,
188{
189 fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
190 <Self as QueryFragment<DB, DB::InsertWithDefaultKeyword>>::walk_ast(self, pass)
191 }
192}
193
194impl<Expr, DB> QueryFragment<DB, sql_dialect::default_keyword_for_insert::IsoSqlDefaultKeyword> for DefaultableColumnInsertValue<Expr>
195where
196 DB: Backend + SqlDialect<InsertWithDefaultKeyword = sql_dialect::default_keyword_for_insert::IsoSqlDefaultKeyword>,
197 Expr: QueryFragment<DB>,
198{
199 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
200 out.unsafe_to_cache_prepared();
201 if let Self::Expression(ref inner) = *self {
202 inner.walk_ast(out.reborrow())?;
203 } else {
204 out.push_sql("DEFAULT");
205 }
206 Ok(())
207 }
208}
209
210impl<Col, Expr, DB> QueryFragment<DB> for ColumnInsertValue<Col, Expr>
211where
212 DB: Backend + DieselReserveSpecialization,
213 Expr: QueryFragment<DB>,
214{
215 fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
216 self.expr.walk_ast(pass)
217 }
218}
219
220#[cfg(feature = "sqlite")]
221impl<Col, Expr> InsertValues<crate::sqlite::Sqlite, Col::Table>
222 for DefaultableColumnInsertValue<ColumnInsertValue<Col, Expr>>
223where
224 Col: Column,
225 Expr: Expression<SqlType = Col::SqlType> + AppearsOnTable<NoFromClause>,
226 Self: QueryFragment<crate::sqlite::Sqlite>,
227{
228 fn column_names(&self, mut out: AstPass<'_, '_, crate::sqlite::Sqlite>) -> QueryResult<()> {
229 if let Self::Expression(..) = *self {
230 out.push_identifier(Col::NAME)?;
231 }
232 Ok(())
233 }
234}
235
236#[cfg(feature = "sqlite")]
237impl<Col, Expr>
238 QueryFragment<
239 crate::sqlite::Sqlite,
240 crate::backend::sql_dialect::default_keyword_for_insert::DoesNotSupportDefaultKeyword,
241 > for DefaultableColumnInsertValue<ColumnInsertValue<Col, Expr>>
242where
243 Expr: QueryFragment<crate::sqlite::Sqlite>,
244{
245 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, crate::sqlite::Sqlite>) -> QueryResult<()> {
246 if let Self::Expression(ref inner) = *self {
247 inner.walk_ast(out.reborrow())?;
248 }
249 Ok(())
250 }
251}
252
253impl<'a, T, Tab> Insertable<Tab> for &'a [T]
254where
255 &'a T: UndecoratedInsertRecord<Tab> + Insertable<Tab>,
256{
257 type Values = BatchInsert<Vec<<&'a T as Insertable<Tab>>::Values>, Tab, (), false>;
258
259 fn values(self) -> Self::Values {
260 let values = self.iter().map(Insertable::values).collect::<Vec<_>>();
261 BatchInsert::new(values)
262 }
263}
264
265impl<'a, T, Tab> Insertable<Tab> for &'a Vec<T>
266where
267 &'a [T]: Insertable<Tab>,
268{
269 type Values = <&'a [T] as Insertable<Tab>>::Values;
270
271 fn values(self) -> Self::Values {
272 (&**self).values()
273 }
274}
275
276impl<T, Tab> Insertable<Tab> for Vec<T>
277where
278 T: Insertable<Tab> + UndecoratedInsertRecord<Tab>,
279{
280 type Values = BatchInsert<Vec<T::Values>, Tab, (), false>;
281
282 fn values(self) -> Self::Values {
283 let values = self.into_iter().map(Insertable::values).collect::<Vec<_>>();
284 BatchInsert::new(values)
285 }
286}
287
288impl<T, Tab, const N: usize> Insertable<Tab> for [T; N]
289where
290 T: Insertable<Tab>,
291{
292 type Values = BatchInsert<Vec<T::Values>, Tab, [T::Values; N], true>;
293
294 #[allow(deprecated)]
298 fn values(self) -> Self::Values {
299 let values = std::array::IntoIter::new(self)
300 .map(Insertable::values)
301 .collect::<Vec<_>>();
302 BatchInsert::new(values)
303 }
304}
305
306impl<'a, T, Tab, const N: usize> Insertable<Tab> for &'a [T; N]
307where
308 T: Insertable<Tab>,
309 &'a T: Insertable<Tab>,
310{
311 type Values = BatchInsert<Vec<<&'a T as Insertable<Tab>>::Values>, Tab, [T::Values; N], true>;
314
315 fn values(self) -> Self::Values {
316 let values = self.iter().map(Insertable::values).collect();
317 BatchInsert::new(values)
318 }
319}
320
321impl<T, Tab, const N: usize> Insertable<Tab> for Box<[T; N]>
322where
323 T: Insertable<Tab>,
324{
325 type Values = BatchInsert<Vec<T::Values>, Tab, [T::Values; N], true>;
328
329 fn values(self) -> Self::Values {
330 let v = Vec::from(self as Box<[T]>);
331 let values = v.into_iter().map(Insertable::values).collect::<Vec<_>>();
332 BatchInsert::new(values)
333 }
334}
335
336mod private {
337 #[allow(missing_debug_implementations)]
340 pub struct InsertableOptionHelper<T, V>(
341 pub(crate) Option<T>,
342 pub(crate) std::marker::PhantomData<V>,
343 );
344}
345
346pub(crate) use self::private::InsertableOptionHelper;
347
348impl<T, Tab, V> Insertable<Tab> for Option<T>
349where
350 T: Insertable<Tab, Values = ValuesClause<V, Tab>>,
351 InsertableOptionHelper<T, V>: Insertable<Tab>,
352{
353 type Values = <InsertableOptionHelper<T, V> as Insertable<Tab>>::Values;
354
355 fn values(self) -> Self::Values {
356 InsertableOptionHelper(self, PhantomData).values()
357 }
358}
359
360impl<T, Tab, Expr, Col> Insertable<Tab> for InsertableOptionHelper<T, ColumnInsertValue<Col, Expr>>
361where
362 T: Insertable<Tab, Values = ValuesClause<ColumnInsertValue<Col, Expr>, Tab>>,
363{
364 type Values = ValuesClause<DefaultableColumnInsertValue<ColumnInsertValue<Col, Expr>>, Tab>;
365
366 fn values(self) -> Self::Values {
367 ValuesClause::new(
368 self.0
369 .map(|v| DefaultableColumnInsertValue::Expression(Insertable::values(v).values))
370 .unwrap_or_default(),
371 )
372 }
373}
374
375impl<'a, T, Tab> Insertable<Tab> for &'a Option<T>
376where
377 Option<&'a T>: Insertable<Tab>,
378{
379 type Values = <Option<&'a T> as Insertable<Tab>>::Values;
380
381 fn values(self) -> Self::Values {
382 self.as_ref().values()
383 }
384}
385
386impl<L, R, Tab> Insertable<Tab> for Grouped<crate::expression::operators::Eq<L, R>>
387where
388 crate::expression::operators::Eq<L, R>: Insertable<Tab>,
389{
390 type Values = <crate::expression::operators::Eq<L, R> as Insertable<Tab>>::Values;
391
392 fn values(self) -> Self::Values {
393 self.0.values()
394 }
395}
396
397impl<'a, L, R, Tab> Insertable<Tab> for &'a Grouped<crate::expression::operators::Eq<L, R>>
398where
399 &'a crate::expression::operators::Eq<L, R>: Insertable<Tab>,
400{
401 type Values = <&'a crate::expression::operators::Eq<L, R> as Insertable<Tab>>::Values;
402
403 fn values(self) -> Self::Values {
404 self.0.values()
405 }
406}