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)
}
},
}
}
}