uorm 0.9.2

Rust 下的轻量级 ORM 框架,借鉴了 Java MyBatis 的设计理念,强调 SQL 与业务逻辑分离。它结合 Rust 的类型系统与宏机制,支持编写原生 SQL 并自动映射结果,兼容 async/await,兼顾性能与可控性。
Documentation
use crate::Result;
use crate::error::DbError;
use crate::tpl::engine;
use crate::udbc::connection::Connection;
use crate::udbc::driver::Driver;
use crate::udbc::value::{FromValue, ToValue, Value};
use log::debug;
use std::collections::HashMap;
use std::time::Instant;

/// 在给定连接上执行 SQL 语句(INSERT、UPDATE、DELETE)。
pub async fn execute_conn<T: ToValue>(
    conn: &mut dyn Connection,
    driver: &dyn Driver,
    template_name: &str,
    sql: &str,
    args: &T,
) -> Result<u64> {
    let start = Instant::now();
    let (rendered_sql, params) = engine::render_template(template_name, sql, args, driver)?;
    let result = conn.execute(&rendered_sql, &params).await;
    let elapsed = start.elapsed().as_millis();

    match &result {
        Ok(affected) => debug!(
            "Execute: sql=\n{}, params={:?}, elapsed={}ms, affected={}",
            &rendered_sql, &params, elapsed, affected
        ),
        Err(e) => debug!(
            "Execute: sql=\n{}, params={:?}, elapsed={}ms, error={:?}",
            &rendered_sql, &params, elapsed, e
        ),
    }

    result
}

/// 在给定连接上执行 SQL 查询并返回原始行数据。
pub async fn query_conn<T: ToValue>(
    conn: &mut dyn Connection,
    driver: &dyn Driver,
    template_name: &str,
    sql: &str,
    args: &T,
) -> Result<Vec<HashMap<String, Value>>> {
    let start = Instant::now();
    let (rendered_sql, params) = engine::render_template(template_name, sql, args, driver)?;
    let result: Result<Vec<HashMap<String, Value>>> = conn.query(&rendered_sql, &params).await;
    let elapsed = start.elapsed().as_millis();

    match &result {
        Ok(rows) => debug!(
            "Query: sql=\n{}, params={:?}, elapsed={}ms, rows={}",
            &rendered_sql,
            &params,
            elapsed,
            rows.len()
        ),
        Err(e) => debug!(
            "Query: sql=\n{}, params={:?}, elapsed={}ms, error={:?}",
            &rendered_sql, &params, elapsed, e
        ),
    }

    result
}

/// 将原始数据库行映射为目标类型 `R`。
pub fn map_rows<R>(rows: Vec<HashMap<String, Value>>) -> Result<Vec<R>>
where
    R: FromValue,
{
    rows.into_iter()
        .map(|r| {
            // debug!("映射行: {:?}", r);
            R::from_value(Value::Map(r))
                .map_err(|e| DbError::SerializationError(format!("Row mapping failed: {:?}", e)))
        })
        .collect()
}