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::upsert::on_conflict_clause::OnConflictValues;
7use crate::query_builder::{AstPass, QueryBuilder, QueryId, ValuesClause};
8use crate::query_builder::{DebugQuery, QueryFragment};
9use crate::query_dsl::{methods::ExecuteDsl, LoadQuery};
10use crate::sqlite::{Sqlite, SqliteQueryBuilder};
11use std::fmt::{self, Debug, Display};
12
13pub trait DebugQueryHelper<ContainsDefaultableValue> {
14    fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
15    fn fmt_display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
16}
17
18impl<T, V, QId, Op, Ret, const STATIC_QUERY_ID: bool> DebugQueryHelper<Yes>
19    for DebugQuery<
20        '_,
21        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op, Ret>,
22        Sqlite,
23    >
24where
25    V: QueryFragment<Sqlite>,
26    T: Copy + QuerySource,
27    Op: Copy,
28    Ret: Copy,
29    for<'b> InsertStatement<T, &'b ValuesClause<V, T>, Op, Ret>: QueryFragment<Sqlite>,
30{
31    fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32        let mut statements = vec![String::from("BEGIN")];
33        for record in self.query.records.values.iter() {
34            let stmt = InsertStatement::new(
35                self.query.target,
36                record,
37                self.query.operator,
38                self.query.returning,
39            );
40            statements.push(crate::debug_query(&stmt).to_string());
41        }
42        statements.push("COMMIT".into());
43
44        f.debug_struct("Query")
45            .field("sql", &statements)
46            .field("binds", &[] as &[i32; 0])
47            .finish()
48    }
49
50    fn fmt_display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51        writeln!(f, "BEGIN;")?;
52        for record in self.query.records.values.iter() {
53            let stmt = InsertStatement::new(
54                self.query.target,
55                record,
56                self.query.operator,
57                self.query.returning,
58            );
59            writeln!(f, "{}", crate::debug_query(&stmt))?;
60        }
61        writeln!(f, "COMMIT;")?;
62        Ok(())
63    }
64}
65
66impl<'a, T, V, QId, Op, const STATIC_QUERY_ID: bool> DebugQueryHelper<No>
67    for DebugQuery<
68        'a,
69        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
70        Sqlite,
71    >
72where
73    T: Copy + Table,
74    Op: Copy + QueryFragment<Sqlite>,
75    SqliteBatchInsertWrapper<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>:
76        QueryFragment<Sqlite>,
77    V: CanInsertInSingleQuery<Sqlite>,
78    T::FromClause: QueryFragment<Sqlite>,
79{
80    fn fmt_debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81        self.fmt_helper(f, crate::query_builder::debug_query::debug)
82    }
83
84    fn fmt_display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85        self.fmt_helper(f, crate::query_builder::debug_query::display)
86    }
87}
88
89#[allow(unsafe_code)] // cast to transparent wrapper type
90impl<'a, T, V, QId, Op, const STATIC_QUERY_ID: bool>
91    DebugQuery<
92        'a,
93        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
94        Sqlite,
95    >
96where
97    T: Copy + Table,
98    Op: Copy + QueryFragment<Sqlite>,
99    SqliteBatchInsertWrapper<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>:
100        QueryFragment<Sqlite>,
101    V: CanInsertInSingleQuery<Sqlite>,
102    T::FromClause: QueryFragment<Sqlite>,
103{
104    fn fmt_helper(
105        &self,
106        f: &mut fmt::Formatter<'_>,
107        formatter: fn(String, &DebugBinds<'_>, &mut fmt::Formatter<'_>) -> fmt::Result,
108    ) -> fmt::Result {
109        // explicit destruct to make sure we use all  the fields
110        let InsertStatement {
111            operator,
112            target: _,
113            records,
114            returning,
115            into_clause,
116        } = self.query;
117        let records = unsafe {
118            // SAFETY:
119            // * SqliteBatchInsertWrapper is `#[repr(transparent)]` so this cast
120            // is allowed
121            &*(records as *const _
122                as *const SqliteBatchInsertWrapper<
123                    Vec<ValuesClause<V, T>>,
124                    T,
125                    QId,
126                    STATIC_QUERY_ID,
127                >)
128        };
129        let mut buffer = Vec::new();
130        let ast_pass = AstPass::debug_binds(&mut buffer, &Sqlite);
131        super::insert_statement::walk_ast_intern::<T, _, _, _, Sqlite>(
132            ast_pass,
133            records,
134            into_clause,
135            operator,
136            returning,
137        )
138        .map_err(|_| fmt::Error)?;
139        let mut query_builder = SqliteQueryBuilder::default();
140        let mut ast_pass_to_sql_options = Default::default();
141        let sql_pass = AstPass::to_sql(&mut query_builder, &mut ast_pass_to_sql_options, &Sqlite);
142        super::insert_statement::walk_ast_intern::<T, _, _, _, Sqlite>(
143            sql_pass,
144            records,
145            into_clause,
146            operator,
147            returning,
148        )
149        .map_err(|_| fmt::Error)?;
150        let query = query_builder.finish();
151        let debug_binds = crate::query_builder::debug_query::DebugBinds::new(&buffer);
152        formatter(query, &debug_binds, f)
153    }
154}
155
156impl<T, V, QId, Op, O, const STATIC_QUERY_ID: bool> Display
157    for DebugQuery<
158        '_,
159        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
160        Sqlite,
161    >
162where
163    T: QuerySource,
164    V: ContainsDefaultableValue<Out = O>,
165    Self: DebugQueryHelper<O>,
166{
167    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168        self.fmt_display(f)
169    }
170}
171
172impl<T, V, QId, Op, O, const STATIC_QUERY_ID: bool> Debug
173    for DebugQuery<
174        '_,
175        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
176        Sqlite,
177    >
178where
179    T: QuerySource,
180    V: ContainsDefaultableValue<Out = O>,
181    Self: DebugQueryHelper<O>,
182{
183    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184        self.fmt_debug(f)
185    }
186}
187
188#[allow(missing_debug_implementations, missing_copy_implementations)]
189pub struct Yes;
190
191impl Default for Yes {
192    fn default() -> Self {
193        Yes
194    }
195}
196
197#[allow(missing_debug_implementations, missing_copy_implementations)]
198pub struct No;
199
200impl Default for No {
201    fn default() -> Self {
202        No
203    }
204}
205
206pub trait Any<Rhs> {
207    type Out: Any<Yes> + Any<No>;
208}
209
210impl Any<No> for No {
211    type Out = No;
212}
213
214impl Any<Yes> for No {
215    type Out = Yes;
216}
217
218impl Any<No> for Yes {
219    type Out = Yes;
220}
221
222impl Any<Yes> for Yes {
223    type Out = Yes;
224}
225
226pub trait ContainsDefaultableValue {
227    type Out: Any<Yes> + Any<No>;
228}
229
230impl<C, B> ContainsDefaultableValue for ColumnInsertValue<C, B> {
231    type Out = No;
232}
233
234impl<I> ContainsDefaultableValue for DefaultableColumnInsertValue<I> {
235    type Out = Yes;
236}
237
238impl<I, const SIZE: usize> ContainsDefaultableValue for [I; SIZE]
239where
240    I: ContainsDefaultableValue,
241{
242    type Out = I::Out;
243}
244
245impl<I, T> ContainsDefaultableValue for ValuesClause<I, T>
246where
247    I: ContainsDefaultableValue,
248{
249    type Out = I::Out;
250}
251
252impl<T> ContainsDefaultableValue for &T
253where
254    T: ContainsDefaultableValue,
255{
256    type Out = T::Out;
257}
258
259impl<V, T, QId, C, Op, O, const STATIC_QUERY_ID: bool> ExecuteDsl<C, Sqlite>
260    for InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>
261where
262    T: QuerySource,
263    C: Connection<Backend = Sqlite>,
264    V: ContainsDefaultableValue<Out = O>,
265    O: Default,
266    (O, Self): ExecuteDsl<C, Sqlite>,
267{
268    fn execute(query: Self, conn: &mut C) -> QueryResult<usize> {
269        <(O, Self) as ExecuteDsl<C, Sqlite>>::execute((O::default(), query), conn)
270    }
271}
272
273impl<V, T, QId, C, Op, O, Target, ConflictOpt, const STATIC_QUERY_ID: bool> ExecuteDsl<C, Sqlite>
274    for InsertStatement<
275        T,
276        OnConflictValues<
277            BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>,
278            Target,
279            ConflictOpt,
280        >,
281        Op,
282    >
283where
284    T: QuerySource,
285    C: Connection<Backend = Sqlite>,
286    V: ContainsDefaultableValue<Out = O>,
287    O: Default,
288    (O, Self): ExecuteDsl<C, Sqlite>,
289{
290    fn execute(query: Self, conn: &mut C) -> QueryResult<usize> {
291        <(O, Self) as ExecuteDsl<C, Sqlite>>::execute((O::default(), query), conn)
292    }
293}
294
295impl<V, T, QId, C, Op, const STATIC_QUERY_ID: bool> ExecuteDsl<C, Sqlite>
296    for (
297        Yes,
298        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
299    )
300where
301    C: Connection<Backend = Sqlite>,
302    T: Table + Copy + QueryId + 'static,
303    T::FromClause: QueryFragment<Sqlite>,
304    Op: Copy + QueryId + QueryFragment<Sqlite>,
305    V: InsertValues<Sqlite, T> + CanInsertInSingleQuery<Sqlite> + QueryId,
306{
307    fn execute((Yes, query): Self, conn: &mut C) -> QueryResult<usize> {
308        conn.transaction(|conn| {
309            let mut result = 0;
310            for record in &query.records.values {
311                let stmt =
312                    InsertStatement::new(query.target, record, query.operator, query.returning);
313                result += stmt.execute(conn)?;
314            }
315            Ok(result)
316        })
317    }
318}
319
320impl<'query, V, T, QId, Op, O, U, B, const STATIC_QUERY_ID: bool>
321    LoadQuery<'query, SqliteConnection, U, B>
322    for InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>
323where
324    T: QuerySource,
325    V: ContainsDefaultableValue<Out = O>,
326    O: Default,
327    (O, Self): LoadQuery<'query, SqliteConnection, U, B>,
328{
329    type RowIter<'conn> = <(O, Self) as LoadQuery<'query, SqliteConnection, U, B>>::RowIter<'conn>;
330
331    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
332        <(O, Self) as LoadQuery<'query, SqliteConnection, U, B>>::internal_load(
333            (O::default(), self),
334            conn,
335        )
336    }
337}
338
339impl<'query, V, T, QId, Op, O, U, B, Target, ConflictOpt, const STATIC_QUERY_ID: bool>
340    LoadQuery<'query, SqliteConnection, U, B>
341    for InsertStatement<
342        T,
343        OnConflictValues<
344            BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>,
345            Target,
346            ConflictOpt,
347        >,
348        Op,
349    >
350where
351    T: QuerySource,
352    V: ContainsDefaultableValue<Out = O>,
353    O: Default,
354    (O, Self): LoadQuery<'query, SqliteConnection, U, B>,
355{
356    type RowIter<'conn> = <(O, Self) as LoadQuery<'query, SqliteConnection, U, B>>::RowIter<'conn>;
357
358    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
359        <(O, Self) as LoadQuery<'query, SqliteConnection, U, B>>::internal_load(
360            (O::default(), self),
361            conn,
362        )
363    }
364}
365
366impl<V, T, QId, Op, O, const STATIC_QUERY_ID: bool> RunQueryDsl<SqliteConnection>
367    for (
368        O,
369        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
370    )
371where
372    T: QuerySource,
373    V: ContainsDefaultableValue<Out = O>,
374    O: Default,
375    InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>:
376        RunQueryDsl<SqliteConnection>,
377{
378}
379
380impl<V, T, QId, Op, O, Target, ConflictOpt, const STATIC_QUERY_ID: bool>
381    RunQueryDsl<SqliteConnection>
382    for (
383        O,
384        InsertStatement<
385            T,
386            OnConflictValues<
387                BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>,
388                Target,
389                ConflictOpt,
390            >,
391            Op,
392        >,
393    )
394where
395    T: QuerySource,
396    V: ContainsDefaultableValue<Out = O>,
397    O: Default,
398    InsertStatement<
399        T,
400        OnConflictValues<
401            BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>,
402            Target,
403            ConflictOpt,
404        >,
405        Op,
406    >: RunQueryDsl<SqliteConnection>,
407{
408}
409
410#[diagnostic::do_not_recommend]
411impl<'query, V, T, QId, Op, U, B, const STATIC_QUERY_ID: bool>
412    LoadQuery<'query, SqliteConnection, U, B>
413    for (
414        Yes,
415        InsertStatement<T, BatchInsert<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>, Op>,
416    )
417where
418    T: Table + Copy + QueryId + 'static,
419    Op: Copy + QueryId + QueryFragment<Sqlite>,
420    InsertStatement<T, ValuesClause<V, T>, Op>: LoadQuery<'query, SqliteConnection, U, B>,
421    Self: RunQueryDsl<SqliteConnection>,
422{
423    type RowIter<'conn> = std::vec::IntoIter<QueryResult<U>>;
424
425    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
426        let (Yes, query) = self;
427
428        conn.transaction(|conn| {
429            let mut results = Vec::with_capacity(query.records.values.len());
430
431            for record in query.records.values {
432                let stmt =
433                    InsertStatement::new(query.target, record, query.operator, query.returning);
434
435                let result = stmt
436                    .internal_load(conn)?
437                    .next()
438                    .ok_or(crate::result::Error::NotFound)?;
439
440                match &result {
441                    Ok(_) | Err(crate::result::Error::DeserializationError(_)) => {
442                        results.push(result)
443                    }
444                    Err(_) => {
445                        result?;
446                    }
447                };
448            }
449
450            Ok(results.into_iter())
451        })
452    }
453}
454
455#[diagnostic::do_not_recommend]
456impl<'query, V, T, QId, Op, U, B, Target, ConflictOpt, const STATIC_QUERY_ID: bool>
457    LoadQuery<'query, SqliteConnection, U, B>
458    for (
459        Yes,
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: Table + Copy + QueryId + 'static,
472    T::FromClause: Copy,
473    Op: Copy,
474    Target: Copy,
475    ConflictOpt: Copy,
476    InsertStatement<T, OnConflictValues<ValuesClause<V, T>, Target, ConflictOpt>, Op>:
477        LoadQuery<'query, SqliteConnection, U, B>,
478    Self: RunQueryDsl<SqliteConnection>,
479{
480    type RowIter<'conn> = std::vec::IntoIter<QueryResult<U>>;
481
482    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
483        let (Yes, query) = self;
484
485        conn.transaction(|conn| {
486            let mut results = Vec::with_capacity(query.records.values.values.len());
487
488            for record in query.records.values.values {
489                let stmt = InsertStatement {
490                    operator: query.operator,
491                    target: query.target,
492                    records: OnConflictValues {
493                        values: record,
494                        target: query.records.target,
495                        action: query.records.action,
496                        where_clause: query.records.where_clause,
497                    },
498                    returning: query.returning,
499                    into_clause: query.into_clause,
500                };
501
502                let result = stmt
503                    .internal_load(conn)?
504                    .next()
505                    .ok_or(crate::result::Error::NotFound)?;
506
507                match &result {
508                    Ok(_) | Err(crate::result::Error::DeserializationError(_)) => {
509                        results.push(result)
510                    }
511                    Err(_) => {
512                        result?;
513                    }
514                };
515            }
516
517            Ok(results.into_iter())
518        })
519    }
520}
521
522#[allow(missing_debug_implementations, missing_copy_implementations)]
523#[repr(transparent)]
524pub struct SqliteBatchInsertWrapper<V, T, QId, const STATIC_QUERY_ID: bool>(
525    BatchInsert<V, T, QId, STATIC_QUERY_ID>,
526);
527
528impl<V, Tab, QId, const STATIC_QUERY_ID: bool> QueryFragment<Sqlite>
529    for SqliteBatchInsertWrapper<Vec<ValuesClause<V, Tab>>, Tab, QId, STATIC_QUERY_ID>
530where
531    ValuesClause<V, Tab>: QueryFragment<Sqlite>,
532    V: QueryFragment<Sqlite>,
533{
534    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Sqlite>) -> QueryResult<()> {
535        if !STATIC_QUERY_ID {
536            out.unsafe_to_cache_prepared();
537        }
538
539        let mut values = self.0.values.iter();
540        if let Some(value) = values.next() {
541            value.walk_ast(out.reborrow())?;
542        }
543        for value in values {
544            out.push_sql(", (");
545            value.values.walk_ast(out.reborrow())?;
546            out.push_sql(")");
547        }
548        Ok(())
549    }
550}
551
552#[allow(missing_copy_implementations, missing_debug_implementations)]
553#[repr(transparent)]
554pub struct SqliteCanInsertInSingleQueryHelper<T: ?Sized>(T);
555
556impl<V, T, QId, const STATIC_QUERY_ID: bool> CanInsertInSingleQuery<Sqlite>
557    for SqliteBatchInsertWrapper<Vec<ValuesClause<V, T>>, T, QId, STATIC_QUERY_ID>
558where
559    // We constrain that here on an internal helper type
560    // to make sure that this does not accidentally leak
561    // so that none does really implement normal batch
562    // insert for inserts with default values here
563    SqliteCanInsertInSingleQueryHelper<V>: CanInsertInSingleQuery<Sqlite>,
564{
565    fn rows_to_insert(&self) -> Option<usize> {
566        Some(self.0.values.len())
567    }
568}
569
570impl<T> CanInsertInSingleQuery<Sqlite> for SqliteCanInsertInSingleQueryHelper<T>
571where
572    T: CanInsertInSingleQuery<Sqlite>,
573{
574    fn rows_to_insert(&self) -> Option<usize> {
575        self.0.rows_to_insert()
576    }
577}
578
579impl<V, T, QId, const STATIC_QUERY_ID: bool> QueryId
580    for SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>
581where
582    BatchInsert<V, T, QId, STATIC_QUERY_ID>: QueryId,
583{
584    type QueryId = <BatchInsert<V, T, QId, STATIC_QUERY_ID> as QueryId>::QueryId;
585
586    const HAS_STATIC_QUERY_ID: bool =
587        <BatchInsert<V, T, QId, STATIC_QUERY_ID> as QueryId>::HAS_STATIC_QUERY_ID;
588}
589
590impl<V, T, QId, C, Op, const STATIC_QUERY_ID: bool> ExecuteDsl<C, Sqlite>
591    for (
592        No,
593        InsertStatement<T, BatchInsert<V, T, QId, STATIC_QUERY_ID>, Op>,
594    )
595where
596    C: Connection<Backend = Sqlite>,
597    T: Table + QueryId + 'static,
598    T::FromClause: QueryFragment<Sqlite>,
599    Op: QueryFragment<Sqlite> + QueryId,
600    SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>:
601        QueryFragment<Sqlite> + QueryId + CanInsertInSingleQuery<Sqlite>,
602{
603    fn execute((No, query): Self, conn: &mut C) -> QueryResult<usize> {
604        let query = InsertStatement {
605            records: SqliteBatchInsertWrapper(query.records),
606            operator: query.operator,
607            target: query.target,
608            returning: query.returning,
609            into_clause: query.into_clause,
610        };
611        query.execute(conn)
612    }
613}
614
615impl<V, T, QId, C, Op, Target, ConflictOpt, const STATIC_QUERY_ID: bool> ExecuteDsl<C, Sqlite>
616    for (
617        No,
618        InsertStatement<
619            T,
620            OnConflictValues<BatchInsert<V, T, QId, STATIC_QUERY_ID>, Target, ConflictOpt>,
621            Op,
622        >,
623    )
624where
625    C: Connection<Backend = Sqlite>,
626    T: Table + QueryId + 'static,
627    T::FromClause: QueryFragment<Sqlite>,
628    Op: QueryFragment<Sqlite> + QueryId,
629    OnConflictValues<SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>, Target, ConflictOpt>:
630        QueryFragment<Sqlite> + CanInsertInSingleQuery<Sqlite> + QueryId,
631{
632    fn execute((No, query): Self, conn: &mut C) -> QueryResult<usize> {
633        let query = InsertStatement {
634            operator: query.operator,
635            target: query.target,
636            records: OnConflictValues {
637                values: SqliteBatchInsertWrapper(query.records.values),
638                target: query.records.target,
639                action: query.records.action,
640                where_clause: query.records.where_clause,
641            },
642            returning: query.returning,
643            into_clause: query.into_clause,
644        };
645        query.execute(conn)
646    }
647}
648
649#[diagnostic::do_not_recommend]
650impl<'query, V, T, QId, Op, U, B, const STATIC_QUERY_ID: bool>
651    LoadQuery<'query, SqliteConnection, U, B>
652    for (
653        No,
654        InsertStatement<T, BatchInsert<V, T, QId, STATIC_QUERY_ID>, Op>,
655    )
656where
657    T: Table + QueryId + 'static,
658    InsertStatement<T, SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>, Op>:
659        LoadQuery<'query, SqliteConnection, U, B>,
660    Self: RunQueryDsl<SqliteConnection>,
661{
662    type RowIter<'conn> = <InsertStatement<
663        T,
664        SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>,
665        Op,
666    > as LoadQuery<'query, SqliteConnection, U, B>>::RowIter<'conn>;
667
668    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
669        let (No, query) = self;
670
671        let query = InsertStatement {
672            records: SqliteBatchInsertWrapper(query.records),
673            operator: query.operator,
674            target: query.target,
675            returning: query.returning,
676            into_clause: query.into_clause,
677        };
678
679        query.internal_load(conn)
680    }
681}
682
683#[diagnostic::do_not_recommend]
684impl<'query, V, T, QId, Op, U, B, Target, ConflictOpt, const STATIC_QUERY_ID: bool>
685    LoadQuery<'query, SqliteConnection, U, B>
686    for (
687        No,
688        InsertStatement<
689            T,
690            OnConflictValues<BatchInsert<V, T, QId, STATIC_QUERY_ID>, Target, ConflictOpt>,
691            Op,
692        >,
693    )
694where
695    T: Table + QueryId + 'static,
696    InsertStatement<
697        T,
698        OnConflictValues<SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>, Target, ConflictOpt>,
699        Op,
700    >: LoadQuery<'query, SqliteConnection, U, B>,
701    Self: RunQueryDsl<SqliteConnection>,
702{
703    type RowIter<'conn> = <InsertStatement<
704        T,
705        OnConflictValues<SqliteBatchInsertWrapper<V, T, QId, STATIC_QUERY_ID>, Target, ConflictOpt>,
706        Op,
707    > as LoadQuery<'query, SqliteConnection, U, B>>::RowIter<'conn>;
708
709    fn internal_load(self, conn: &mut SqliteConnection) -> QueryResult<Self::RowIter<'_>> {
710        let (No, query) = self;
711
712        let query = InsertStatement {
713            operator: query.operator,
714            target: query.target,
715            records: OnConflictValues {
716                values: SqliteBatchInsertWrapper(query.records.values),
717                target: query.records.target,
718                action: query.records.action,
719                where_clause: query.records.where_clause,
720            },
721            returning: query.returning,
722            into_clause: query.into_clause,
723        };
724
725        query.internal_load(conn)
726    }
727}
728
729macro_rules! tuple_impls {
730        ($(
731            $Tuple:tt {
732                $(($idx:tt) -> $T:ident, $ST:ident, $TT:ident,)+
733            }
734        )+) => {
735            $(
736                impl_contains_defaultable_value!($($T,)*);
737            )*
738        }
739    }
740
741macro_rules! impl_contains_defaultable_value {
742      (
743        @build
744        start_ts = [$($ST: ident,)*],
745        ts = [$T1: ident,],
746        bounds = [$($bounds: tt)*],
747        out = [$($out: tt)*],
748    )=> {
749        impl<$($ST,)*> ContainsDefaultableValue for ($($ST,)*)
750        where
751            $($ST: ContainsDefaultableValue,)*
752            $($bounds)*
753            $T1::Out: Any<$($out)*>,
754        {
755            type Out = <$T1::Out as Any<$($out)*>>::Out;
756        }
757
758    };
759    (
760        @build
761        start_ts = [$($ST: ident,)*],
762        ts = [$T1: ident, $($T: ident,)+],
763        bounds = [$($bounds: tt)*],
764        out = [$($out: tt)*],
765    )=> {
766        impl_contains_defaultable_value! {
767            @build
768            start_ts = [$($ST,)*],
769            ts = [$($T,)*],
770            bounds = [$($bounds)* $T1::Out: Any<$($out)*>,],
771            out = [<$T1::Out as Any<$($out)*>>::Out],
772        }
773    };
774    ($T1: ident, $($T: ident,)+) => {
775        impl_contains_defaultable_value! {
776            @build
777            start_ts = [$T1, $($T,)*],
778            ts = [$($T,)*],
779            bounds = [],
780            out = [$T1::Out],
781        }
782    };
783    ($T1: ident,) => {
784        impl<$T1> ContainsDefaultableValue for ($T1,)
785        where $T1: ContainsDefaultableValue,
786        {
787            type Out = <$T1 as ContainsDefaultableValue>::Out;
788        }
789    }
790}
791
792diesel_derives::__diesel_for_each_tuple!(tuple_impls);