trailbase_sqlite/
params.rs

1use rusqlite::types::ToSqlOutput;
2use rusqlite::{types, Result, Statement};
3use std::borrow::Cow;
4
5pub type NamedParams = Vec<(Cow<'static, str>, types::Value)>;
6pub type NamedParamRef<'a> = (Cow<'static, str>, types::ToSqlOutput<'a>);
7pub type NamedParamsRef<'a> = &'a [NamedParamRef<'a>];
8
9// This strong typedef only exists to implement From<Option<T>>.
10#[allow(missing_debug_implementations)]
11pub enum ToSqlType {
12  /// A borrowed SQLite-representable value.
13  Borrowed(types::ValueRef<'static>),
14
15  /// An owned SQLite-representable value.
16  Owned(types::Value),
17}
18
19impl rusqlite::ToSql for ToSqlType {
20  #[inline]
21  fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
22    Ok(match *self {
23      ToSqlType::Borrowed(v) => ToSqlOutput::Borrowed(v),
24      ToSqlType::Owned(ref v) => ToSqlOutput::Borrowed(types::ValueRef::from(v)),
25    })
26  }
27}
28
29impl<T: ?Sized> From<&'static T> for ToSqlType
30where
31  &'static T: Into<types::ValueRef<'static>>,
32{
33  #[inline]
34  fn from(t: &'static T) -> Self {
35    ToSqlType::Borrowed(t.into())
36  }
37}
38
39macro_rules! from_value(
40    ($t:ty) => (
41        impl From<$t> for ToSqlType {
42            #[inline]
43            fn from(t: $t) -> Self { ToSqlType::Owned(t.into())}
44        }
45        impl From<Option<$t>> for ToSqlType {
46            #[inline]
47            fn from(t: Option<$t>) -> Self {
48                match t {
49                    Some(t) => ToSqlType::Owned(t.into()),
50                    None => ToSqlType::Owned(types::Value::Null),
51                }
52            }
53        }
54    )
55);
56
57from_value!(String);
58from_value!(bool);
59from_value!(i64);
60from_value!(f64);
61from_value!(Vec<u8>);
62from_value!(types::Value);
63
64impl<const N: usize> From<[u8; N]> for ToSqlType {
65  fn from(t: [u8; N]) -> Self {
66    ToSqlType::Owned(types::Value::Blob(t.into()))
67  }
68}
69
70pub trait Params {
71  fn bind(self, stmt: &mut Statement<'_>) -> rusqlite::Result<()>;
72}
73
74impl Params for () {
75  fn bind(self, _stmt: &mut Statement<'_>) -> rusqlite::Result<()> {
76    Ok(())
77  }
78}
79
80impl Params for Vec<(String, types::Value)> {
81  fn bind(self, stmt: &mut Statement<'_>) -> rusqlite::Result<()> {
82    for (name, v) in self {
83      if let Some(idx) = stmt.parameter_index(&name)? {
84        stmt.raw_bind_parameter(idx, v)?;
85      };
86    }
87    return Ok(());
88  }
89}
90
91impl Params for NamedParams {
92  fn bind(self, stmt: &mut Statement<'_>) -> rusqlite::Result<()> {
93    for (name, v) in self {
94      let Some(idx) = stmt.parameter_index(&name)? else {
95        continue;
96      };
97      stmt.raw_bind_parameter(idx, v)?;
98    }
99    return Ok(());
100  }
101}
102
103impl Params for Vec<(&str, types::Value)> {
104  fn bind(self, stmt: &mut Statement<'_>) -> rusqlite::Result<()> {
105    for (name, v) in self {
106      let Some(idx) = stmt.parameter_index(name)? else {
107        continue;
108      };
109      stmt.raw_bind_parameter(idx, v)?;
110    }
111    return Ok(());
112  }
113}
114
115impl Params for &[(&str, types::Value)] {
116  fn bind(self, stmt: &mut Statement<'_>) -> rusqlite::Result<()> {
117    for (name, v) in self {
118      let Some(idx) = stmt.parameter_index(name)? else {
119        continue;
120      };
121      stmt.raw_bind_parameter(idx, v)?;
122    }
123    return Ok(());
124  }
125}
126
127impl Params for NamedParamsRef<'_> {
128  fn bind(self, stmt: &mut Statement<'_>) -> rusqlite::Result<()> {
129    for (name, v) in self {
130      let Some(idx) = stmt.parameter_index(name)? else {
131        continue;
132      };
133      stmt.raw_bind_parameter(idx, v)?;
134    }
135    return Ok(());
136  }
137}
138
139impl<const N: usize> Params for [(&str, types::Value); N] {
140  fn bind(self, stmt: &mut Statement<'_>) -> rusqlite::Result<()> {
141    for (name, v) in self {
142      let Some(idx) = stmt.parameter_index(name)? else {
143        continue;
144      };
145      stmt.raw_bind_parameter(idx, v)?;
146    }
147    return Ok(());
148  }
149}
150
151impl<const N: usize> Params for [(&str, ToSqlType); N] {
152  fn bind(self, stmt: &mut Statement<'_>) -> rusqlite::Result<()> {
153    for (name, v) in self {
154      let Some(idx) = stmt.parameter_index(name)? else {
155        continue;
156      };
157      stmt.raw_bind_parameter(idx, v)?;
158    }
159    return Ok(());
160  }
161}
162
163impl Params for Vec<types::Value> {
164  fn bind(self, stmt: &mut Statement<'_>) -> rusqlite::Result<()> {
165    for (idx, p) in self.into_iter().enumerate() {
166      stmt.raw_bind_parameter(idx + 1, p)?;
167    }
168    return Ok(());
169  }
170}
171
172impl Params for &[types::Value] {
173  fn bind(self, stmt: &mut Statement<'_>) -> rusqlite::Result<()> {
174    for (idx, p) in self.iter().enumerate() {
175      stmt.raw_bind_parameter(idx + 1, p)?;
176    }
177    return Ok(());
178  }
179}
180
181impl<const N: usize> Params for [ToSqlType; N] {
182  fn bind(self, stmt: &mut Statement<'_>) -> rusqlite::Result<()> {
183    for (idx, p) in self.into_iter().enumerate() {
184      stmt.raw_bind_parameter(idx + 1, p)?;
185    }
186    return Ok(());
187  }
188}
189
190impl<T, const N: usize> Params for &[T; N]
191where
192  T: rusqlite::ToSql + Send + Sync,
193{
194  fn bind(self, stmt: &mut Statement<'_>) -> rusqlite::Result<()> {
195    for (idx, p) in self.iter().enumerate() {
196      stmt.raw_bind_parameter(idx + 1, p)?;
197    }
198    return Ok(());
199  }
200}
201
202impl<T> Params for (T,)
203where
204  T: rusqlite::ToSql + Send + Sync,
205{
206  fn bind(self, stmt: &mut Statement<'_>) -> rusqlite::Result<()> {
207    return stmt.raw_bind_parameter(1, self.0);
208  }
209}
210
211impl<const N: usize> Params for [types::Value; N] {
212  fn bind(self, stmt: &mut Statement<'_>) -> rusqlite::Result<()> {
213    for (idx, p) in self.into_iter().enumerate() {
214      stmt.raw_bind_parameter(idx + 1, p)?;
215    }
216    return Ok(());
217  }
218}