use crate::{Appender, Result, ToSql};
mod sealed {
pub trait Sealed {}
}
use sealed::Sealed;
pub trait AppenderParams: Sealed {
#[doc(hidden)]
fn __bind_in(self, stmt: &mut Appender<'_>) -> Result<()>;
}
impl Sealed for [&dyn ToSql; 0] {}
impl AppenderParams for [&dyn ToSql; 0] {
#[inline]
fn __bind_in(self, stmt: &mut Appender<'_>) -> Result<()> {
stmt.append_parameter_row(&[] as &[&dyn ToSql])
}
}
impl Sealed for &[&dyn ToSql] {}
impl AppenderParams for &[&dyn ToSql] {
#[inline]
fn __bind_in(self, stmt: &mut Appender<'_>) -> Result<()> {
stmt.append_parameter_row(self)
}
}
macro_rules! impl_for_array_ref {
($($N:literal)+) => {$(
impl<T: ToSql + ?Sized> Sealed for &[&T; $N] {}
impl<T: ToSql + ?Sized> AppenderParams for &[&T; $N] {
fn __bind_in(self, stmt: &mut Appender<'_>) -> Result<()> {
stmt.append_parameter_row(self)
}
}
impl<T: ToSql> Sealed for [T; $N] {}
impl<T: ToSql> AppenderParams for [T; $N] {
#[inline]
fn __bind_in(self, stmt: &mut Appender<'_>) -> Result<()> {
stmt.append_parameter_row(&self)
}
}
)+};
}
impl_for_array_ref!(
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
);
macro_rules! impl_appender_params_for_tuple {
($($T:ident),+) => {
impl<$($T: ToSql),+> Sealed for ($($T,)+) {}
impl<$($T: ToSql),+> AppenderParams for ($($T,)+) {
fn __bind_in(self, stmt: &mut Appender<'_>) -> Result<()> {
#[allow(non_snake_case)]
let ($($T,)+) = &self;
stmt.append_parameter_row([$($T as &dyn ToSql),+])
}
}
};
}
impl_appender_params_for_tuple!(T1);
impl_appender_params_for_tuple!(T1, T2);
impl_appender_params_for_tuple!(T1, T2, T3);
impl_appender_params_for_tuple!(T1, T2, T3, T4);
impl_appender_params_for_tuple!(T1, T2, T3, T4, T5);
impl_appender_params_for_tuple!(T1, T2, T3, T4, T5, T6);
impl_appender_params_for_tuple!(T1, T2, T3, T4, T5, T6, T7);
impl_appender_params_for_tuple!(T1, T2, T3, T4, T5, T6, T7, T8);
impl_appender_params_for_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
impl_appender_params_for_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
impl_appender_params_for_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
impl_appender_params_for_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
impl_appender_params_for_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
impl_appender_params_for_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
impl_appender_params_for_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
impl_appender_params_for_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);
#[derive(Clone, Debug)]
pub struct AppenderParamsFromIter<I>(I);
#[inline]
pub fn appender_params_from_iter<I>(iter: I) -> AppenderParamsFromIter<I>
where
I: IntoIterator,
I::Item: ToSql,
{
AppenderParamsFromIter(iter)
}
impl<I> Sealed for AppenderParamsFromIter<I>
where
I: IntoIterator,
I::Item: ToSql,
{
}
impl<I> AppenderParams for AppenderParamsFromIter<I>
where
I: IntoIterator,
I::Item: ToSql,
{
#[inline]
fn __bind_in(self, stmt: &mut Appender<'_>) -> Result<()> {
stmt.append_parameter_row(self.0)
}
}
#[cfg(test)]
mod tests {
use crate::{Connection, Result};
#[test]
fn test_append_row_tuple() -> Result<()> {
let db = Connection::open_in_memory()?;
db.execute_batch("CREATE TABLE test (id INTEGER, name TEXT)")?;
let mut app = db.appender("test")?;
app.append_row((1i32, "alice"))?;
app.flush()?;
let mut stmt = db.prepare("SELECT id, name FROM test")?;
let mut rows = stmt.query([])?;
let row = rows.next()?.unwrap();
assert_eq!(row.get::<_, i32>(0)?, 1i32);
assert_eq!(row.get::<_, String>(1)?, "alice");
Ok(())
}
#[test]
fn test_append_rows_iterator_tuple() -> Result<()> {
let db = Connection::open_in_memory()?;
db.execute_batch("CREATE TABLE test (id INTEGER, name TEXT)")?;
#[allow(clippy::useless_vec)]
let data = vec![(1, "alice"), (2, "bob")];
let mut app = db.appender("test")?;
app.append_rows(data.iter().map(|(id, name)| (*id, *name)))?;
app.flush()?;
let count: i32 = db.query_row("SELECT COUNT(*) FROM test", [], |r| r.get(0))?;
assert_eq!(count, 2);
Ok(())
}
}