Skip to main content

diesel/query_builder/insert_statement/
insert_with_default_for_sqlite.rs

1use super::{BatchInsert, InsertStatement};
2use crate::insertable::InsertValues;
3use crate::insertable::{CanInsertInSingleQuery, ColumnInsertValue, DefaultableColumnInsertValue};
4use crate::prelude::*;
5use crate::query_builder::debug_query::DebugBinds;
6use crate::query_builder::returning_clause::ReturningClause;
7use crate::query_builder::upsert::on_conflict_clause::OnConflictValues;
8use crate::query_builder::{AstPass, QueryBuilder, QueryId, ValuesClause};
9use crate::query_builder::{DebugQuery, QueryFragment};
10use crate::query_dsl::{methods::ExecuteDsl, LoadQuery};
11use crate::sqlite::{Sqlite, SqliteQueryBuilder};
12use std::fmt::{self, Debug, Display};
13
14pub trait DebugQueryHelper<ContainsDefaultableValue> {
15    fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
16    fn fmt_display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
17}
18
19impl<T, V, QId, Op, Ret, const STATIC_QUERY_ID: bool> DebugQueryHelper<Yes>
20    for DebugQuery<
21        '_,
22        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op, Ret>,
23        Sqlite,
24    >
25where
26    V: QueryFragment<Sqlite>,
27    T: Copy + QuerySource,
28    Op: Copy,
29    Ret: Copy,
30    for<'b> InsertStatement<T, &'b ValuesClause<V, T>, Op, Ret>: QueryFragment<Sqlite>,
31{
32    fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33        let mut statements = vec![String::from("BEGIN")];
34        for record in self.query.records.values.iter() {
35            let stmt = InsertStatement::new(
36                self.query.target,
37                record,
38                self.query.operator,
39                self.query.returning,
40            );
41            statements.push(crate::debug_query(&stmt).to_string());
42        }
43        statements.push("COMMIT".into());
44
45        f.debug_struct("Query")
46            .field("sql", &statements)
47            .field("binds", &[] as &[i32; 0])
48            .finish()
49    }
50
51    fn fmt_display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52        writeln!(f, "BEGIN;")?;
53        for record in self.query.records.values.iter() {
54            let stmt = InsertStatement::new(
55                self.query.target,
56                record,
57                self.query.operator,
58                self.query.returning,
59            );
60            writeln!(f, "{}", crate::debug_query(&stmt))?;
61        }
62        writeln!(f, "COMMIT;")?;
63        Ok(())
64    }
65}
66
67impl<'a, T, V, QId, Op, const STATIC_QUERY_ID: bool> DebugQueryHelper<No>
68    for DebugQuery<
69        'a,
70        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
71        Sqlite,
72    >
73where
74    T: Copy + Table,
75    Op: Copy + QueryFragment<Sqlite>,
76    SqliteBatchInsertWrapper<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>:
77        QueryFragment<Sqlite>,
78    V: CanInsertInSingleQuery<Sqlite>,
79    T::FromClause: QueryFragment<Sqlite>,
80{
81    fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82        self.fmt_helper(f, crate::query_builder::debug_query::debug)
83    }
84
85    fn fmt_display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86        self.fmt_helper(f, crate::query_builder::debug_query::display)
87    }
88}
89
90#[allow(unsafe_code)] // cast to transparent wrapper type
91impl<'a, T, V, QId, Op, const STATIC_QUERY_ID: bool>
92    DebugQuery<
93        'a,
94        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
95        Sqlite,
96    >
97where
98    T: Copy + Table,
99    Op: Copy + QueryFragment<Sqlite>,
100    SqliteBatchInsertWrapper<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>:
101        QueryFragment<Sqlite>,
102    V: CanInsertInSingleQuery<Sqlite>,
103    T::FromClause: QueryFragment<Sqlite>,
104{
105    fn fmt_helper(
106        &self,
107        f: &mut fmt::Formatter<'_>,
108        formatter: fn(String, &DebugBinds<'_>, &mut fmt::Formatter<'_>) -> fmt::Result,
109    ) -> fmt::Result {
110        // explicit destruct to make sure we use all  the fields
111        let InsertStatement {
112            operator,
113            target: _,
114            records,
115            returning,
116            into_clause,
117        } = self.query;
118        let records = unsafe {
119            // SAFETY:
120            // * SqliteBatchInsertWrapper is `#[repr(transparent)]` so this cast
121            // is allowed
122            &*(records as *const _
123                as *const SqliteBatchInsertWrapper<
124                    Vec<ValuesClause<V, T>>,
125                    T,
126                    QId,
127                    STATIC_QUERY_ID,
128                >)
129        };
130        let mut buffer = Vec::new();
131        let ast_pass = AstPass::debug_binds(&mut buffer, &Sqlite);
132        super::insert_statement::walk_ast_intern::<T, _, _, _, Sqlite>(
133            ast_pass,
134            records,
135            into_clause,
136            operator,
137            returning,
138        )
139        .map_err(|_| fmt::Error)?;
140        let mut query_builder = SqliteQueryBuilder::default();
141        let mut ast_pass_to_sql_options = Default::default();
142        let sql_pass = AstPass::to_sql(&mut query_builder, &mut ast_pass_to_sql_options, &Sqlite);
143        super::insert_statement::walk_ast_intern::<T, _, _, _, Sqlite>(
144            sql_pass,
145            records,
146            into_clause,
147            operator,
148            returning,
149        )
150        .map_err(|_| fmt::Error)?;
151        let query = query_builder.finish();
152        let debug_binds = crate::query_builder::debug_query::DebugBinds::new(&buffer);
153        formatter(query, &debug_binds, f)
154    }
155}
156
157impl<T, V, QId, Op, O, const STATIC_QUERY_ID: bool> Display
158    for DebugQuery<
159        '_,
160        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
161        Sqlite,
162    >
163where
164    T: QuerySource,
165    V: ContainsDefaultableValue<Out = O>,
166    Self: DebugQueryHelper<O>,
167{
168    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
169        self.fmt_display(f)
170    }
171}
172
173impl<T, V, QId, Op, O, const STATIC_QUERY_ID: bool> Debug
174    for DebugQuery<
175        '_,
176        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
177        Sqlite,
178    >
179where
180    T: QuerySource,
181    V: ContainsDefaultableValue<Out = O>,
182    Self: DebugQueryHelper<O>,
183{
184    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185        self.fmt_debug(f)
186    }
187}
188
189#[allow(missing_debug_implementations, missing_copy_implementations)]
190pub struct Yes;
191
192impl Default for Yes {
193    fn default() -> Self {
194        Yes
195    }
196}
197
198#[allow(missing_debug_implementations, missing_copy_implementations)]
199pub struct No;
200
201impl Default for No {
202    fn default() -> Self {
203        No
204    }
205}
206
207pub trait Any<Rhs> {
208    type Out: Any<Yes> + Any<No>;
209}
210
211impl Any<No> for No {
212    type Out = No;
213}
214
215impl Any<Yes> for No {
216    type Out = Yes;
217}
218
219impl Any<No> for Yes {
220    type Out = Yes;
221}
222
223impl Any<Yes> for Yes {
224    type Out = Yes;
225}
226
227pub trait ContainsDefaultableValue {
228    type Out: Any<Yes> + Any<No>;
229}
230
231impl<C, B> ContainsDefaultableValue for ColumnInsertValue<C, B> {
232    type Out = No;
233}
234
235impl<I> ContainsDefaultableValue for DefaultableColumnInsertValue<I> {
236    type Out = Yes;
237}
238
239impl<I, const SIZE: usize> ContainsDefaultableValue for [I; SIZE]
240where
241    I: ContainsDefaultableValue,
242{
243    type Out = I::Out;
244}
245
246impl<I, T> ContainsDefaultableValue for ValuesClause<I, T>
247where
248    I: ContainsDefaultableValue,
249{
250    type Out = I::Out;
251}
252
253impl<T> ContainsDefaultableValue for &T
254where
255    T: ContainsDefaultableValue,
256{
257    type Out = T::Out;
258}
259
260impl<V, T, QId, C, Op, O, const STATIC_QUERY_ID: bool> ExecuteDsl<C, Sqlite>
261    for InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>
262where
263    T: QuerySource,
264    C: Connection<Backend = Sqlite>,
265    V: ContainsDefaultableValue<Out = O>,
266    O: Default,
267    (O, Self): ExecuteDsl<C, Sqlite>,
268{
269    fn execute(query: Self, conn: &mut C) -> QueryResult<usize> {
270        <(O, Self) as ExecuteDsl<C, Sqlite>>::execute((O::default(), query), conn)
271    }
272}
273
274impl<V, T, QId, C, Op, O, Target, ConflictOpt, const STATIC_QUERY_ID: bool> ExecuteDsl<C, Sqlite>
275    for InsertStatement<
276        T,
277        OnConflictValues<
278            BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>,
279            Target,
280            ConflictOpt,
281        >,
282        Op,
283    >
284where
285    T: QuerySource,
286    C: Connection<Backend = Sqlite>,
287    V: ContainsDefaultableValue<Out = O>,
288    O: Default,
289    (O, Self): ExecuteDsl<C, Sqlite>,
290{
291    fn execute(query: Self, conn: &mut C) -> QueryResult<usize> {
292        <(O, Self) as ExecuteDsl<C, Sqlite>>::execute((O::default(), query), conn)
293    }
294}
295
296impl<V, T, QId, C, Op, const STATIC_QUERY_ID: bool> ExecuteDsl<C, Sqlite>
297    for (
298        Yes,
299        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
300    )
301where
302    C: Connection<Backend = Sqlite>,
303    T: Table + Copy + QueryId + 'static,
304    T::FromClause: QueryFragment<Sqlite>,
305    Op: Copy + QueryId + QueryFragment<Sqlite>,
306    V: InsertValues<Sqlite, T> + CanInsertInSingleQuery<Sqlite> + QueryId,
307{
308    fn execute((Yes, query): Self, conn: &mut C) -> QueryResult<usize> {
309        conn.transaction(|conn| {
310            let mut result = 0;
311            for record in &query.records.values {
312                let stmt =
313                    InsertStatement::new(query.target, record, query.operator, query.returning);
314                result += stmt.execute(conn)?;
315            }
316            Ok(result)
317        })
318    }
319}
320
321impl<'query, V, T, QId, Op, O, U, B, const STATIC_QUERY_ID: bool>
322    LoadQuery<'query, SqliteConnection, U, B>
323    for InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>
324where
325    T: QuerySource,
326    V: ContainsDefaultableValue<Out = O>,
327    O: Default,
328    (O, Self): LoadQuery<'query, SqliteConnection, U, B>,
329{
330    type RowIter<'conn> = <(O, Self) as LoadQuery<'query, SqliteConnection, U, B>>::RowIter<'conn>;
331
332    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
333        <(O, Self) as LoadQuery<'query, SqliteConnection, U, B>>::internal_load(
334            (O::default(), self),
335            conn,
336        )
337    }
338}
339
340impl<'query, V, T, QId, Op, Ret, O, U, B, const STATIC_QUERY_ID: bool>
341    LoadQuery<'query, SqliteConnection, U, B>
342    for InsertStatement<
343        T,
344        BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>,
345        Op,
346        ReturningClause<Ret>,
347    >
348where
349    T: QuerySource,
350    V: ContainsDefaultableValue<Out = O>,
351    O: Default,
352    (O, Self): LoadQuery<'query, SqliteConnection, U, B>,
353{
354    type RowIter<'conn> = <(O, Self) as LoadQuery<'query, SqliteConnection, U, B>>::RowIter<'conn>;
355
356    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
357        <(O, Self) as LoadQuery<'query, SqliteConnection, U, B>>::internal_load(
358            (O::default(), self),
359            conn,
360        )
361    }
362}
363
364impl<'query, V, T, QId, Op, O, U, B, Target, ConflictOpt, const STATIC_QUERY_ID: bool>
365    LoadQuery<'query, SqliteConnection, U, B>
366    for InsertStatement<
367        T,
368        OnConflictValues<
369            BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>,
370            Target,
371            ConflictOpt,
372        >,
373        Op,
374    >
375where
376    T: QuerySource,
377    V: ContainsDefaultableValue<Out = O>,
378    O: Default,
379    (O, Self): LoadQuery<'query, SqliteConnection, U, B>,
380{
381    type RowIter<'conn> = <(O, Self) as LoadQuery<'query, SqliteConnection, U, B>>::RowIter<'conn>;
382
383    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
384        <(O, Self) as LoadQuery<'query, SqliteConnection, U, B>>::internal_load(
385            (O::default(), self),
386            conn,
387        )
388    }
389}
390
391impl<'query, V, T, QId, Op, Ret, O, U, B, Target, ConflictOpt, const STATIC_QUERY_ID: bool>
392    LoadQuery<'query, SqliteConnection, U, B>
393    for InsertStatement<
394        T,
395        OnConflictValues<
396            BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>,
397            Target,
398            ConflictOpt,
399        >,
400        Op,
401        ReturningClause<Ret>,
402    >
403where
404    T: QuerySource,
405    V: ContainsDefaultableValue<Out = O>,
406    O: Default,
407    (O, Self): LoadQuery<'query, SqliteConnection, U, B>,
408{
409    type RowIter<'conn> = <(O, Self) as LoadQuery<'query, SqliteConnection, U, B>>::RowIter<'conn>;
410
411    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
412        <(O, Self) as LoadQuery<'query, SqliteConnection, U, B>>::internal_load(
413            (O::default(), self),
414            conn,
415        )
416    }
417}
418
419impl<V, T, QId, Op, O, const STATIC_QUERY_ID: bool> RunQueryDsl<SqliteConnection>
420    for (
421        O,
422        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
423    )
424where
425    T: QuerySource,
426    V: ContainsDefaultableValue<Out = O>,
427    O: Default,
428    InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>:
429        RunQueryDsl<SqliteConnection>,
430{
431}
432
433impl<V, T, QId, Op, Ret, O, const STATIC_QUERY_ID: bool> RunQueryDsl<SqliteConnection>
434    for (
435        O,
436        InsertStatement<
437            T,
438            BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>,
439            Op,
440            ReturningClause<Ret>,
441        >,
442    )
443where
444    T: QuerySource,
445    V: ContainsDefaultableValue<Out = O>,
446    O: Default,
447    InsertStatement<
448        T,
449        BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>,
450        Op,
451        ReturningClause<Ret>,
452    >: RunQueryDsl<SqliteConnection>,
453{
454}
455
456impl<V, T, QId, Op, O, Target, ConflictOpt, const STATIC_QUERY_ID: bool>
457    RunQueryDsl<SqliteConnection>
458    for (
459        O,
460        InsertStatement<
461            T,
462            OnConflictValues<
463                BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>,
464                Target,
465                ConflictOpt,
466            >,
467            Op,
468        >,
469    )
470where
471    T: QuerySource,
472    V: ContainsDefaultableValue<Out = O>,
473    O: Default,
474    InsertStatement<
475        T,
476        OnConflictValues<
477            BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>,
478            Target,
479            ConflictOpt,
480        >,
481        Op,
482    >: RunQueryDsl<SqliteConnection>,
483{
484}
485
486impl<V, T, QId, Op, Ret, O, Target, ConflictOpt, const STATIC_QUERY_ID: bool>
487    RunQueryDsl<SqliteConnection>
488    for (
489        O,
490        InsertStatement<
491            T,
492            OnConflictValues<
493                BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>,
494                Target,
495                ConflictOpt,
496            >,
497            Op,
498            ReturningClause<Ret>,
499        >,
500    )
501where
502    T: QuerySource,
503    V: ContainsDefaultableValue<Out = O>,
504    O: Default,
505    InsertStatement<
506        T,
507        OnConflictValues<
508            BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>,
509            Target,
510            ConflictOpt,
511        >,
512        Op,
513        ReturningClause<Ret>,
514    >: RunQueryDsl<SqliteConnection>,
515{
516}
517
518#[diagnostic::do_not_recommend]
519impl<'query, V, T, QId, Op, U, B, const STATIC_QUERY_ID: bool>
520    LoadQuery<'query, SqliteConnection, U, B>
521    for (
522        Yes,
523        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
524    )
525where
526    T: Table + Copy + QueryId + 'static,
527    Op: Copy + QueryId + QueryFragment<Sqlite>,
528    InsertStatement<T, ValuesClause<V, T>, Op>: LoadQuery<'query, SqliteConnection, U, B>,
529    Self: RunQueryDsl<SqliteConnection>,
530{
531    type RowIter<'conn> = std::vec::IntoIter<QueryResult<U>>;
532
533    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
534        let (Yes, query) = self;
535
536        conn.transaction(|conn| {
537            let mut results = Vec::with_capacity(query.records.values.len());
538
539            for record in query.records.values {
540                let stmt =
541                    InsertStatement::new(query.target, record, query.operator, query.returning);
542
543                let result = stmt
544                    .internal_load(conn)?
545                    .next()
546                    .ok_or(crate::result::Error::NotFound)?;
547
548                match &result {
549                    Ok(_) | Err(crate::result::Error::DeserializationError(_)) => {
550                        results.push(result)
551                    }
552                    Err(_) => {
553                        result?;
554                    }
555                };
556            }
557
558            Ok(results.into_iter())
559        })
560    }
561}
562
563#[diagnostic::do_not_recommend]
564impl<'query, V, T, QId, Op, Ret, U, B, const STATIC_QUERY_ID: bool>
565    LoadQuery<'query, SqliteConnection, U, B>
566    for (
567        Yes,
568        InsertStatement<
569            T,
570            BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>,
571            Op,
572            ReturningClause<Ret>,
573        >,
574    )
575where
576    T: Table + Copy + QueryId + 'static,
577    Op: Copy + QueryId + QueryFragment<Sqlite>,
578    ReturningClause<Ret>: Copy,
579    InsertStatement<T, ValuesClause<V, T>, Op, ReturningClause<Ret>>:
580        LoadQuery<'query, SqliteConnection, U, B>,
581    Self: RunQueryDsl<SqliteConnection>,
582{
583    type RowIter<'conn> = std::vec::IntoIter<QueryResult<U>>;
584
585    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
586        let (Yes, query) = self;
587
588        conn.transaction(|conn| {
589            let mut results = Vec::with_capacity(query.records.values.len());
590
591            for record in query.records.values {
592                let stmt =
593                    InsertStatement::new(query.target, record, query.operator, query.returning);
594
595                let result = stmt
596                    .internal_load(conn)?
597                    .next()
598                    .ok_or(crate::result::Error::NotFound)?;
599
600                match &result {
601                    Ok(_) | Err(crate::result::Error::DeserializationError(_)) => {
602                        results.push(result)
603                    }
604                    Err(_) => {
605                        result?;
606                    }
607                };
608            }
609
610            Ok(results.into_iter())
611        })
612    }
613}
614
615#[diagnostic::do_not_recommend]
616impl<'query, V, T, QId, Op, U, B, Target, ConflictOpt, const STATIC_QUERY_ID: bool>
617    LoadQuery<'query, SqliteConnection, U, B>
618    for (
619        Yes,
620        InsertStatement<
621            T,
622            OnConflictValues<
623                BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>,
624                Target,
625                ConflictOpt,
626            >,
627            Op,
628        >,
629    )
630where
631    T: Table + Copy + QueryId + 'static,
632    T::FromClause: Copy,
633    Op: Copy,
634    Target: Copy,
635    ConflictOpt: Copy,
636    InsertStatement<T, OnConflictValues<ValuesClause<V, T>, Target, ConflictOpt>, Op>:
637        LoadQuery<'query, SqliteConnection, U, B>,
638    Self: RunQueryDsl<SqliteConnection>,
639{
640    type RowIter<'conn> = std::vec::IntoIter<QueryResult<U>>;
641
642    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
643        let (Yes, query) = self;
644
645        conn.transaction(|conn| {
646            let mut results = Vec::with_capacity(query.records.values.values.len());
647
648            for record in query.records.values.values {
649                let stmt = InsertStatement {
650                    operator: query.operator,
651                    target: query.target,
652                    records: OnConflictValues {
653                        values: record,
654                        target: query.records.target,
655                        action: query.records.action,
656                        where_clause: query.records.where_clause,
657                    },
658                    returning: query.returning,
659                    into_clause: query.into_clause,
660                };
661
662                let result = stmt
663                    .internal_load(conn)?
664                    .next()
665                    .ok_or(crate::result::Error::NotFound)?;
666
667                match &result {
668                    Ok(_) | Err(crate::result::Error::DeserializationError(_)) => {
669                        results.push(result)
670                    }
671                    Err(_) => {
672                        result?;
673                    }
674                };
675            }
676
677            Ok(results.into_iter())
678        })
679    }
680}
681
682#[diagnostic::do_not_recommend]
683impl<'query, V, T, QId, Op, Ret, U, B, Target, ConflictOpt, const STATIC_QUERY_ID: bool>
684    LoadQuery<'query, SqliteConnection, U, B>
685    for (
686        Yes,
687        InsertStatement<
688            T,
689            OnConflictValues<
690                BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>,
691                Target,
692                ConflictOpt,
693            >,
694            Op,
695            ReturningClause<Ret>,
696        >,
697    )
698where
699    T: Table + Copy + QueryId + 'static,
700    T::FromClause: Copy,
701    Op: Copy,
702    ReturningClause<Ret>: Copy,
703    Target: Copy,
704    ConflictOpt: Copy,
705    InsertStatement<
706        T,
707        OnConflictValues<ValuesClause<V, T>, Target, ConflictOpt>,
708        Op,
709        ReturningClause<Ret>,
710    >: LoadQuery<'query, SqliteConnection, U, B>,
711    Self: RunQueryDsl<SqliteConnection>,
712{
713    type RowIter<'conn> = std::vec::IntoIter<QueryResult<U>>;
714
715    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
716        let (Yes, query) = self;
717
718        conn.transaction(|conn| {
719            let mut results = Vec::with_capacity(query.records.values.values.len());
720
721            for record in query.records.values.values {
722                let stmt = InsertStatement {
723                    operator: query.operator,
724                    target: query.target,
725                    records: OnConflictValues {
726                        values: record,
727                        target: query.records.target,
728                        action: query.records.action,
729                        where_clause: query.records.where_clause,
730                    },
731                    returning: query.returning,
732                    into_clause: query.into_clause,
733                };
734
735                let result = stmt
736                    .internal_load(conn)?
737                    .next()
738                    .ok_or(crate::result::Error::NotFound)?;
739
740                match &result {
741                    Ok(_) | Err(crate::result::Error::DeserializationError(_)) => {
742                        results.push(result)
743                    }
744                    Err(_) => {
745                        result?;
746                    }
747                };
748            }
749
750            Ok(results.into_iter())
751        })
752    }
753}
754
755#[allow(missing_debug_implementations, missing_copy_implementations)]
756#[repr(transparent)]
757pub struct SqliteBatchInsertWrapper<V, T, QId, const STATIC_QUERY_ID: bool>(
758    BatchInsert<V, T, QId, STATIC_QUERY_ID>,
759);
760
761impl<V, Tab, QId, const STATIC_QUERY_ID: bool> QueryFragment<Sqlite>
762    for SqliteBatchInsertWrapper<Vec<ValuesClause<V, Tab>>, Tab, QId, STATIC_QUERY_ID>
763where
764    ValuesClause<V, Tab>: QueryFragment<Sqlite>,
765    V: QueryFragment<Sqlite>,
766{
767    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Sqlite>) -> QueryResult<()> {
768        if !STATIC_QUERY_ID {
769            out.unsafe_to_cache_prepared();
770        }
771
772        let mut values = self.0.values.iter();
773        if let Some(value) = values.next() {
774            value.walk_ast(out.reborrow())?;
775        }
776        for value in values {
777            out.push_sql(", (");
778            value.values.walk_ast(out.reborrow())?;
779            out.push_sql(")");
780        }
781        Ok(())
782    }
783}
784
785#[allow(missing_copy_implementations, missing_debug_implementations)]
786#[repr(transparent)]
787pub struct SqliteCanInsertInSingleQueryHelper<T: ?Sized>(T);
788
789impl<V, T, QId, const STATIC_QUERY_ID: bool> CanInsertInSingleQuery<Sqlite>
790    for SqliteBatchInsertWrapper<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>
791where
792    // We constrain that here on an internal helper type
793    // to make sure that this does not accidentally leak
794    // so that none does really implement normal batch
795    // insert for inserts with default values here
796    SqliteCanInsertInSingleQueryHelper<V>: CanInsertInSingleQuery<Sqlite>,
797{
798    fn rows_to_insert(&self) -> Option<usize> {
799        Some(self.0.values.len())
800    }
801}
802
803impl<T> CanInsertInSingleQuery<Sqlite> for SqliteCanInsertInSingleQueryHelper<T>
804where
805    T: CanInsertInSingleQuery<Sqlite>,
806{
807    fn rows_to_insert(&self) -> Option<usize> {
808        self.0.rows_to_insert()
809    }
810}
811
812impl<V, T, QId, const STATIC_QUERY_ID: bool> QueryId
813    for SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>
814where
815    BatchInsert<V, T, QId, STATIC_QUERY_ID>: QueryId,
816{
817    type QueryId = <BatchInsert<V, T, QId, STATIC_QUERY_ID> as QueryId>::QueryId;
818
819    const HAS_STATIC_QUERY_ID: bool =
820        <BatchInsert<V, T, QId, STATIC_QUERY_ID> as QueryId>::HAS_STATIC_QUERY_ID;
821}
822
823impl<V, T, QId, C, Op, const STATIC_QUERY_ID: bool> ExecuteDsl<C, Sqlite>
824    for (
825        No,
826        InsertStatement<T, BatchInsert<V, T, QId, STATIC_QUERY_ID>, Op>,
827    )
828where
829    C: Connection<Backend = Sqlite>,
830    T: Table + QueryId + 'static,
831    T::FromClause: QueryFragment<Sqlite>,
832    Op: QueryFragment<Sqlite> + QueryId,
833    SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>:
834        QueryFragment<Sqlite> + QueryId + CanInsertInSingleQuery<Sqlite>,
835{
836    fn execute((No, query): Self, conn: &mut C) -> QueryResult<usize> {
837        let query = InsertStatement {
838            records: SqliteBatchInsertWrapper(query.records),
839            operator: query.operator,
840            target: query.target,
841            returning: query.returning,
842            into_clause: query.into_clause,
843        };
844        query.execute(conn)
845    }
846}
847
848impl<V, T, QId, C, Op, Target, ConflictOpt, const STATIC_QUERY_ID: bool> ExecuteDsl<C, Sqlite>
849    for (
850        No,
851        InsertStatement<
852            T,
853            OnConflictValues<BatchInsert<V, T, QId, STATIC_QUERY_ID>, Target, ConflictOpt>,
854            Op,
855        >,
856    )
857where
858    C: Connection<Backend = Sqlite>,
859    T: Table + QueryId + 'static,
860    T::FromClause: QueryFragment<Sqlite>,
861    Op: QueryFragment<Sqlite> + QueryId,
862    OnConflictValues<SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>, Target, ConflictOpt>:
863        QueryFragment<Sqlite> + CanInsertInSingleQuery<Sqlite> + QueryId,
864{
865    fn execute((No, query): Self, conn: &mut C) -> QueryResult<usize> {
866        let query = InsertStatement {
867            operator: query.operator,
868            target: query.target,
869            records: OnConflictValues {
870                values: SqliteBatchInsertWrapper(query.records.values),
871                target: query.records.target,
872                action: query.records.action,
873                where_clause: query.records.where_clause,
874            },
875            returning: query.returning,
876            into_clause: query.into_clause,
877        };
878        query.execute(conn)
879    }
880}
881
882#[diagnostic::do_not_recommend]
883impl<'query, V, T, QId, Op, U, B, const STATIC_QUERY_ID: bool>
884    LoadQuery<'query, SqliteConnection, U, B>
885    for (
886        No,
887        InsertStatement<T, BatchInsert<V, T, QId, STATIC_QUERY_ID>, Op>,
888    )
889where
890    T: Table + QueryId + 'static,
891    InsertStatement<T, SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>, Op>:
892        LoadQuery<'query, SqliteConnection, U, B>,
893    Self: RunQueryDsl<SqliteConnection>,
894{
895    type RowIter<'conn> = <InsertStatement<
896        T,
897        SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>,
898        Op,
899    > as LoadQuery<'query, SqliteConnection, U, B>>::RowIter<'conn>;
900
901    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
902        let (No, query) = self;
903
904        let query = InsertStatement {
905            records: SqliteBatchInsertWrapper(query.records),
906            operator: query.operator,
907            target: query.target,
908            returning: query.returning,
909            into_clause: query.into_clause,
910        };
911
912        query.internal_load(conn)
913    }
914}
915
916#[diagnostic::do_not_recommend]
917impl<'query, V, T, QId, Op, Ret, U, B, const STATIC_QUERY_ID: bool>
918    LoadQuery<'query, SqliteConnection, U, B>
919    for (
920        No,
921        InsertStatement<T, BatchInsert<V, T, QId, STATIC_QUERY_ID>, Op, ReturningClause<Ret>>,
922    )
923where
924    T: Table + QueryId + 'static,
925    InsertStatement<
926        T,
927        SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>,
928        Op,
929        ReturningClause<Ret>,
930    >: LoadQuery<'query, SqliteConnection, U, B>,
931    Self: RunQueryDsl<SqliteConnection>,
932{
933    type RowIter<'conn> = <InsertStatement<
934        T,
935        SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>,
936        Op,
937        ReturningClause<Ret>,
938    > as LoadQuery<'query, SqliteConnection, U, B>>::RowIter<'conn>;
939
940    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
941        let (No, query) = self;
942
943        let query = InsertStatement {
944            records: SqliteBatchInsertWrapper(query.records),
945            operator: query.operator,
946            target: query.target,
947            returning: query.returning,
948            into_clause: query.into_clause,
949        };
950
951        query.internal_load(conn)
952    }
953}
954
955#[diagnostic::do_not_recommend]
956impl<'query, V, T, QId, Op, U, B, Target, ConflictOpt, const STATIC_QUERY_ID: bool>
957    LoadQuery<'query, SqliteConnection, U, B>
958    for (
959        No,
960        InsertStatement<
961            T,
962            OnConflictValues<BatchInsert<V, T, QId, STATIC_QUERY_ID>, Target, ConflictOpt>,
963            Op,
964        >,
965    )
966where
967    T: Table + QueryId + 'static,
968    InsertStatement<
969        T,
970        OnConflictValues<SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>, Target, ConflictOpt>,
971        Op,
972    >: LoadQuery<'query, SqliteConnection, U, B>,
973    Self: RunQueryDsl<SqliteConnection>,
974{
975    type RowIter<'conn> = <InsertStatement<
976        T,
977        OnConflictValues<SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>, Target, ConflictOpt>,
978        Op,
979    > as LoadQuery<'query, SqliteConnection, U, B>>::RowIter<'conn>;
980
981    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
982        let (No, query) = self;
983
984        let query = InsertStatement {
985            operator: query.operator,
986            target: query.target,
987            records: OnConflictValues {
988                values: SqliteBatchInsertWrapper(query.records.values),
989                target: query.records.target,
990                action: query.records.action,
991                where_clause: query.records.where_clause,
992            },
993            returning: query.returning,
994            into_clause: query.into_clause,
995        };
996
997        query.internal_load(conn)
998    }
999}
1000
1001#[diagnostic::do_not_recommend]
1002impl<'query, V, T, QId, Op, Ret, U, B, Target, ConflictOpt, const STATIC_QUERY_ID: bool>
1003    LoadQuery<'query, SqliteConnection, U, B>
1004    for (
1005        No,
1006        InsertStatement<
1007            T,
1008            OnConflictValues<BatchInsert<V, T, QId, STATIC_QUERY_ID>, Target, ConflictOpt>,
1009            Op,
1010            ReturningClause<Ret>,
1011        >,
1012    )
1013where
1014    T: Table + QueryId + 'static,
1015    InsertStatement<
1016        T,
1017        OnConflictValues<SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>, Target, ConflictOpt>,
1018        Op,
1019        ReturningClause<Ret>,
1020    >: LoadQuery<'query, SqliteConnection, U, B>,
1021    Self: RunQueryDsl<SqliteConnection>,
1022{
1023    type RowIter<'conn> = <InsertStatement<
1024        T,
1025        OnConflictValues<SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>, Target, ConflictOpt>,
1026        Op,
1027        ReturningClause<Ret>,
1028    > as LoadQuery<'query, SqliteConnection, U, B>>::RowIter<'conn>;
1029
1030    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
1031        let (No, query) = self;
1032
1033        let query = InsertStatement {
1034            operator: query.operator,
1035            target: query.target,
1036            records: OnConflictValues {
1037                values: SqliteBatchInsertWrapper(query.records.values),
1038                target: query.records.target,
1039                action: query.records.action,
1040                where_clause: query.records.where_clause,
1041            },
1042            returning: query.returning,
1043            into_clause: query.into_clause,
1044        };
1045
1046        query.internal_load(conn)
1047    }
1048}
1049
1050macro_rules! tuple_impls {
1051        ($(
1052            $Tuple:tt {
1053                $(($idx:tt) -> $T:ident, $ST:ident, $TT:ident,)+
1054            }
1055        )+) => {
1056            $(
1057                impl_contains_defaultable_value!($($T,)*);
1058            )*
1059        }
1060    }
1061
1062macro_rules! impl_contains_defaultable_value {
1063      (
1064        @build
1065        start_ts = [$($ST: ident,)*],
1066        ts = [$T1: ident,],
1067        bounds = [$($bounds: tt)*],
1068        out = [$($out: tt)*],
1069    )=> {
1070        impl<$($ST,)*> ContainsDefaultableValue for ($($ST,)*)
1071        where
1072            $($ST: ContainsDefaultableValue,)*
1073            $($bounds)*
1074            $T1::Out: Any<$($out)*>,
1075        {
1076            type Out = <$T1::Out as Any<$($out)*>>::Out;
1077        }
1078
1079    };
1080    (
1081        @build
1082        start_ts = [$($ST: ident,)*],
1083        ts = [$T1: ident, $($T: ident,)+],
1084        bounds = [$($bounds: tt)*],
1085        out = [$($out: tt)*],
1086    )=> {
1087        impl_contains_defaultable_value! {
1088            @build
1089            start_ts = [$($ST,)*],
1090            ts = [$($T,)*],
1091            bounds = [$($bounds)* $T1::Out: Any<$($out)*>,],
1092            out = [<$T1::Out as Any<$($out)*>>::Out],
1093        }
1094    };
1095    ($T1: ident, $($T: ident,)+) => {
1096        impl_contains_defaultable_value! {
1097            @build
1098            start_ts = [$T1, $($T,)*],
1099            ts = [$($T,)*],
1100            bounds = [],
1101            out = [$T1::Out],
1102        }
1103    };
1104    ($T1: ident,) => {
1105        impl<$T1> ContainsDefaultableValue for ($T1,)
1106        where $T1: ContainsDefaultableValue,
1107        {
1108            type Out = <$T1 as ContainsDefaultableValue>::Out;
1109        }
1110    }
1111}
1112
1113diesel_derives::__diesel_for_each_tuple!(tuple_impls);