diesel/query_builder/
bind_collector.rs1use crate::backend::Backend;
4use crate::result::Error::SerializationError;
5use crate::result::QueryResult;
6use crate::serialize::{IsNull, Output, ToSql};
7use crate::sql_types::{HasSqlType, TypeMetadata};
8
9#[doc(inline)]
10#[diesel_derives::__diesel_public_if(
11 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
12)]
13pub(crate) use self::private::ByteWrapper;
14
15pub trait BindCollector<'a, DB: TypeMetadata>: Sized {
23 type Buffer;
25
26 fn push_bound_value<T, U>(
28 &mut self,
29 bind: &'a U,
30 metadata_lookup: &mut DB::MetadataLookup,
31 ) -> QueryResult<()>
32 where
33 DB: Backend + HasSqlType<T>,
34 U: ToSql<T, DB> + ?Sized + 'a;
35
36 #[diesel_derives::__diesel_public_if(
41 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
42 )]
43 fn push_null_value(&mut self, _metadata: DB::TypeMetadata) -> QueryResult<()> {
44 Ok(())
45 }
46}
47
48#[diesel_derives::__diesel_public_if(
52 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
53)]
54pub trait MoveableBindCollector<DB: TypeMetadata> {
55 type BindData: Send + 'static;
57
58 fn moveable(&self) -> Self::BindData;
60
61 fn append_bind_data(&mut self, from: &Self::BindData);
63
64 fn push_debug_binds<'a, 'b>(
66 bind_data: &Self::BindData,
67 f: &'a mut Vec<Box<dyn std::fmt::Debug + 'b>>,
68 );
69}
70
71#[derive(Debug)]
72#[diesel_derives::__diesel_public_if(
78 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
79 public_fields(metadata, binds)
80)]
81pub struct RawBytesBindCollector<DB: Backend + TypeMetadata> {
82 pub(crate) metadata: Vec<DB::TypeMetadata>,
86 pub(crate) binds: Vec<Option<Vec<u8>>>,
90}
91
92impl<DB: Backend + TypeMetadata> Default for RawBytesBindCollector<DB> {
93 fn default() -> Self {
94 Self::new()
95 }
96}
97
98#[allow(clippy::new_without_default)]
99impl<DB: Backend + TypeMetadata> RawBytesBindCollector<DB> {
100 pub fn new() -> Self {
102 RawBytesBindCollector {
103 metadata: Vec::new(),
104 binds: Vec::new(),
105 }
106 }
107
108 pub(crate) fn reborrow_buffer<'a: 'b, 'b>(b: &'b mut ByteWrapper<'a>) -> ByteWrapper<'b> {
109 ByteWrapper(b.0)
110 }
111}
112
113impl<'a, DB> BindCollector<'a, DB> for RawBytesBindCollector<DB>
114where
115 for<'b> DB: Backend<BindCollector<'b> = Self> + TypeMetadata,
116{
117 type Buffer = ByteWrapper<'a>;
118
119 fn push_bound_value<T, U>(
120 &mut self,
121 bind: &U,
122 metadata_lookup: &mut DB::MetadataLookup,
123 ) -> QueryResult<()>
124 where
125 DB: HasSqlType<T>,
126 U: ToSql<T, DB> + ?Sized,
127 {
128 let mut bytes = Vec::new();
129 let is_null = {
130 let mut to_sql_output = Output::new(ByteWrapper(&mut bytes), metadata_lookup);
131 bind.to_sql(&mut to_sql_output)
132 .map_err(SerializationError)?
133 };
134 let metadata = <DB as HasSqlType<T>>::metadata(metadata_lookup);
135 match is_null {
136 IsNull::No => self.binds.push(Some(bytes)),
137 IsNull::Yes => self.binds.push(None),
138 }
139 self.metadata.push(metadata);
140 Ok(())
141 }
142
143 fn push_null_value(&mut self, metadata: DB::TypeMetadata) -> QueryResult<()> {
144 self.metadata.push(metadata);
145 self.binds.push(None);
146 Ok(())
147 }
148}
149
150impl<DB> MoveableBindCollector<DB> for RawBytesBindCollector<DB>
151where
152 for<'a> DB: Backend<BindCollector<'a> = Self> + TypeMetadata + 'static,
153 <DB as TypeMetadata>::TypeMetadata: std::fmt::Debug + Clone + Send,
154{
155 type BindData = Self;
156
157 fn moveable(&self) -> Self::BindData {
158 RawBytesBindCollector {
159 binds: self.binds.clone(),
160 metadata: self.metadata.clone(),
161 }
162 }
163
164 fn append_bind_data(&mut self, from: &Self::BindData) {
165 self.binds.extend(from.binds.iter().cloned());
166 self.metadata.extend(from.metadata.clone());
167 }
168
169 fn push_debug_binds<'a, 'b>(
170 bind_data: &Self::BindData,
171 f: &'a mut Vec<Box<dyn std::fmt::Debug + 'b>>,
172 ) {
173 f.extend(
174 bind_data
175 .metadata
176 .iter()
177 .map(|m| Box::new(m.clone()) as Box<dyn std::fmt::Debug>),
178 );
179 }
180}
181
182mod private {
185 #[derive(Debug)]
187 pub struct ByteWrapper<'a>(pub(crate) &'a mut Vec<u8>);
188}