65 lines
1.5 KiB
Rust
65 lines
1.5 KiB
Rust
use std::iter::repeat;
|
|
|
|
use sqlx::{prelude::*, query::Query, sqlite::SqliteArguments, Encode, Sqlite};
|
|
|
|
type BindFn = Box<
|
|
dyn for<'q> FnOnce(
|
|
Query<'q, Sqlite, SqliteArguments<'q>>,
|
|
) -> Query<'q, Sqlite, SqliteArguments<'q>>
|
|
+ Send,
|
|
>;
|
|
|
|
fn make_bind_fn<T>(value: T) -> BindFn
|
|
where
|
|
T: for<'q> Encode<'q, Sqlite> + Type<Sqlite> + Send + 'static,
|
|
{
|
|
Box::new(move |query| query.bind(value))
|
|
}
|
|
|
|
pub struct BindFields {
|
|
binds: Vec<(&'static str, BindFn)>,
|
|
}
|
|
|
|
impl Default for BindFields {
|
|
fn default() -> Self {
|
|
Self { binds: vec![] }
|
|
}
|
|
}
|
|
|
|
impl BindFields {
|
|
#[must_use]
|
|
pub fn push<'a>(
|
|
mut self,
|
|
field: &'static str,
|
|
value: &'a (impl for<'q> Encode<'q, Sqlite> + Type<Sqlite> + Send + 'static + Clone),
|
|
) -> Self {
|
|
self.binds.push((field, make_bind_fn(value.clone())));
|
|
self
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn extend(mut self, other: Self) -> Self {
|
|
self.binds.extend(other.binds);
|
|
self
|
|
}
|
|
|
|
pub fn bind_to_query<'q>(
|
|
self,
|
|
query: Query<'q, Sqlite, SqliteArguments<'q>>,
|
|
) -> Query<'q, Sqlite, SqliteArguments<'q>> {
|
|
let mut query = query;
|
|
for (_, bind_fn) in self.binds {
|
|
query = bind_fn(query);
|
|
}
|
|
query
|
|
}
|
|
|
|
pub fn bind_names(&self) -> impl Iterator<Item = &'static str> + '_ {
|
|
self.binds.iter().map(|(name, _)| *name)
|
|
}
|
|
|
|
pub fn bind_placeholders(&self) -> impl Iterator<Item = &'static str> + '_ {
|
|
repeat("?").take(self.binds.len())
|
|
}
|
|
}
|