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)] impl<'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 let InsertStatement {
112 operator,
113 target: _,
114 records,
115 returning,
116 into_clause,
117 } = self.query;
118 let records = unsafe {
119 &*(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 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);