1use super::Statement;
2use crate::{ffi, sqlite3_match_version, sqlite3_require_version, types::*, value::*};
3use sealed::sealed;
4
5#[macro_export]
40macro_rules! params {
41 ($($val:expr),* $(,)?) => {
42 |stmt: &mut $crate::query::Statement| {{
43 #![allow(unused_assignments)]
44 use $crate::query::ToParam;
45 let mut i = 1i32;
46 $(
47 $val.bind_param(stmt, i)?;
48 i += 1;
49 )*
50 Ok(())
51 }}
52 }
53}
54
55pub trait Params {
86 fn bind_params(self, stmt: &mut Statement) -> Result<()>;
87}
88
89impl Params for () {
90 fn bind_params(self, _: &mut Statement) -> Result<()> {
91 Ok(())
92 }
93}
94
95impl<T> Params for T
96where
97 T: FnOnce(&mut Statement) -> Result<()>,
98{
99 fn bind_params(self, stmt: &mut Statement) -> Result<()> {
100 self(stmt)
101 }
102}
103
104impl<T: ToParam> Params for Vec<T> {
105 fn bind_params(self, stmt: &mut Statement) -> Result<()> {
106 for (pos, val) in self.into_iter().enumerate() {
107 val.bind_param(stmt, pos as i32 + 1)?;
108 }
109 Ok(())
110 }
111}
112
113impl<T: ToParam, const N: usize> Params for [T; N] {
114 fn bind_params(self, stmt: &mut Statement) -> Result<()> {
115 for (pos, val) in self.into_iter().enumerate() {
116 val.bind_param(stmt, pos as i32 + 1)?;
117 }
118 Ok(())
119 }
120}
121
122impl Params for &mut [&mut ValueRef] {
123 fn bind_params(self, stmt: &mut Statement) -> Result<()> {
124 for (pos, val) in self.into_iter().enumerate() {
125 val.bind_param(stmt, pos as i32 + 1)?;
126 }
127 Ok(())
128 }
129}
130
131#[sealed]
133pub trait ToParam {
134 fn bind_param(self, stmt: &mut Statement, position: i32) -> Result<()>;
139}
140
141macro_rules! to_param {
142 ($(#[$attr:meta])* $ty:ty as ($stmt:ident, $pos:ident, $val:ident) => $impl:expr) => {
143 $(#[$attr])*
144 #[sealed]
145 impl ToParam for $ty {
146 fn bind_param(self, stmt: &mut Statement, $pos: i32) -> Result<()> {
147 let $val = self;
148 let $stmt = stmt.base;
149 Error::from_sqlite(unsafe { $impl })
150 }
151 }
152 };
153}
154
155to_param!(() as (stmt, pos, _val) => ffi::sqlite3_bind_null(stmt, pos));
156to_param!(bool as (stmt, pos, val) => ffi::sqlite3_bind_int(stmt, pos, val as i32));
157to_param!(i64 as (stmt, pos, val) => ffi::sqlite3_bind_int64(stmt, pos, val));
158to_param!(f64 as (stmt, pos, val) => ffi::sqlite3_bind_double(stmt, pos, val));
159to_param!(Blob as (stmt, pos, val) => {
160 let len = val.len();
161 let rc = sqlite3_match_version! {
162 3_008_007 => ffi::sqlite3_bind_blob64(stmt, pos, val.into_raw(), len as _, Some(ffi::drop_blob)),
163 _ => ffi::sqlite3_bind_blob(stmt, pos, val.into_raw(), len as _, Some(ffi::drop_blob)),
164 };
165 rc
166});
167to_param!(&mut ValueRef as (stmt, pos, val) => ffi::sqlite3_bind_value(stmt, pos, val.as_ptr()));
168
169#[sealed]
170impl<'a> ToParam for &'a str {
171 fn bind_param(self, stmt: &mut Statement, pos: i32) -> Result<()> {
172 let val = self.as_bytes();
173 let len = val.len();
174 Error::from_sqlite(unsafe {
175 sqlite3_match_version! {
176 3_008_007 => ffi::sqlite3_bind_text64(stmt.base, pos, val.as_ptr() as _, len as _, ffi::sqlite_transient(), ffi::SQLITE_UTF8 as _),
177 _ => ffi::sqlite3_bind_text(stmt.base, pos, val.as_ptr() as _, len as _, ffi::sqlite_transient()),
178 }
179 })
180 }
181}
182
183#[sealed]
184impl<'a> ToParam for &'a ValueRef {
185 fn bind_param(self, stmt: &mut Statement, pos: i32) -> Result<()> {
186 unsafe { Error::from_sqlite(ffi::sqlite3_bind_value(stmt.base, pos, self.as_ptr())) }
187 }
188}
189
190#[sealed]
191impl<'a> ToParam for &'a [u8] {
192 fn bind_param(self, stmt: &mut Statement, pos: i32) -> Result<()> {
193 let len = self.len();
194 unsafe {
195 Error::from_sqlite(sqlite3_match_version! {
196 3_008_007 => ffi::sqlite3_bind_blob64(
197 stmt.base,
198 pos,
199 self.as_ptr() as _,
200 len as _,
201 ffi::sqlite_transient(),
202 ),
203 _ => ffi::sqlite3_bind_blob(
204 stmt.base,
205 pos,
206 self.as_ptr() as _,
207 len as _,
208 ffi::sqlite_transient(),
209 ),
210 })
211 }
212 }
213}
214
215#[sealed]
216impl<'a, const N: usize> ToParam for &'a [u8; N] {
217 fn bind_param(self, stmt: &mut Statement, pos: i32) -> Result<()> {
218 self.as_slice().bind_param(stmt, pos)
219 }
220}
221
222#[sealed]
224impl ToParam for Value {
225 fn bind_param(self, stmt: &mut Statement, pos: i32) -> Result<()> {
226 match self {
227 Value::Integer(x) => x.bind_param(stmt, pos),
228 Value::Float(x) => x.bind_param(stmt, pos),
229 Value::Text(x) => x.bind_param(stmt, pos),
230 Value::Blob(x) => x.bind_param(stmt, pos),
231 Value::Null => ().bind_param(stmt, pos),
232 }
233 }
234}
235
236#[sealed]
238impl<T> ToParam for Option<T>
239where
240 T: ToParam,
241{
242 fn bind_param(self, stmt: &mut Statement, pos: i32) -> Result<()> {
243 match self {
244 Some(x) => x.bind_param(stmt, pos),
245 None => ().bind_param(stmt, pos),
246 }
247 }
248}
249
250#[sealed]
252impl<T: 'static> ToParam for PassedRef<T> {
253 fn bind_param(self, stmt: &mut Statement, pos: i32) -> Result<()> {
254 let _ = (POINTER_TAG, &stmt, pos);
255 sqlite3_require_version!(3_020_000, unsafe {
256 Error::from_sqlite(ffi::sqlite3_bind_pointer(
257 stmt.base,
258 pos,
259 Box::into_raw(Box::new(self)) as _,
260 POINTER_TAG,
261 Some(ffi::drop_boxed::<PassedRef<T>>),
262 ))
263 })
264 }
265}
266
267#[sealed]
270impl<K, V> ToParam for (K, V)
271where
272 K: Into<Vec<u8>>,
273 V: ToParam,
274{
275 fn bind_param(self, stmt: &mut Statement, _: i32) -> Result<()> {
276 let pos = stmt.parameter_position(self.0);
277 match pos {
278 Some(pos) => self.1.bind_param(stmt, pos.get()),
279 None => Err(SQLITE_RANGE),
280 }
281 }
282}