db-derive 0.1.8

PostgreSQL/SQLite pooling derive system
Documentation
use {
    crate::{sql::Sql, table::Table, ConnTrans, Connection, Error, Row, Transaction},
    std::convert::TryInto,
};

pub trait Query<'__query>: Sql<'__query> {
    fn query_row<C: TryInto<ConnTrans<'__query>>, T: Table>(
        &'__query self,
        into_conn_trans: C,
    ) -> Result<T, Error>
    where
        Error: From<C::Error>,
    {
        let conn_trans = into_conn_trans.try_into()?;

        match conn_trans {
            ConnTrans::Conn(conn) => match conn {
                #[cfg(feature = "postgresql")]
                Connection::PostgreSQL(mut conn) => {
                    let rows = conn.query(
                        self.sql_postgres().as_ref(),
                        self.params_postgres().as_ref(),
                    )?;

                    if rows.is_empty() {
                        return Err(Error::QueryReturnedNoRows);
                    }

                    let row = rows.into_iter().next().unwrap();

                    if row.columns().len() != T::columns() {
                        return Err(Error::MismatchedColumnCount);
                    }

                    let typ = T::from_row(Row::PostgreSQL(row))?;

                    Ok(typ)
                }
                #[cfg(feature = "sqlite")]
                Connection::SQLite(conn) => {
                    let mut stmt = conn.prepare(self.sql_sqlite().as_ref())?;

                    let mut rows = stmt.query(self.params_sqlite().as_ref())?;

                    let next = rows.next()?;

                    if next.is_none() {
                        return Err(Error::QueryReturnedNoRows);
                    }

                    let row = next.unwrap();

                    if row.column_count() != T::columns() {
                        return Err(Error::MismatchedColumnCount);
                    }

                    let typ = T::from_row(Row::SQLite(row))?;

                    Ok(typ)
                }
            },
            ConnTrans::Trans(trans) => match trans {
                #[cfg(feature = "postgresql")]
                Transaction::PostgreSQL(mut trans) => {
                    let rows = trans.query(
                        self.sql_postgres().as_ref(),
                        self.params_postgres().as_ref(),
                    )?;

                    if rows.is_empty() {
                        return Err(Error::QueryReturnedNoRows);
                    }

                    let row = rows.into_iter().next().unwrap();

                    if row.columns().len() != T::columns() {
                        return Err(Error::MismatchedColumnCount);
                    }

                    let typ = T::from_row(Row::PostgreSQL(row))?;

                    Ok(typ)
                }
                #[cfg(feature = "sqlite")]
                Transaction::SQLite(trans) => {
                    let mut stmt = trans.prepare(self.sql_sqlite().as_ref())?;

                    let mut rows = stmt.query(self.params_sqlite().as_ref())?;

                    let next = rows.next()?;

                    if next.is_none() {
                        return Err(Error::QueryReturnedNoRows);
                    }

                    let row = next.unwrap();

                    if row.column_count() != T::columns() {
                        return Err(Error::MismatchedColumnCount);
                    }

                    let typ = T::from_row(Row::SQLite(row))?;

                    Ok(typ)
                }
            },
        }
    }

    fn query_rows<C: TryInto<ConnTrans<'__query>>, T: Table>(
        &'__query self,
        into_conn_trans: C,
    ) -> Result<Vec<T>, Error>
    where
        Error: From<C::Error>,
    {
        let conn_trans = into_conn_trans.try_into()?;

        match conn_trans {
            ConnTrans::Conn(conn) => match conn {
                #[cfg(feature = "postgresql")]
                Connection::PostgreSQL(mut conn) => {
                    let rows = conn.query(
                        self.sql_postgres().as_ref(),
                        self.params_postgres().as_ref(),
                    )?;

                    let types = rows
                        .into_iter()
                        .map(|row| {
                            if row.columns().len() != T::columns() {
                                Err(Error::MismatchedColumnCount)
                            } else {
                                T::from_row(Row::PostgreSQL(row))
                            }
                        })
                        .collect::<Result<Vec<_>, Error>>()?;

                    Ok(types)
                }
                #[cfg(feature = "sqlite")]
                Connection::SQLite(conn) => {
                    let mut stmt = conn.prepare(self.sql_sqlite().as_ref())?;

                    let mut rows = stmt.query(self.params_sqlite().as_ref())?;

                    let mut vec = Vec::new();

                    while let Some(row) = rows.next()? {
                        if row.column_count() != T::columns() {
                            return Err(Error::MismatchedColumnCount);
                        }

                        let typ = T::from_row(Row::SQLite(row))?;

                        vec.push(typ);
                    }

                    Ok(vec)
                }
            },
            ConnTrans::Trans(trans) => match trans {
                #[cfg(feature = "postgresql")]
                Transaction::PostgreSQL(mut trans) => {
                    let rows = trans.query(
                        self.sql_postgres().as_ref(),
                        self.params_postgres().as_ref(),
                    )?;

                    let types = rows
                        .into_iter()
                        .map(|row| {
                            if row.columns().len() != T::columns() {
                                Err(Error::MismatchedColumnCount)
                            } else {
                                T::from_row(Row::PostgreSQL(row))
                            }
                        })
                        .collect::<Result<Vec<_>, Error>>()?;

                    Ok(types)
                }
                #[cfg(feature = "sqlite")]
                Transaction::SQLite(trans) => {
                    let mut stmt = trans.prepare(self.sql_sqlite().as_ref())?;

                    let mut rows = stmt.query(self.params_sqlite().as_ref())?;

                    let mut vec = Vec::new();

                    while let Some(row) = rows.next()? {
                        if row.column_count() != T::columns() {
                            return Err(Error::MismatchedColumnCount);
                        }

                        let typ = T::from_row(Row::SQLite(row))?;

                        vec.push(typ);
                    }

                    Ok(vec)
                }
            },
        }
    }
}