pub trait Params<'p> {
// Required method
fn bind<'q, 'r>(
self,
q: &'q mut Separated<'r, 'p, Db, &'static str>,
) -> &'q mut Separated<'r, 'p, Db, &'static str>
where 'p: 'r;
}
Expand description
A collection of parameters which can be bound to a SQL query.
This trait allows us to carry around hetergenous lists of parameters (e.g. tuples) and bind them
to a query at the last moment before executing. This means we can manipulate the parameters
independently of the query before executing it. For example, by requiring a trait bound of
Params<'p> + Clone
, we get a list (or tuple) of parameters which can be cloned and then bound
to a query, which allows us to keep a copy of the parameters around in order to retry the query
if it fails.
§Lifetimes
A SQL Query
with lifetime 'q
borrows from both it’s SQL statement (&'q str
) and its
parameters (bound via bind<'q>
). Sometimes, though, it is necessary for the statement and its
parameters to have different (but overlapping) lifetimes. For example, the parameters might be
passed in and owned by the caller, while the query string is constructed in the callee and its
lifetime is limited to the callee scope. (See for example the upsert
function which does exactly this.)
We could rectify this situation with a trait bound like P: for<'q> Params<'q>
, meaning P
must be bindable to a query with a lifetime chosen by the callee. However, when P
is an
associated type, such as an element of an iterator, as in
<I as IntoIter>::Item: for<'q> Params<'q>
, a current limitation
in the Rust compiler then requires P: 'static
, which we don’t necessarily want: the caller
should be able to pass in a reference to avoid expensive cloning.
So, instead, we work around this by making it explicit in the Params
trait that the lifetime
of the query we’re binding to ('q
) may be different than the lifetime of the parameters ('p
)
as long as the parameters outlive the duration of the query (the 'p: 'q
) bound on the
bind
function.