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
14pub trait Insertable<T> {
20 type Values;
27
28 fn values(self) -> Self::Values;
33
34 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 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 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 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 #[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}