sqlx-query-dsl 0.1.1

A query DSL extension for SQLx
Documentation

use sqlx::{MySql, MySqlPool, QueryBuilder};
use crate::params::QueryParams;
use crate::whitelist::FieldWhitelist;
use crate::builder::build_filter;

/// 分页查询结果封装
pub struct PageResult<T> {
    /// 总记录数
    pub total: i64,
    /// 当前页的数据列表
    pub list: Vec<T>,
}

/// 执行分页查询
///
/// 该函数会执行两次查询:一次用于计算总数,一次用于获取当前页数据。
///
/// # Arguments
/// * `pool` - 数据库连接池
/// * `base_sql` - 基础查询 SQL(不包含 WHERE, LIMIT 等)
/// * `count_sql` - 用于统计总数的 SQL(通常是 SELECT COUNT(*) ...)
/// * `params` - 查询参数,包含过滤条件和分页信息
/// * `whitelist` - 字段白名单,用于校验过滤条件中的字段
pub async fn query_page<T>(
    pool: &MySqlPool,
    base_sql: &str,
    count_sql: &str,
    params: QueryParams,
    whitelist: FieldWhitelist,
) -> Result<PageResult<T>, sqlx::Error>
where
    T: for<'r> sqlx::FromRow<'r, sqlx::mysql::MySqlRow> + Send + Unpin,
{
    let mut count_qb = QueryBuilder::<MySql>::new(count_sql);
    if let Some(f) = &params.filter {
        count_qb.push(" WHERE ");
        build_filter(&mut count_qb, f, &whitelist).map_err(|e| sqlx::Error::Protocol(e))?;
    }
    let total: i64 = count_qb.build_query_scalar().fetch_one(pool).await?;

    let mut qb = QueryBuilder::<MySql>::new(base_sql);
    if let Some(f) = &params.filter {
        qb.push(" WHERE ");
        build_filter(&mut qb, f, &whitelist).map_err(|e| sqlx::Error::Protocol(e))?;
    }
    qb.push(" LIMIT ");
    qb.push_bind(params.page_size);
    qb.push(" OFFSET ");
    qb.push_bind(params.page * params.page_size);

    let list = qb.build_query_as::<T>().fetch_all(pool).await?;
    Ok(PageResult { total, list })
}