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