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