diesel/sqlite/connection/
bind_collector.rs
1use crate::query_builder::{BindCollector, MoveableBindCollector};
2use crate::serialize::{IsNull, Output};
3use crate::sql_types::HasSqlType;
4use crate::sqlite::{Sqlite, SqliteType};
5use crate::QueryResult;
6#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
7use libsqlite3_sys as ffi;
8#[cfg(all(target_family = "wasm", target_os = "unknown"))]
9use sqlite_wasm_rs::export as ffi;
10
11#[derive(Debug, Default)]
12pub struct SqliteBindCollector<'a> {
13 pub(in crate::sqlite) binds: Vec<(InternalSqliteBindValue<'a>, SqliteType)>,
14}
15
16impl SqliteBindCollector<'_> {
17 pub(in crate::sqlite) fn new() -> Self {
18 Self { binds: Vec::new() }
19 }
20}
21
22#[derive(Debug)]
27pub struct SqliteBindValue<'a> {
28 pub(in crate::sqlite) inner: InternalSqliteBindValue<'a>,
29}
30
31impl From<i32> for SqliteBindValue<'_> {
32 fn from(i: i32) -> Self {
33 Self {
34 inner: InternalSqliteBindValue::I32(i),
35 }
36 }
37}
38
39impl From<i64> for SqliteBindValue<'_> {
40 fn from(i: i64) -> Self {
41 Self {
42 inner: InternalSqliteBindValue::I64(i),
43 }
44 }
45}
46
47impl From<f64> for SqliteBindValue<'_> {
48 fn from(f: f64) -> Self {
49 Self {
50 inner: InternalSqliteBindValue::F64(f),
51 }
52 }
53}
54
55impl<'a, T> From<Option<T>> for SqliteBindValue<'a>
56where
57 T: Into<SqliteBindValue<'a>>,
58{
59 fn from(o: Option<T>) -> Self {
60 match o {
61 Some(v) => v.into(),
62 None => Self {
63 inner: InternalSqliteBindValue::Null,
64 },
65 }
66 }
67}
68
69impl<'a> From<&'a str> for SqliteBindValue<'a> {
70 fn from(s: &'a str) -> Self {
71 Self {
72 inner: InternalSqliteBindValue::BorrowedString(s),
73 }
74 }
75}
76
77impl From<String> for SqliteBindValue<'_> {
78 fn from(s: String) -> Self {
79 Self {
80 inner: InternalSqliteBindValue::String(s.into_boxed_str()),
81 }
82 }
83}
84
85impl From<Vec<u8>> for SqliteBindValue<'_> {
86 fn from(b: Vec<u8>) -> Self {
87 Self {
88 inner: InternalSqliteBindValue::Binary(b.into_boxed_slice()),
89 }
90 }
91}
92
93impl<'a> From<&'a [u8]> for SqliteBindValue<'a> {
94 fn from(b: &'a [u8]) -> Self {
95 Self {
96 inner: InternalSqliteBindValue::BorrowedBinary(b),
97 }
98 }
99}
100
101#[derive(Debug)]
102pub(crate) enum InternalSqliteBindValue<'a> {
103 BorrowedString(&'a str),
104 String(Box<str>),
105 BorrowedBinary(&'a [u8]),
106 Binary(Box<[u8]>),
107 I32(i32),
108 I64(i64),
109 F64(f64),
110 Null,
111}
112
113impl std::fmt::Display for InternalSqliteBindValue<'_> {
114 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115 let n = match self {
116 InternalSqliteBindValue::BorrowedString(_) | InternalSqliteBindValue::String(_) => {
117 "Text"
118 }
119 InternalSqliteBindValue::BorrowedBinary(_) | InternalSqliteBindValue::Binary(_) => {
120 "Binary"
121 }
122 InternalSqliteBindValue::I32(_) | InternalSqliteBindValue::I64(_) => "Integer",
123 InternalSqliteBindValue::F64(_) => "Float",
124 InternalSqliteBindValue::Null => "Null",
125 };
126 f.write_str(n)
127 }
128}
129
130impl InternalSqliteBindValue<'_> {
131 #[allow(unsafe_code)] pub(in crate::sqlite) fn result_of(
133 self,
134 ctx: &mut ffi::sqlite3_context,
135 ) -> Result<(), std::num::TryFromIntError> {
136 use std::os::raw as libc;
137 unsafe {
141 match self {
142 InternalSqliteBindValue::BorrowedString(s) => ffi::sqlite3_result_text(
143 ctx,
144 s.as_ptr() as *const libc::c_char,
145 s.len().try_into()?,
146 ffi::SQLITE_TRANSIENT(),
147 ),
148 InternalSqliteBindValue::String(s) => ffi::sqlite3_result_text(
149 ctx,
150 s.as_ptr() as *const libc::c_char,
151 s.len().try_into()?,
152 ffi::SQLITE_TRANSIENT(),
153 ),
154 InternalSqliteBindValue::Binary(b) => ffi::sqlite3_result_blob(
155 ctx,
156 b.as_ptr() as *const libc::c_void,
157 b.len().try_into()?,
158 ffi::SQLITE_TRANSIENT(),
159 ),
160 InternalSqliteBindValue::BorrowedBinary(b) => ffi::sqlite3_result_blob(
161 ctx,
162 b.as_ptr() as *const libc::c_void,
163 b.len().try_into()?,
164 ffi::SQLITE_TRANSIENT(),
165 ),
166 InternalSqliteBindValue::I32(i) => ffi::sqlite3_result_int(ctx, i as libc::c_int),
167 InternalSqliteBindValue::I64(l) => ffi::sqlite3_result_int64(ctx, l),
168 InternalSqliteBindValue::F64(d) => {
169 ffi::sqlite3_result_double(ctx, d as libc::c_double)
170 }
171 InternalSqliteBindValue::Null => ffi::sqlite3_result_null(ctx),
172 }
173 }
174 Ok(())
175 }
176}
177
178impl<'a> BindCollector<'a, Sqlite> for SqliteBindCollector<'a> {
179 type Buffer = SqliteBindValue<'a>;
180
181 fn push_bound_value<T, U>(&mut self, bind: &'a U, metadata_lookup: &mut ()) -> QueryResult<()>
182 where
183 Sqlite: crate::sql_types::HasSqlType<T>,
184 U: crate::serialize::ToSql<T, Sqlite> + ?Sized,
185 {
186 let value = SqliteBindValue {
187 inner: InternalSqliteBindValue::Null,
188 };
189 let mut to_sql_output = Output::new(value, metadata_lookup);
190 let is_null = bind
191 .to_sql(&mut to_sql_output)
192 .map_err(crate::result::Error::SerializationError)?;
193 let bind = to_sql_output.into_inner();
194 let metadata = Sqlite::metadata(metadata_lookup);
195 self.binds.push((
196 match is_null {
197 IsNull::No => bind.inner,
198 IsNull::Yes => InternalSqliteBindValue::Null,
199 },
200 metadata,
201 ));
202 Ok(())
203 }
204
205 fn push_null_value(&mut self, metadata: SqliteType) -> QueryResult<()> {
206 self.binds.push((InternalSqliteBindValue::Null, metadata));
207 Ok(())
208 }
209}
210
211#[derive(Debug)]
212enum OwnedSqliteBindValue {
213 String(Box<str>),
214 Binary(Box<[u8]>),
215 I32(i32),
216 I64(i64),
217 F64(f64),
218 Null,
219}
220
221impl<'a> std::convert::From<&InternalSqliteBindValue<'a>> for OwnedSqliteBindValue {
222 fn from(value: &InternalSqliteBindValue<'a>) -> Self {
223 match value {
224 InternalSqliteBindValue::String(s) => Self::String(s.clone()),
225 InternalSqliteBindValue::BorrowedString(s) => {
226 Self::String(String::from(*s).into_boxed_str())
227 }
228 InternalSqliteBindValue::Binary(b) => Self::Binary(b.clone()),
229 InternalSqliteBindValue::BorrowedBinary(s) => {
230 Self::Binary(Vec::from(*s).into_boxed_slice())
231 }
232 InternalSqliteBindValue::I32(val) => Self::I32(*val),
233 InternalSqliteBindValue::I64(val) => Self::I64(*val),
234 InternalSqliteBindValue::F64(val) => Self::F64(*val),
235 InternalSqliteBindValue::Null => Self::Null,
236 }
237 }
238}
239
240impl std::convert::From<&OwnedSqliteBindValue> for InternalSqliteBindValue<'_> {
241 fn from(value: &OwnedSqliteBindValue) -> Self {
242 match value {
243 OwnedSqliteBindValue::String(s) => Self::String(s.clone()),
244 OwnedSqliteBindValue::Binary(b) => Self::Binary(b.clone()),
245 OwnedSqliteBindValue::I32(val) => Self::I32(*val),
246 OwnedSqliteBindValue::I64(val) => Self::I64(*val),
247 OwnedSqliteBindValue::F64(val) => Self::F64(*val),
248 OwnedSqliteBindValue::Null => Self::Null,
249 }
250 }
251}
252
253#[derive(Debug)]
254pub struct SqliteBindCollectorData {
256 binds: Vec<(OwnedSqliteBindValue, SqliteType)>,
257}
258
259impl MoveableBindCollector<Sqlite> for SqliteBindCollector<'_> {
260 type BindData = SqliteBindCollectorData;
261
262 fn moveable(&self) -> Self::BindData {
263 let mut binds = Vec::with_capacity(self.binds.len());
264 for b in self
265 .binds
266 .iter()
267 .map(|(bind, tpe)| (OwnedSqliteBindValue::from(bind), *tpe))
268 {
269 binds.push(b);
270 }
271 SqliteBindCollectorData { binds }
272 }
273
274 fn append_bind_data(&mut self, from: &Self::BindData) {
275 self.binds.reserve_exact(from.binds.len());
276 self.binds.extend(
277 from.binds
278 .iter()
279 .map(|(bind, tpe)| (InternalSqliteBindValue::from(bind), *tpe)),
280 );
281 }
282}