1mod column_list;
2mod insert_from_select;
3
4pub(crate) use self::column_list::ColumnList;
5pub(crate) use self::insert_from_select::InsertFromSelect;
6
7use std::any::*;
8use std::marker::PhantomData;
9
10use super::returning_clause::*;
11use backend::Backend;
12use expression::operators::Eq;
13use expression::{Expression, NonAggregate, SelectableExpression};
14use insertable::*;
15#[cfg(feature = "mysql")]
16use mysql::Mysql;
17use query_builder::*;
18#[cfg(feature = "sqlite")]
19use query_dsl::methods::ExecuteDsl;
20use query_dsl::RunQueryDsl;
21use query_source::{Column, Table};
22use result::QueryResult;
23#[cfg(feature = "sqlite")]
24use sqlite::{Sqlite, SqliteConnection};
25
26#[derive(Debug, Clone, Copy)]
35#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
36pub struct IncompleteInsertStatement<T, Op> {
37 target: T,
38 operator: Op,
39}
40
41impl<T, Op> IncompleteInsertStatement<T, Op> {
42 pub(crate) fn new(target: T, operator: Op) -> Self {
43 IncompleteInsertStatement { target, operator }
44 }
45
46 pub fn default_values(self) -> InsertStatement<T, DefaultValues, Op> {
84 static STATIC_DEFAULT_VALUES: &DefaultValues = &DefaultValues;
85 self.values(STATIC_DEFAULT_VALUES)
86 }
87
88 pub fn values<U>(self, records: U) -> InsertStatement<T, U::Values, Op>
100 where
101 U: Insertable<T>,
102 {
103 InsertStatement::new(
104 self.target,
105 records.values(),
106 self.operator,
107 NoReturningClause,
108 )
109 }
110}
111
112#[derive(Debug, Copy, Clone)]
113#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
114pub struct InsertStatement<T, U, Op = Insert, Ret = NoReturningClause> {
127 operator: Op,
128 target: T,
129 records: U,
130 returning: Ret,
131}
132
133impl<T, U, Op, Ret> InsertStatement<T, U, Op, Ret> {
134 fn new(target: T, records: U, operator: Op, returning: Ret) -> Self {
135 InsertStatement {
136 operator: operator,
137 target: target,
138 records: records,
139 returning: returning,
140 }
141 }
142
143 #[cfg(feature = "postgres")]
144 pub(crate) fn replace_values<F, V>(self, f: F) -> InsertStatement<T, V, Op, Ret>
145 where
146 F: FnOnce(U) -> V,
147 {
148 InsertStatement::new(self.target, f(self.records), self.operator, self.returning)
149 }
150}
151
152impl<T, U, C, Op, Ret> InsertStatement<T, InsertFromSelect<U, C>, Op, Ret> {
153 pub fn into_columns<C2>(
159 self,
160 columns: C2,
161 ) -> InsertStatement<T, InsertFromSelect<U, C2>, Op, Ret>
162 where
163 C2: ColumnList<Table = T> + Expression<SqlType = U::SqlType>,
164 U: Query,
165 {
166 InsertStatement::new(
167 self.target,
168 self.records.with_columns(columns),
169 self.operator,
170 self.returning,
171 )
172 }
173}
174
175impl<T, U, Op, Ret, DB> QueryFragment<DB> for InsertStatement<T, U, Op, Ret>
176where
177 DB: Backend,
178 T: Table,
179 T::FromClause: QueryFragment<DB>,
180 U: QueryFragment<DB> + CanInsertInSingleQuery<DB>,
181 Op: QueryFragment<DB>,
182 Ret: QueryFragment<DB>,
183{
184 fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
185 out.unsafe_to_cache_prepared();
186
187 if self.records.rows_to_insert() == Some(0) {
188 out.push_sql("SELECT 1 FROM ");
189 self.target.from_clause().walk_ast(out.reborrow())?;
190 out.push_sql(" WHERE 1=0");
191 return Ok(());
192 }
193
194 self.operator.walk_ast(out.reborrow())?;
195 out.push_sql(" INTO ");
196 self.target.from_clause().walk_ast(out.reborrow())?;
197 out.push_sql(" ");
198 self.records.walk_ast(out.reborrow())?;
199 self.returning.walk_ast(out.reborrow())?;
200 Ok(())
201 }
202}
203
204#[cfg(feature = "sqlite")]
205impl<'a, T, U, Op> ExecuteDsl<SqliteConnection> for InsertStatement<T, &'a [U], Op>
206where
207 &'a U: Insertable<T>,
208 InsertStatement<T, <&'a U as Insertable<T>>::Values, Op>: QueryFragment<Sqlite>,
209 T: Copy,
210 Op: Copy,
211{
212 fn execute(query: Self, conn: &SqliteConnection) -> QueryResult<usize> {
213 use connection::Connection;
214 conn.transaction(|| {
215 let mut result = 0;
216 for record in query.records {
217 result += InsertStatement::new(
218 query.target,
219 record.values(),
220 query.operator,
221 query.returning,
222 )
223 .execute(conn)?;
224 }
225 Ok(result)
226 })
227 }
228}
229
230#[cfg(feature = "sqlite")]
231impl<'a, T, U, Op> ExecuteDsl<SqliteConnection> for InsertStatement<T, BatchInsert<'a, U, T>, Op>
232where
233 InsertStatement<T, &'a [U], Op>: ExecuteDsl<SqliteConnection>,
234{
235 fn execute(query: Self, conn: &SqliteConnection) -> QueryResult<usize> {
236 InsertStatement::new(
237 query.target,
238 query.records.records,
239 query.operator,
240 query.returning,
241 )
242 .execute(conn)
243 }
244}
245
246#[cfg(feature = "sqlite")]
247impl<T, U, Op> ExecuteDsl<SqliteConnection>
248 for InsertStatement<T, OwnedBatchInsert<ValuesClause<U, T>, T>, Op>
249where
250 InsertStatement<T, ValuesClause<U, T>, Op>: QueryFragment<Sqlite>,
251 T: Copy,
252 Op: Copy,
253{
254 fn execute(query: Self, conn: &SqliteConnection) -> QueryResult<usize> {
255 use connection::Connection;
256 conn.transaction(|| {
257 let mut result = 0;
258 for value in query.records.values {
259 result +=
260 InsertStatement::new(query.target, value, query.operator, query.returning)
261 .execute(conn)?;
262 }
263 Ok(result)
264 })
265 }
266}
267
268impl<T, U, Op, Ret> QueryId for InsertStatement<T, U, Op, Ret> {
269 type QueryId = ();
270
271 const HAS_STATIC_QUERY_ID: bool = false;
272}
273
274impl<T, U, Op> AsQuery for InsertStatement<T, U, Op, NoReturningClause>
275where
276 T: Table,
277 InsertStatement<T, U, Op, ReturningClause<T::AllColumns>>: Query,
278{
279 type SqlType = <Self::Query as Query>::SqlType;
280 type Query = InsertStatement<T, U, Op, ReturningClause<T::AllColumns>>;
281
282 fn as_query(self) -> Self::Query {
283 self.returning(T::all_columns())
284 }
285}
286
287impl<T, U, Op, Ret> Query for InsertStatement<T, U, Op, ReturningClause<Ret>>
288where
289 Ret: Expression + SelectableExpression<T> + NonAggregate,
290{
291 type SqlType = Ret::SqlType;
292}
293
294impl<T, U, Op, Ret, Conn> RunQueryDsl<Conn> for InsertStatement<T, U, Op, Ret> {}
295
296impl<T, U, Op> InsertStatement<T, U, Op> {
297 pub fn returning<E>(self, returns: E) -> InsertStatement<T, U, Op, ReturningClause<E>>
320 where
321 InsertStatement<T, U, Op, ReturningClause<E>>: Query,
322 {
323 InsertStatement::new(
324 self.target,
325 self.records,
326 self.operator,
327 ReturningClause(returns),
328 )
329 }
330}
331
332#[derive(Debug, Copy, Clone, QueryId)]
333#[doc(hidden)]
334pub struct Insert;
335
336impl<DB: Backend> QueryFragment<DB> for Insert {
337 fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
338 out.push_sql("INSERT");
339 Ok(())
340 }
341}
342
343#[derive(Debug, Copy, Clone, QueryId)]
344#[doc(hidden)]
345pub struct InsertOrIgnore;
346
347#[cfg(feature = "sqlite")]
348impl QueryFragment<Sqlite> for InsertOrIgnore {
349 fn walk_ast(&self, mut out: AstPass<Sqlite>) -> QueryResult<()> {
350 out.push_sql("INSERT OR IGNORE");
351 Ok(())
352 }
353}
354
355#[cfg(feature = "mysql")]
356impl QueryFragment<Mysql> for InsertOrIgnore {
357 fn walk_ast(&self, mut out: AstPass<Mysql>) -> QueryResult<()> {
358 out.push_sql("INSERT IGNORE");
359 Ok(())
360 }
361}
362
363#[derive(Debug, Copy, Clone)]
364#[doc(hidden)]
365pub struct Replace;
366
367#[cfg(feature = "sqlite")]
368impl QueryFragment<Sqlite> for Replace {
369 fn walk_ast(&self, mut out: AstPass<Sqlite>) -> QueryResult<()> {
370 out.push_sql("REPLACE");
371 Ok(())
372 }
373}
374
375#[cfg(feature = "mysql")]
376impl QueryFragment<Mysql> for Replace {
377 fn walk_ast(&self, mut out: AstPass<Mysql>) -> QueryResult<()> {
378 out.push_sql("REPLACE");
379 Ok(())
380 }
381}
382
383pub trait UndecoratedInsertRecord<Table> {}
390
391impl<'a, T, Tab> UndecoratedInsertRecord<Tab> for &'a T where
392 T: ?Sized + UndecoratedInsertRecord<Tab>
393{
394}
395
396impl<T, U> UndecoratedInsertRecord<T::Table> for ColumnInsertValue<T, U> where T: Column {}
397
398impl<T, Table> UndecoratedInsertRecord<Table> for [T] where T: UndecoratedInsertRecord<Table> {}
399
400impl<'a, T, Table> UndecoratedInsertRecord<Table> for BatchInsert<'a, T, Table> where
401 T: UndecoratedInsertRecord<Table>
402{
403}
404
405impl<T, Table> UndecoratedInsertRecord<Table> for OwnedBatchInsert<T, Table> where
406 T: UndecoratedInsertRecord<Table>
407{
408}
409
410impl<T, Table> UndecoratedInsertRecord<Table> for Vec<T> where [T]: UndecoratedInsertRecord<Table> {}
411
412impl<Lhs, Rhs> UndecoratedInsertRecord<Lhs::Table> for Eq<Lhs, Rhs> where Lhs: Column {}
413
414impl<Lhs, Rhs, Tab> UndecoratedInsertRecord<Tab> for Option<Eq<Lhs, Rhs>> where
415 Eq<Lhs, Rhs>: UndecoratedInsertRecord<Tab>
416{
417}
418
419impl<T, Table> UndecoratedInsertRecord<Table> for ValuesClause<T, Table> where
420 T: UndecoratedInsertRecord<Table>
421{
422}
423
424#[derive(Debug, Clone, Copy)]
425#[doc(hidden)]
426pub struct DefaultValues;
427
428impl<DB: Backend> CanInsertInSingleQuery<DB> for DefaultValues {
429 fn rows_to_insert(&self) -> Option<usize> {
430 Some(1)
431 }
432}
433
434impl<'a, Tab> Insertable<Tab> for &'a DefaultValues {
435 type Values = DefaultValues;
436
437 fn values(self) -> Self::Values {
438 *self
439 }
440}
441
442impl<DB> QueryFragment<DB> for DefaultValues
443where
444 DB: Backend + Any,
445{
446 #[cfg(feature = "mysql")]
447 fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
448 if TypeId::of::<DB>() == TypeId::of::<::mysql::Mysql>() {
450 out.push_sql("() VALUES ()");
451 } else {
452 out.push_sql("DEFAULT VALUES");
453 }
454 Ok(())
455 }
456
457 #[cfg(not(feature = "mysql"))]
458 fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
459 out.push_sql("DEFAULT VALUES");
460 Ok(())
461 }
462}
463
464#[doc(hidden)]
465#[derive(Debug, Clone, Copy)]
466pub struct ValuesClause<T, Tab> {
467 pub(crate) values: T,
468 _marker: PhantomData<Tab>,
469}
470
471impl<T: Default, Tab> Default for ValuesClause<T, Tab> {
472 fn default() -> Self {
473 Self::new(T::default())
474 }
475}
476
477impl<T, Tab> ValuesClause<T, Tab> {
478 pub(crate) fn new(values: T) -> Self {
479 Self {
480 values,
481 _marker: PhantomData,
482 }
483 }
484}
485
486impl<T, Tab, DB> CanInsertInSingleQuery<DB> for ValuesClause<T, Tab>
487where
488 DB: Backend,
489 T: CanInsertInSingleQuery<DB>,
490{
491 fn rows_to_insert(&self) -> Option<usize> {
492 self.values.rows_to_insert()
493 }
494}
495
496impl<T, Tab, DB> QueryFragment<DB> for ValuesClause<T, Tab>
497where
498 DB: Backend,
499 Tab: Table,
500 T: InsertValues<Tab, DB>,
501 DefaultValues: QueryFragment<DB>,
502{
503 fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
504 if self.values.is_noop()? {
505 DefaultValues.walk_ast(out)?;
506 } else {
507 out.push_sql("(");
508 self.values.column_names(out.reborrow())?;
509 out.push_sql(") VALUES (");
510 self.values.walk_ast(out.reborrow())?;
511 out.push_sql(")");
512 }
513 Ok(())
514 }
515}