use sqlx::{mysql::MySqlRow, MySqlPool};
use super::executor;
use crate::core::condition::SqlValue;
use crate::core::model::Model;
use crate::core::query::QueryBuilder;
pub trait MysqlModel: Model + for<'r> sqlx::FromRow<'r, MySqlRow> + Send + Unpin {
fn all(
pool: &MySqlPool,
) -> impl std::future::Future<Output = Result<Vec<Self>, sqlx::Error>> + Send
where
Self: Sized,
{
executor::fetch_all(pool, Self::query())
}
fn find_where(
pool: &MySqlPool,
builder: QueryBuilder<Self>,
) -> impl std::future::Future<Output = Result<Vec<Self>, sqlx::Error>> + Send
where
Self: Sized,
{
executor::fetch_all(pool, builder)
}
fn find_by_pk(
pool: &MySqlPool,
id: impl Into<SqlValue> + Send,
) -> impl std::future::Future<Output = Result<Option<Self>, sqlx::Error>> + Send
where
Self: Sized,
{
executor::fetch_optional(pool, Self::find(id))
}
fn find_or_fail(
pool: &MySqlPool,
id: impl Into<SqlValue> + Send,
) -> impl std::future::Future<Output = Result<Self, sqlx::Error>> + Send
where
Self: Sized,
{
async move {
match executor::fetch_optional(pool, Self::find(id)).await? {
Some(row) => Ok(row),
None => Err(sqlx::Error::RowNotFound),
}
}
}
fn count(pool: &MySqlPool) -> impl std::future::Future<Output = Result<i64, sqlx::Error>> + Send
where
Self: Sized,
{
executor::count(pool, Self::query())
}
fn count_where(
pool: &MySqlPool,
builder: QueryBuilder<Self>,
) -> impl std::future::Future<Output = Result<i64, sqlx::Error>> + Send
where
Self: Sized,
{
executor::count(pool, builder)
}
fn first(
pool: &MySqlPool,
) -> impl std::future::Future<Output = Result<Option<Self>, sqlx::Error>> + Send
where
Self: Sized,
{
executor::fetch_optional(pool, Self::query().limit(1))
}
fn last(
pool: &MySqlPool,
) -> impl std::future::Future<Output = Result<Option<Self>, sqlx::Error>> + Send
where
Self: Sized,
{
let pk = Self::primary_key();
executor::fetch_optional(pool, Self::query().order_by_desc(pk).limit(1))
}
fn filter(col: &str, val: impl Into<SqlValue>) -> QueryBuilder<Self>
where
Self: Sized,
{
Self::query().where_eq(col, val)
}
fn find_query(id: impl Into<SqlValue>) -> QueryBuilder<Self>
where
Self: Sized,
{
Self::find(id)
}
fn create(
pool: &MySqlPool,
data: &[(&str, SqlValue)],
) -> impl std::future::Future<Output = Result<i64, sqlx::Error>> + Send
where
Self: Sized,
{
executor::insert(pool, Self::table_name(), data)
}
fn update_by_pk(
pool: &MySqlPool,
id: impl Into<SqlValue> + Send,
data: &[(&str, SqlValue)],
) -> impl std::future::Future<Output = Result<u64, sqlx::Error>> + Send
where
Self: Sized,
{
executor::update(
pool,
Self::table_name(),
Self::primary_key(),
id.into(),
data,
)
}
fn delete_by_pk(
pool: &MySqlPool,
id: impl Into<SqlValue> + Send,
) -> impl std::future::Future<Output = Result<u64, sqlx::Error>> + Send
where
Self: Sized,
{
executor::delete(pool, Self::table_name(), Self::primary_key(), id.into())
}
fn delete_self(
&self,
pool: &MySqlPool,
) -> impl std::future::Future<Output = Result<u64, sqlx::Error>> + Send
where
Self: Sized,
{
let val = self.pk_value();
executor::delete(pool, Self::table_name(), Self::primary_key(), val)
}
fn sum(
pool: &MySqlPool,
col: &str,
) -> impl std::future::Future<Output = Result<Option<f64>, sqlx::Error>> + Send
where
Self: Sized,
{
let expr = format!("SUM(`{col}`)");
async move { executor::aggregate(pool, Self::table_name(), &expr, "", vec![]).await }
}
fn avg(
pool: &MySqlPool,
col: &str,
) -> impl std::future::Future<Output = Result<Option<f64>, sqlx::Error>> + Send
where
Self: Sized,
{
let expr = format!("AVG(`{col}`)");
async move { executor::aggregate(pool, Self::table_name(), &expr, "", vec![]).await }
}
fn max(
pool: &MySqlPool,
col: &str,
) -> impl std::future::Future<Output = Result<Option<f64>, sqlx::Error>> + Send
where
Self: Sized,
{
let expr = format!("MAX(`{col}`)");
async move { executor::aggregate(pool, Self::table_name(), &expr, "", vec![]).await }
}
fn min(
pool: &MySqlPool,
col: &str,
) -> impl std::future::Future<Output = Result<Option<f64>, sqlx::Error>> + Send
where
Self: Sized,
{
let expr = format!("MIN(`{col}`)");
async move { executor::aggregate(pool, Self::table_name(), &expr, "", vec![]).await }
}
}
impl<T> MysqlModel for T where T: Model + for<'r> sqlx::FromRow<'r, MySqlRow> + Send + Unpin {}