1pub(crate) mod batch_insert;
2mod column_list;
3mod insert_from_select;
4
5pub(crate) use self::batch_insert::BatchInsert;
6pub(crate) use self::column_list::ColumnList;
7pub(crate) use self::insert_from_select::InsertFromSelect;
8pub(crate) use self::private::Insert;
9#[diesel_derives::__diesel_public_if(
10 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
11)]
12pub(crate) use self::private::{InsertOrIgnore, Replace};
13
14use super::returning_clause::*;
15use crate::backend::{sql_dialect, DieselReserveSpecialization, SqlDialect};
16use crate::expression::grouped::Grouped;
17use crate::expression::operators::Eq;
18use crate::expression::{Expression, NonAggregate, SelectableExpression};
19use crate::query_builder::*;
20use crate::query_dsl::RunQueryDsl;
21use crate::query_source::{Column, Table};
22use crate::{insertable::*, QuerySource};
23use std::marker::PhantomData;
24
25pub(crate) use self::private::InsertAutoTypeHelper;
26
27#[cfg(feature = "sqlite")]
28mod insert_with_default_for_sqlite;
29
30#[derive(Debug, Clone, Copy)]
39#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
40pub struct IncompleteInsertStatement<T, Op = Insert> {
41 target: T,
42 operator: Op,
43}
44
45pub type IncompleteInsertOrIgnoreStatement<T> = IncompleteInsertStatement<T, InsertOrIgnore>;
47
48pub type InsertOrIgnoreStatement<T, U, Ret = NoReturningClause> =
50 InsertStatement<T, U, InsertOrIgnore, Ret>;
51
52pub type IncompleteReplaceStatement<T> = IncompleteInsertStatement<T, Replace>;
54
55pub type ReplaceStatement<T, U, Ret = NoReturningClause> = InsertStatement<T, U, Replace, Ret>;
57
58impl<T, Op> IncompleteInsertStatement<T, Op>
59where
60 T: QuerySource,
61{
62 pub(crate) fn new(target: T, operator: Op) -> Self {
63 IncompleteInsertStatement { target, operator }
64 }
65
66 pub fn default_values(self) -> InsertStatement<T, DefaultValues, Op> {
103 self.values(DefaultValues)
104 }
105
106 pub fn values<U>(self, records: U) -> InsertStatement<T, U::Values, Op>
118 where
119 U: Insertable<T>,
120 {
121 InsertStatement::new(
122 self.target,
123 records.values(),
124 self.operator,
125 NoReturningClause,
126 )
127 }
128}
129
130#[diesel_derives::__diesel_public_if(
143 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
144 public_fields(operator, target, records, returning)
145)]
146#[derive(Debug, Copy, Clone)]
147#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
148pub struct InsertStatement<T: QuerySource, U, Op = Insert, Ret = NoReturningClause> {
149 operator: Op,
153 target: T,
155 records: U,
157 returning: Ret,
159 into_clause: T::FromClause,
160}
161
162impl<T, U, Op, Ret> QueryId for InsertStatement<T, U, Op, Ret>
163where
164 T: QuerySource + QueryId + 'static,
165 U: QueryId,
166 Op: QueryId,
167 Ret: QueryId,
168{
169 type QueryId = InsertStatement<T, U::QueryId, Op::QueryId, Ret::QueryId>;
170
171 const HAS_STATIC_QUERY_ID: bool = T::HAS_STATIC_QUERY_ID
172 && U::HAS_STATIC_QUERY_ID
173 && Op::HAS_STATIC_QUERY_ID
174 && Ret::HAS_STATIC_QUERY_ID;
175}
176
177impl<T: QuerySource, U, Op, Ret> InsertStatement<T, U, Op, Ret> {
178 #[diesel_derives::__diesel_public_if(
180 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
181 )]
182 pub(crate) fn new(target: T, records: U, operator: Op, returning: Ret) -> Self {
183 InsertStatement {
184 into_clause: target.from_clause(),
185 operator,
186 target,
187 records,
188 returning,
189 }
190 }
191
192 pub(crate) fn replace_values<F, V>(self, f: F) -> InsertStatement<T, V, Op, Ret>
193 where
194 F: FnOnce(U) -> V,
195 {
196 InsertStatement::new(self.target, f(self.records), self.operator, self.returning)
197 }
198}
199
200impl<T: QuerySource, U, C, Op, Ret> InsertStatement<T, InsertFromSelect<U, C>, Op, Ret> {
201 pub fn into_columns<C2>(
207 self,
208 columns: C2,
209 ) -> InsertStatement<T, InsertFromSelect<U, C2>, Op, Ret>
210 where
211 C2: ColumnList<Table = T> + Expression,
212 U: Query<SqlType = C2::SqlType>,
213 {
214 InsertStatement::new(
215 self.target,
216 self.records.with_columns(columns),
217 self.operator,
218 self.returning,
219 )
220 }
221}
222
223impl<T, U, Op, Ret, DB> QueryFragment<DB> for InsertStatement<T, U, Op, Ret>
224where
225 DB: Backend + DieselReserveSpecialization,
226 T: Table,
227 T::FromClause: QueryFragment<DB>,
228 U: QueryFragment<DB> + CanInsertInSingleQuery<DB>,
229 Op: QueryFragment<DB>,
230 Ret: QueryFragment<DB>,
231{
232 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
233 if self.records.rows_to_insert() == Some(0) {
234 out.push_sql("SELECT 1 FROM ");
235 self.into_clause.walk_ast(out.reborrow())?;
236 out.push_sql(" WHERE 1=0");
237 return Ok(());
238 }
239
240 self.operator.walk_ast(out.reborrow())?;
241 out.push_sql(" INTO ");
242 self.into_clause.walk_ast(out.reborrow())?;
243 out.push_sql(" ");
244 self.records.walk_ast(out.reborrow())?;
245 self.returning.walk_ast(out.reborrow())?;
246 Ok(())
247 }
248}
249
250impl<T, U, Op> AsQuery for InsertStatement<T, U, Op, NoReturningClause>
251where
252 T: Table,
253 InsertStatement<T, U, Op, ReturningClause<T::AllColumns>>: Query,
254{
255 type SqlType = <Self::Query as Query>::SqlType;
256 type Query = InsertStatement<T, U, Op, ReturningClause<T::AllColumns>>;
257
258 fn as_query(self) -> Self::Query {
259 self.returning(T::all_columns())
260 }
261}
262
263impl<T, U, Op, Ret> Query for InsertStatement<T, U, Op, ReturningClause<Ret>>
264where
265 T: QuerySource,
266 Ret: Expression + SelectableExpression<T> + NonAggregate,
267{
268 type SqlType = Ret::SqlType;
269}
270
271impl<T: QuerySource, U, Op, Ret, Conn> RunQueryDsl<Conn> for InsertStatement<T, U, Op, Ret> {}
272
273impl<T: QuerySource, U, Op> InsertStatement<T, U, Op> {
274 pub fn returning<E>(self, returns: E) -> InsertStatement<T, U, Op, ReturningClause<E>>
300 where
301 InsertStatement<T, U, Op, ReturningClause<E>>: Query,
302 {
303 InsertStatement::new(
304 self.target,
305 self.records,
306 self.operator,
307 ReturningClause(returns),
308 )
309 }
310}
311
312#[cfg_attr(
319 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
320 cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")
321)]
322pub trait UndecoratedInsertRecord<Table> {}
323
324impl<T, Tab> UndecoratedInsertRecord<Tab> for &T where T: ?Sized + UndecoratedInsertRecord<Tab> {}
325
326impl<T, U> UndecoratedInsertRecord<T::Table> for ColumnInsertValue<T, U> where T: Column {}
327
328impl<T, U> UndecoratedInsertRecord<T::Table>
329 for DefaultableColumnInsertValue<ColumnInsertValue<T, U>>
330where
331 T: Column,
332{
333}
334
335impl<T, Table> UndecoratedInsertRecord<Table> for [T] where T: UndecoratedInsertRecord<Table> {}
336
337impl<T, Table, QId, const STATIC_QUERY_ID: bool> UndecoratedInsertRecord<Table>
338 for BatchInsert<T, Table, QId, STATIC_QUERY_ID>
339where
340 T: UndecoratedInsertRecord<Table>,
341{
342}
343
344impl<T, Table> UndecoratedInsertRecord<Table> for Vec<T> where [T]: UndecoratedInsertRecord<Table> {}
345
346impl<Lhs, Rhs> UndecoratedInsertRecord<Lhs::Table> for Eq<Lhs, Rhs> where Lhs: Column {}
347
348impl<Lhs, Rhs, Tab> UndecoratedInsertRecord<Tab> for Option<Eq<Lhs, Rhs>> where
349 Eq<Lhs, Rhs>: UndecoratedInsertRecord<Tab>
350{
351}
352
353impl<Lhs, Rhs> UndecoratedInsertRecord<Lhs::Table> for Grouped<Eq<Lhs, Rhs>> where Lhs: Column {}
354
355impl<Lhs, Rhs, Tab> UndecoratedInsertRecord<Tab> for Option<Grouped<Eq<Lhs, Rhs>>> where
356 Eq<Lhs, Rhs>: UndecoratedInsertRecord<Tab>
357{
358}
359
360impl<T, Table> UndecoratedInsertRecord<Table> for ValuesClause<T, Table> where
361 T: UndecoratedInsertRecord<Table>
362{
363}
364
365#[derive(Debug, Clone, Copy, QueryId)]
366#[doc(hidden)]
367pub struct DefaultValues;
368
369impl<DB: Backend> CanInsertInSingleQuery<DB> for DefaultValues {
370 fn rows_to_insert(&self) -> Option<usize> {
371 Some(1)
372 }
373}
374
375impl<Tab> Insertable<Tab> for DefaultValues {
376 type Values = DefaultValues;
377
378 fn values(self) -> Self::Values {
379 self
380 }
381}
382
383impl<Tab> Insertable<Tab> for &DefaultValues {
384 type Values = DefaultValues;
385
386 fn values(self) -> Self::Values {
387 *self
388 }
389}
390
391impl<DB> QueryFragment<DB> for DefaultValues
392where
393 DB: Backend,
394 Self: QueryFragment<DB, DB::DefaultValueClauseForInsert>,
395{
396 fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
397 <Self as QueryFragment<DB, DB::DefaultValueClauseForInsert>>::walk_ast(self, pass)
398 }
399}
400
401impl<DB> QueryFragment<DB, sql_dialect::default_value_clause::AnsiDefaultValueClause>
402 for DefaultValues
403where
404 DB: Backend
405 + SqlDialect<
406 DefaultValueClauseForInsert = sql_dialect::default_value_clause::AnsiDefaultValueClause,
407 >,
408{
409 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
410 out.push_sql("DEFAULT VALUES");
411 Ok(())
412 }
413}
414
415#[cfg_attr(
420 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
421 cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")
422)]
423#[derive(Debug, Clone, Copy, QueryId)]
424pub struct ValuesClause<T, Tab> {
425 pub values: T,
427 _marker: PhantomData<Tab>,
428}
429
430impl<T: Default, Tab> Default for ValuesClause<T, Tab> {
431 fn default() -> Self {
432 Self::new(T::default())
433 }
434}
435
436impl<T, Tab> ValuesClause<T, Tab> {
437 pub(crate) fn new(values: T) -> Self {
438 Self {
439 values,
440 _marker: PhantomData,
441 }
442 }
443}
444
445impl<T, Tab, DB> CanInsertInSingleQuery<DB> for ValuesClause<T, Tab>
446where
447 DB: Backend,
448 T: CanInsertInSingleQuery<DB>,
449{
450 fn rows_to_insert(&self) -> Option<usize> {
451 self.values.rows_to_insert()
452 }
453}
454
455impl<T, Tab, DB> QueryFragment<DB> for ValuesClause<T, Tab>
456where
457 DB: Backend,
458 Tab: Table,
459 T: InsertValues<DB, Tab>,
460 DefaultValues: QueryFragment<DB>,
461{
462 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
463 if self.values.is_noop(out.backend())? {
464 DefaultValues.walk_ast(out)?;
465 } else {
466 out.push_sql("(");
467 self.values.column_names(out.reborrow())?;
468 out.push_sql(") VALUES (");
469 self.values.walk_ast(out.reborrow())?;
470 out.push_sql(")");
471 }
472 Ok(())
473 }
474}
475
476mod private {
477 use crate::backend::{Backend, DieselReserveSpecialization};
478 use crate::query_builder::{AstPass, QueryFragment, QueryId};
479 use crate::QueryResult;
480
481 #[derive(Debug, Copy, Clone, QueryId)]
482 pub struct Insert;
483
484 impl<DB> QueryFragment<DB> for Insert
485 where
486 DB: Backend + DieselReserveSpecialization,
487 {
488 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
489 out.push_sql("INSERT");
490 Ok(())
491 }
492 }
493
494 #[derive(Debug, Copy, Clone, QueryId)]
496 pub struct InsertOrIgnore;
497
498 #[cfg(feature = "sqlite")]
499 impl QueryFragment<crate::sqlite::Sqlite> for InsertOrIgnore {
500 fn walk_ast<'b>(
501 &'b self,
502 mut out: AstPass<'_, 'b, crate::sqlite::Sqlite>,
503 ) -> QueryResult<()> {
504 out.push_sql("INSERT OR IGNORE");
505 Ok(())
506 }
507 }
508
509 #[cfg(feature = "mysql_backend")]
510 impl QueryFragment<crate::mysql::Mysql> for InsertOrIgnore {
511 fn walk_ast<'b>(
512 &'b self,
513 mut out: AstPass<'_, 'b, crate::mysql::Mysql>,
514 ) -> QueryResult<()> {
515 out.push_sql("INSERT IGNORE");
516 Ok(())
517 }
518 }
519
520 #[derive(Debug, Copy, Clone, QueryId)]
522 pub struct Replace;
523
524 #[cfg(feature = "sqlite")]
525 impl QueryFragment<crate::sqlite::Sqlite> for Replace {
526 fn walk_ast<'b>(
527 &'b self,
528 mut out: AstPass<'_, 'b, crate::sqlite::Sqlite>,
529 ) -> QueryResult<()> {
530 out.push_sql("REPLACE");
531 Ok(())
532 }
533 }
534
535 #[cfg(feature = "mysql_backend")]
536 impl QueryFragment<crate::mysql::Mysql> for Replace {
537 fn walk_ast<'b>(
538 &'b self,
539 mut out: AstPass<'_, 'b, crate::mysql::Mysql>,
540 ) -> QueryResult<()> {
541 out.push_sql("REPLACE");
542 Ok(())
543 }
544 }
545
546 #[allow(unreachable_pub)]
548 pub trait InsertAutoTypeHelper {
549 type Table;
550 type Op;
551 }
552
553 impl<T, Op> InsertAutoTypeHelper for crate::query_builder::IncompleteInsertStatement<T, Op> {
554 type Table = T;
555 type Op = Op;
556 }
557}