Skip to main content

diesel/sqlite/connection/
bind_collector.rs

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