use crate::connection::{config::DatabaseResult, value_impl::FromDatabaseValue};
#[cfg(feature = "limbo")]
use limbo::Row;
#[cfg(feature = "mysql")]
use mysql_async::Row as MySqlRow;
#[cfg(feature = "postgres")]
use tokio_postgres::Row as PostgresRow;
use wae_types::{WaeError, WaeErrorKind};
pub enum DatabaseRow {
#[cfg(feature = "limbo")]
Limbo(Row),
#[cfg(feature = "postgres")]
Postgres(PostgresRow),
#[cfg(feature = "mysql")]
MySql(MySqlRow),
}
impl DatabaseRow {
#[cfg(feature = "limbo")]
pub(crate) fn new_limbo(row: Row) -> Self {
Self::Limbo(row)
}
#[cfg(feature = "postgres")]
pub(crate) fn new_postgres(row: PostgresRow) -> Self {
Self::Postgres(row)
}
#[cfg(feature = "mysql")]
pub(crate) fn new_mysql(row: MySqlRow) -> Self {
Self::MySql(row)
}
pub fn get<T: FromDatabaseValue>(&self, index: usize) -> DatabaseResult<T> {
match self {
#[cfg(feature = "limbo")]
Self::Limbo(row) => {
let value = row.get_value(index).map_err(|e| {
WaeError::database(WaeErrorKind::QueryFailed {
query: None,
reason: format!("Failed to get column {}: {}", index, e),
})
})?;
T::from_limbo_value(value)
}
#[cfg(feature = "postgres")]
Self::Postgres(row) => T::from_postgres_row(row, index),
#[cfg(feature = "mysql")]
Self::MySql(row) => T::from_mysql_row(row, index),
}
}
pub fn column_count(&self) -> usize {
match self {
#[cfg(feature = "limbo")]
Self::Limbo(row) => row.column_count(),
#[cfg(feature = "postgres")]
Self::Postgres(row) => row.len(),
#[cfg(feature = "mysql")]
Self::MySql(row) => row.len(),
}
}
}
pub enum DatabaseRows {
#[cfg(feature = "limbo")]
Limbo(limbo::Rows),
#[cfg(feature = "postgres")]
Postgres(Vec<PostgresRow>, usize),
#[cfg(feature = "mysql")]
MySql(Vec<MySqlRow>, usize),
}
impl DatabaseRows {
#[cfg(feature = "limbo")]
pub(crate) fn new_limbo(rows: limbo::Rows) -> Self {
Self::Limbo(rows)
}
#[cfg(feature = "postgres")]
pub(crate) fn new_postgres(rows: Vec<PostgresRow>) -> Self {
Self::Postgres(rows, 0)
}
#[cfg(feature = "mysql")]
pub(crate) fn new_mysql(rows: Vec<MySqlRow>) -> Self {
Self::MySql(rows, 0)
}
pub async fn next(&mut self) -> DatabaseResult<Option<DatabaseRow>> {
match self {
#[cfg(feature = "limbo")]
Self::Limbo(rows) => rows
.next()
.await
.map_err(|e| {
WaeError::database(WaeErrorKind::QueryFailed { query: None, reason: format!("Failed to fetch row: {}", e) })
})
.map(|opt| opt.map(DatabaseRow::new_limbo)),
#[cfg(feature = "postgres")]
Self::Postgres(rows, index) => {
if *index < rows.len() {
let row = DatabaseRow::new_postgres(rows[*index].clone());
*index += 1;
Ok(Some(row))
}
else {
Ok(None)
}
}
#[cfg(feature = "mysql")]
Self::MySql(rows, index) => {
if *index < rows.len() {
let row = DatabaseRow::new_mysql(rows[*index].clone());
*index += 1;
Ok(Some(row))
}
else {
Ok(None)
}
}
}
}
pub async fn collect(mut self) -> DatabaseResult<Vec<DatabaseRow>> {
let mut rows = Vec::new();
while let Some(row) = self.next().await? {
rows.push(row);
}
Ok(rows)
}
}