diesel/query_builder/insert_statement/
batch_insert.rs1use super::ValuesClause;
2use crate::QueryResult;
3use crate::backend::{Backend, SqlDialect, sql_dialect};
4use crate::insertable::CanInsertInSingleQuery;
5use crate::query_builder::{AstPass, QueryFragment, QueryId};
6use alloc::boxed::Box;
7use alloc::vec::Vec;
8use core::marker::PhantomData;
9
10#[cfg_attr(
18 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
19 cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")
20)]
21#[derive(#[automatically_derived]impl<V: ::core::fmt::Debug, Tab: ::core::fmt::Debug,
QId: ::core::fmt::Debug, const STABLE_QUERY_ID : bool> ::core::fmt::Debug
for BatchInsert<V, Tab, QId, STABLE_QUERY_ID> {
#[inline]
#[rustc_trivial_field_reads]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"BatchInsert values _marker", &self.values, &&self._marker)
}
}Debug)]
22pub struct BatchInsert<V, Tab, QId, const STABLE_QUERY_ID: bool> {
23 pub values: V,
25 _marker: PhantomData<(QId, Tab)>,
26}
27
28impl<V, Tab, QId, const STABLE_QUERY_ID: bool> BatchInsert<V, Tab, QId, STABLE_QUERY_ID> {
29 pub(crate) fn new(values: V) -> Self {
30 Self {
31 values,
32 _marker: PhantomData,
33 }
34 }
35}
36
37impl<V, QId: 'static, Tab: 'static, const STABLE_QUERY_ID: bool> QueryId
38 for BatchInsert<Vec<V>, Tab, QId, STABLE_QUERY_ID>
39where
40 V: QueryId,
41{
42 type QueryId = QId;
43
44 const HAS_STATIC_QUERY_ID: bool = STABLE_QUERY_ID && V::HAS_STATIC_QUERY_ID;
45}
46
47impl<T, Table, QId, DB, const HAS_STATIC_QUERY_ID: bool> CanInsertInSingleQuery<DB>
48 for BatchInsert<T, Table, QId, HAS_STATIC_QUERY_ID>
49where
50 T: CanInsertInSingleQuery<DB>,
51 DB: Backend,
52 DB: SqlDialect<
53 InsertWithDefaultKeyword = sql_dialect::default_keyword_for_insert::IsoSqlDefaultKeyword,
54 >,
55{
56 fn rows_to_insert(&self) -> Option<usize> {
57 self.values.rows_to_insert()
58 }
59}
60
61impl<T, DB, const N: usize> CanInsertInSingleQuery<DB> for [T; N]
62where
63DB: Backend+ SqlDialect<InsertWithDefaultKeyword = sql_dialect::default_keyword_for_insert::IsoSqlDefaultKeyword>
64{
65 fn rows_to_insert(&self) -> Option<usize> {
66 Some(N)
67 }
68}
69
70impl<T, DB, const N: usize> CanInsertInSingleQuery<DB> for Box<[T; N]>
71where
72 DB: Backend+ SqlDialect<InsertWithDefaultKeyword = sql_dialect::default_keyword_for_insert::IsoSqlDefaultKeyword>
73{
74 fn rows_to_insert(&self) -> Option<usize> {
75 Some(N)
76 }
77}
78
79impl<T, DB, const N: usize> CanInsertInSingleQuery<DB> for alloc::rc::Rc<[T; N]>
80where
81 DB: Backend+ SqlDialect<InsertWithDefaultKeyword = sql_dialect::default_keyword_for_insert::IsoSqlDefaultKeyword>
82{
83 fn rows_to_insert(&self) -> Option<usize> {
84 Some(N)
85 }
86}
87
88impl<T, DB, const N: usize> CanInsertInSingleQuery<DB> for alloc::sync::Arc<[T; N]>
89where
90 DB: Backend+ SqlDialect<InsertWithDefaultKeyword = sql_dialect::default_keyword_for_insert::IsoSqlDefaultKeyword>
91{
92 fn rows_to_insert(&self) -> Option<usize> {
93 Some(N)
94 }
95}
96
97impl<T, DB> CanInsertInSingleQuery<DB> for [T]
98where
99 DB: Backend+ SqlDialect<InsertWithDefaultKeyword = sql_dialect::default_keyword_for_insert::IsoSqlDefaultKeyword>
100{
101 fn rows_to_insert(&self) -> Option<usize> {
102 Some(self.len())
103 }
104}
105
106impl<T, DB> CanInsertInSingleQuery<DB> for Vec<T>
107where
108 DB: Backend+ SqlDialect<InsertWithDefaultKeyword = sql_dialect::default_keyword_for_insert::IsoSqlDefaultKeyword>,
109{
110 fn rows_to_insert(&self) -> Option<usize> {
111 Some(self.len())
112 }
113}
114
115impl<Tab, DB, V, QId, const HAS_STATIC_QUERY_ID: bool> QueryFragment<DB>
116 for BatchInsert<V, Tab, QId, HAS_STATIC_QUERY_ID>
117where
118 DB: Backend,
119 Self: QueryFragment<DB, DB::BatchInsertSupport>,
120{
121 fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
122 <Self as QueryFragment<DB, DB::BatchInsertSupport>>::walk_ast(self, pass)
123 }
124}
125
126impl<Tab, DB, V, QId, const HAS_STATIC_QUERY_ID: bool>
127 QueryFragment<DB, sql_dialect::batch_insert_support::PostgresLikeBatchInsertSupport>
128 for BatchInsert<Vec<ValuesClause<V, Tab>>, Tab, QId, HAS_STATIC_QUERY_ID>
129where
130 DB: Backend
131 + SqlDialect<
132 BatchInsertSupport = sql_dialect::batch_insert_support::PostgresLikeBatchInsertSupport,
133 >,
134 DB::InsertWithDefaultKeyword: sql_dialect::default_keyword_for_insert::SupportsDefaultKeyword,
135 ValuesClause<V, Tab>: QueryFragment<DB>,
136 V: QueryFragment<DB>,
137{
138 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
139 if !HAS_STATIC_QUERY_ID {
140 out.unsafe_to_cache_prepared();
141 }
142
143 let mut values = self.values.iter();
144 if let Some(value) = values.next() {
145 value.walk_ast(out.reborrow())?;
146 }
147 for value in values {
148 out.push_sql(", (");
149 value.values.walk_ast(out.reborrow())?;
150 out.push_sql(")");
151 }
152 Ok(())
153 }
154}