spin-sqlite-connection 0.2.3

Spin Sqlite Connection abstraction
Documentation
use spin_sdk::sqlite::{Error, QueryResult, Row, Value};
use std::marker::PhantomData;

pub struct SqliteConnection<E>
where
    E: From<Error>,
{
    inner: spin_sdk::sqlite::Connection,
    phantomdata: PhantomData<E>,
}

impl<E: From<Error>> SqliteConnection<E> {
    pub fn try_open_default(migrations: Option<&str>) -> Result<Self, E> {
        let connection = spin_sdk::sqlite::Connection::open_default()?;
        if let Some(statements) = migrations {
            for statement in statements.split('\n').map(|line| line.trim()) {
                connection.execute(statement, &[])?;
            }
        }
        Ok(Self {
            inner: connection,
            phantomdata: PhantomData,
        })
    }

    pub fn query<T>(&self, sql: impl AsRef<str>, parameters: &[Value]) -> Result<Vec<T>, E>
    where
        T: for<'a> TryFrom<Row<'a>, Error = E>,
    {
        self.query_result(sql, parameters)
            .and_then(|query_result| query_result.rows().map(T::try_from).collect())
    }

    fn query_result<S>(&self, sql: S, parameters: &[Value]) -> Result<QueryResult, E>
    where
        S: AsRef<str>,
    {
        self.inner
            .execute(sql.as_ref(), parameters)
            .map_err(E::from)
    }

    pub fn execute<S>(&self, sql: S, parameters: &[Value]) -> Result<i64, E>
    where
        S: AsRef<str>,
    {
        self.inner.execute(sql.as_ref(), parameters)?;
        let changes = self.inner.execute("SELECT changes()", &[])?;
        let row = changes
            .rows
            .first()
            .cloned()
            .ok_or(Error::Io("changes() has no rows".to_owned()))?;
        let count = row
            .get::<i64>(0)
            .ok_or(Error::Io("Column changes() missing".to_owned()))?;
        Ok(count)
    }
}