rusqlite/
params.rs

1use crate::{BindIndex, Result, Statement, ToSql};
2
3mod sealed {
4    /// This trait exists just to ensure that the only impls of `trait Params`
5    /// that are allowed are ones in this crate.
6    pub trait Sealed {}
7}
8use sealed::Sealed;
9
10/// Trait used for [sets of parameter][params] passed into SQL
11/// statements/queries.
12///
13/// [params]: https://www.sqlite.org/c3ref/bind_blob.html
14///
15/// Note: Currently, this trait can only be implemented inside this crate.
16/// Additionally, it's methods (which are `doc(hidden)`) should currently not be
17/// considered part of the stable API, although it's possible they will
18/// stabilize in the future.
19///
20/// # Passing parameters to SQLite
21///
22/// Many functions in this library let you pass parameters to SQLite. Doing this
23/// lets you avoid any risk of SQL injection, and is simpler than escaping
24/// things manually. Aside from deprecated functions and a few helpers, this is
25/// indicated by the function taking a generic argument that implements `Params`
26/// (this trait).
27///
28/// ## Positional parameters
29///
30/// For cases where you want to pass a list of parameters where the number of
31/// parameters is known at compile time, this can be done in one of the
32/// following ways:
33///
34/// - For small lists of parameters up to 16 items, they may alternatively be
35///   passed as a tuple, as in `thing.query((1, "foo"))`.
36///   This is somewhat inconvenient for a single item, since you need a
37///   weird-looking trailing comma: `thing.query(("example",))`. That case is
38///   perhaps more cleanly expressed as `thing.query(["example"])`.
39///
40/// - Using the [`rusqlite::params!`](crate::params!) macro, e.g.
41///   `thing.query(rusqlite::params![1, "foo", bar])`. This is mostly useful for
42///   heterogeneous lists where the number of parameters greater than 16, or
43///   homogeneous lists of parameters where the number of parameters exceeds 32.
44///
45/// - For small homogeneous lists of parameters, they can either be passed as:
46///
47///     - an array, as in `thing.query([1i32, 2, 3, 4])` or `thing.query(["foo",
48///       "bar", "baz"])`.
49///
50///     - a reference to an array of references, as in `thing.query(&["foo",
51///       "bar", "baz"])` or `thing.query(&[&1i32, &2, &3])`.
52///       (Note: in this case we don't implement this for slices for coherence
53///       reasons, so it really is only for the "reference to array" types —
54///       hence why the number of parameters must be <= 32, or you need to
55///       reach for `rusqlite::params!`)
56///
57///   Unfortunately, in the current design it's not possible to allow this for
58///   references to arrays of non-references (e.g. `&[1i32, 2, 3]`). Code like
59///   this should instead either use `params!`, an array literal, a `&[&dyn
60///   ToSql]` or if none of those work, [`ParamsFromIter`].
61///
62/// - As a slice of `ToSql` trait object references, e.g. `&[&dyn ToSql]`. This
63///   is mostly useful for passing parameter lists around as arguments without
64///   having every function take a generic `P: Params`.
65///
66/// ### Example (positional)
67///
68/// ```rust,no_run
69/// # use rusqlite::{Connection, Result, params};
70/// fn update_rows(conn: &Connection) -> Result<()> {
71///     let mut stmt = conn.prepare("INSERT INTO test (a, b) VALUES (?1, ?2)")?;
72///
73///     // Using a tuple:
74///     stmt.execute((0, "foobar"))?;
75///
76///     // Using `rusqlite::params!`:
77///     stmt.execute(params![1i32, "blah"])?;
78///
79///     // array literal — non-references
80///     stmt.execute([2i32, 3i32])?;
81///
82///     // array literal — references
83///     stmt.execute(["foo", "bar"])?;
84///
85///     // Slice literal, references:
86///     stmt.execute(&[&2i32, &3i32])?;
87///
88///     // Note: The types behind the references don't have to be `Sized`
89///     stmt.execute(&["foo", "bar"])?;
90///
91///     // However, this doesn't work (see above):
92///     // stmt.execute(&[1i32, 2i32])?;
93///     Ok(())
94/// }
95/// ```
96///
97/// ## Named parameters
98///
99/// SQLite lets you name parameters using a number of conventions (":foo",
100/// "@foo", "$foo"). You can pass named parameters in to SQLite using rusqlite
101/// in a few ways:
102///
103/// - Using the [`rusqlite::named_params!`](crate::named_params!) macro, as in
104///   `stmt.execute(named_params!{ ":name": "foo", ":age": 99 })`. Similar to
105///   the `params` macro, this is most useful for heterogeneous lists of
106///   parameters, or lists where the number of parameters exceeds 32.
107///
108/// - As a slice of `&[(&str, &dyn ToSql)]`. This is what essentially all of
109///   these boil down to in the end, conceptually at least. In theory, you can
110///   pass this as `stmt`.
111///
112/// - As array references, similar to the positional params. This looks like
113///   `thing.query(&[(":foo", &1i32), (":bar", &2i32)])` or
114///   `thing.query(&[(":foo", "abc"), (":bar", "def")])`.
115///
116/// Note: Unbound named parameters will be left to the value they previously
117/// were bound with, falling back to `NULL` for parameters which have never been
118/// bound.
119///
120/// ### Example (named)
121///
122/// ```rust,no_run
123/// # use rusqlite::{Connection, Result, named_params};
124/// fn insert(conn: &Connection) -> Result<()> {
125///     let mut stmt = conn.prepare("INSERT INTO test (key, value) VALUES (:key, :val)")?;
126///     // Using `rusqlite::params!`:
127///     stmt.execute(named_params! { ":key": "one", ":val": 2 })?;
128///     // Alternatively:
129///     stmt.execute(&[(":key", "three"), (":val", "four")])?;
130///     // Or:
131///     stmt.execute(&[(":key", &100), (":val", &200)])?;
132///     Ok(())
133/// }
134/// ```
135///
136/// ## No parameters
137///
138/// You can just use an empty tuple or the empty array literal to run a query
139/// that accepts no parameters.
140///
141/// ### Example (no parameters)
142///
143/// The empty tuple:
144///
145/// ```rust,no_run
146/// # use rusqlite::{Connection, Result, params};
147/// fn delete_all_users(conn: &Connection) -> Result<()> {
148///     // You may also use `()`.
149///     conn.execute("DELETE FROM users", ())?;
150///     Ok(())
151/// }
152/// ```
153///
154/// The empty array:
155///
156/// ```rust,no_run
157/// # use rusqlite::{Connection, Result, params};
158/// fn delete_all_users(conn: &Connection) -> Result<()> {
159///     // Just use an empty array (e.g. `[]`) for no params.
160///     conn.execute("DELETE FROM users", [])?;
161///     Ok(())
162/// }
163/// ```
164///
165/// ## Dynamic parameter list
166///
167/// If you have a number of parameters which is unknown at compile time (for
168/// example, building a dynamic query at runtime), you have two choices:
169///
170/// - Use a `&[&dyn ToSql]`. This is often annoying to construct if you don't
171///   already have this type on-hand.
172/// - Use the [`ParamsFromIter`] type. This essentially lets you wrap an
173///   iterator some `T: ToSql` with something that implements `Params`. The
174///   usage of this looks like `rusqlite::params_from_iter(something)`.
175///
176/// A lot of the considerations here are similar either way, so you should see
177/// the [`ParamsFromIter`] documentation for more info / examples.
178pub trait Params: Sealed {
179    // XXX not public api, might not need to expose.
180    //
181    // Binds the parameters to the statement. It is unlikely calling this
182    // explicitly will do what you want. Please use `Statement::query` or
183    // similar directly.
184    //
185    // For now, just hide the function in the docs...
186    #[doc(hidden)]
187    fn __bind_in(self, stmt: &mut Statement<'_>) -> Result<()>;
188}
189
190// Explicitly impl for empty array. Critically, for `conn.execute([])` to be
191// unambiguous, this must be the *only* implementation for an empty array.
192//
193// This sadly prevents `impl<T: ToSql, const N: usize> Params for [T; N]`, which
194// forces people to use `params![...]` or `rusqlite::params_from_iter` for long
195// homogeneous lists of parameters. This is not that big of a deal, but is
196// unfortunate, especially because I mostly did it because I wanted a simple
197// syntax for no-params that didn't require importing -- the empty tuple fits
198// that nicely, but I didn't think of it until much later.
199//
200// Admittedly, if we did have the generic impl, then we *wouldn't* support the
201// empty array literal as a parameter, since the `T` there would fail to be
202// inferred. The error message here would probably be quite bad, and so on
203// further thought, probably would end up causing *more* surprises, not less.
204impl Sealed for [&(dyn ToSql + Send + Sync); 0] {}
205impl Params for [&(dyn ToSql + Send + Sync); 0] {
206    #[inline]
207    fn __bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
208        stmt.ensure_parameter_count(0)
209    }
210}
211
212impl Sealed for &[&dyn ToSql] {}
213impl Params for &[&dyn ToSql] {
214    #[inline]
215    fn __bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
216        stmt.bind_parameters(self)
217    }
218}
219
220impl<S: BindIndex, T: ToSql> Sealed for &[(S, T)] {}
221impl<S: BindIndex, T: ToSql> Params for &[(S, T)] {
222    #[inline]
223    fn __bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
224        stmt.bind_parameters_named(self)
225    }
226}
227
228// Manual impls for the empty and singleton tuple, although the rest are covered
229// by macros.
230impl Sealed for () {}
231impl Params for () {
232    #[inline]
233    fn __bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
234        stmt.ensure_parameter_count(0)
235    }
236}
237
238// I'm pretty sure you could tweak the `single_tuple_impl` to accept this.
239impl<T: ToSql> Sealed for (T,) {}
240impl<T: ToSql> Params for (T,) {
241    #[inline]
242    fn __bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
243        stmt.ensure_parameter_count(1)?;
244        stmt.raw_bind_parameter(1, self.0)?;
245        Ok(())
246    }
247}
248
249macro_rules! single_tuple_impl {
250    ($count:literal : $(($field:tt $ftype:ident)),* $(,)?) => {
251        impl<$($ftype,)*> Sealed for ($($ftype,)*) where $($ftype: ToSql,)* {}
252        impl<$($ftype,)*> Params for ($($ftype,)*) where $($ftype: ToSql,)* {
253            fn __bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
254                stmt.ensure_parameter_count($count)?;
255                $({
256                    debug_assert!($field < $count);
257                    stmt.raw_bind_parameter($field + 1, self.$field)?;
258                })+
259                Ok(())
260            }
261        }
262    }
263}
264
265// We use a macro for the rest, but don't bother with trying to implement it
266// in a single invocation (it's possible to do, but my attempts were almost the
267// same amount of code as just writing it out this way, and much more dense --
268// it is a more complicated case than the TryFrom macro we have for row->tuple).
269//
270// Note that going up to 16 (rather than the 12 that the impls in the stdlib
271// usually support) is just because we did the same in the `TryFrom<Row>` impl.
272// I didn't catch that then, but there's no reason to remove it, and it seems
273// nice to be consistent here; this way putting data in the database and getting
274// data out of the database are more symmetric in a (mostly superficial) sense.
275single_tuple_impl!(2: (0 A), (1 B));
276single_tuple_impl!(3: (0 A), (1 B), (2 C));
277single_tuple_impl!(4: (0 A), (1 B), (2 C), (3 D));
278single_tuple_impl!(5: (0 A), (1 B), (2 C), (3 D), (4 E));
279single_tuple_impl!(6: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F));
280single_tuple_impl!(7: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G));
281single_tuple_impl!(8: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H));
282single_tuple_impl!(9: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I));
283single_tuple_impl!(10: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J));
284single_tuple_impl!(11: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K));
285single_tuple_impl!(12: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L));
286single_tuple_impl!(13: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L), (12 M));
287single_tuple_impl!(14: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L), (12 M), (13 N));
288single_tuple_impl!(15: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L), (12 M), (13 N), (14 O));
289single_tuple_impl!(16: (0 A), (1 B), (2 C), (3 D), (4 E), (5 F), (6 G), (7 H), (8 I), (9 J), (10 K), (11 L), (12 M), (13 N), (14 O), (15 P));
290
291macro_rules! impl_for_array_ref {
292    ($($N:literal)+) => {$(
293        // These are already generic, and there's a shedload of them, so lets
294        // avoid the compile time hit from making them all inline for now.
295        impl<T: ToSql + ?Sized> Sealed for &[&T; $N] {}
296        impl<T: ToSql + ?Sized> Params for &[&T; $N] {
297            fn __bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
298                stmt.bind_parameters(self)
299            }
300        }
301        impl<S: BindIndex, T: ToSql + ?Sized> Sealed for &[(S, &T); $N] {}
302        impl<S: BindIndex, T: ToSql + ?Sized> Params for &[(S, &T); $N] {
303            fn __bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
304                stmt.bind_parameters_named(self)
305            }
306        }
307        impl<T: ToSql> Sealed for [T; $N] {}
308        impl<T: ToSql> Params for [T; $N] {
309            #[inline]
310            fn __bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
311                stmt.bind_parameters(&self)
312            }
313        }
314    )+};
315}
316
317// Following libstd/libcore's (old) lead, implement this for arrays up to `[_;
318// 32]`. Note `[_; 0]` is intentionally omitted for coherence reasons, see the
319// note above the impl of `[&dyn ToSql; 0]` for more information.
320//
321// Note that this unfortunately means we can't use const generics here, but I
322// don't really think it matters -- users who hit that can use `params!` anyway.
323impl_for_array_ref!(
324    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
325    18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
326);
327
328/// Adapter type which allows any iterator over [`ToSql`] values to implement
329/// [`Params`].
330///
331/// This struct is created by the [`params_from_iter`] function.
332///
333/// This can be useful if you have something like an `&[String]` (of unknown
334/// length), and you want to use them with an API that wants something
335/// implementing `Params`. This way, you can avoid having to allocate storage
336/// for something like a `&[&dyn ToSql]`.
337///
338/// This essentially is only ever actually needed when dynamically generating
339/// SQL — static SQL (by definition) has the number of parameters known
340/// statically. As dynamically generating SQL is itself pretty advanced, this
341/// API is itself for advanced use cases (See "Realistic use case" in the
342/// examples).
343///
344/// # Example
345///
346/// ## Basic usage
347///
348/// ```rust,no_run
349/// use rusqlite::{params_from_iter, Connection, Result};
350/// use std::collections::BTreeSet;
351///
352/// fn query(conn: &Connection, ids: &BTreeSet<String>) -> Result<()> {
353///     assert_eq!(ids.len(), 3, "Unrealistic sample code");
354///
355///     let mut stmt = conn.prepare("SELECT * FROM users WHERE id IN (?1, ?2, ?3)")?;
356///     let _rows = stmt.query(params_from_iter(ids.iter()))?;
357///
358///     // use _rows...
359///     Ok(())
360/// }
361/// ```
362///
363/// ## Realistic use case
364///
365/// Here's how you'd use `ParamsFromIter` to call [`Statement::exists`] with a
366/// dynamic number of parameters.
367///
368/// ```rust,no_run
369/// use rusqlite::{Connection, Result};
370///
371/// pub fn any_active_users(conn: &Connection, usernames: &[String]) -> Result<bool> {
372///     if usernames.is_empty() {
373///         return Ok(false);
374///     }
375///
376///     // Note: `repeat_vars` never returns anything attacker-controlled, so
377///     // it's fine to use it in a dynamically-built SQL string.
378///     let vars = repeat_vars(usernames.len());
379///
380///     let sql = format!(
381///         // In practice this would probably be better as an `EXISTS` query.
382///         "SELECT 1 FROM user WHERE is_active AND name IN ({}) LIMIT 1",
383///         vars,
384///     );
385///     let mut stmt = conn.prepare(&sql)?;
386///     stmt.exists(rusqlite::params_from_iter(usernames))
387/// }
388///
389/// // Helper function to return a comma-separated sequence of `?`.
390/// // - `repeat_vars(0) => panic!(...)`
391/// // - `repeat_vars(1) => "?"`
392/// // - `repeat_vars(2) => "?,?"`
393/// // - `repeat_vars(3) => "?,?,?"`
394/// // - ...
395/// fn repeat_vars(count: usize) -> String {
396///     assert_ne!(count, 0);
397///     let mut s = "?,".repeat(count);
398///     // Remove trailing comma
399///     s.pop();
400///     s
401/// }
402/// ```
403///
404/// That is fairly complex, and even so would need even more work to be fully
405/// production-ready:
406///
407/// - production code should ensure `usernames` isn't so large that it will
408///   surpass [`conn.limit(Limit::SQLITE_LIMIT_VARIABLE_NUMBER)`][limits],
409///   chunking if too large. (Note that the limits api requires rusqlite to have
410///   the "limits" feature).
411///
412/// - `repeat_vars` can be implemented in a way that avoids needing to allocate
413///   a String.
414///
415/// - Etc...
416///
417/// [limits]: crate::Connection::limit
418///
419/// This complexity reflects the fact that `ParamsFromIter` is mainly intended
420/// for advanced use cases — most of the time you should know how many
421/// parameters you have statically (and if you don't, you're either doing
422/// something tricky, or should take a moment to think about the design).
423#[derive(Clone, Debug)]
424pub struct ParamsFromIter<I>(I);
425
426/// Constructor function for a [`ParamsFromIter`]. See its documentation for
427/// more.
428#[inline]
429pub fn params_from_iter<I>(iter: I) -> ParamsFromIter<I>
430where
431    I: IntoIterator,
432    I::Item: ToSql,
433{
434    ParamsFromIter(iter)
435}
436
437impl<I> Sealed for ParamsFromIter<I>
438where
439    I: IntoIterator,
440    I::Item: ToSql,
441{
442}
443
444impl<I> Params for ParamsFromIter<I>
445where
446    I: IntoIterator,
447    I::Item: ToSql,
448{
449    #[inline]
450    fn __bind_in(self, stmt: &mut Statement<'_>) -> Result<()> {
451        stmt.bind_parameters(self.0)
452    }
453}