#orm #async-orm #mysql #postgresql #sqlite

rbatis-codegen

Rust SQL 工具和 ORM 库。一个具有编译时动态 SQL 生成系统的异步、纯 Rust SQL 模块

30 个稳定版本

4.5.20 2024 年 7 月 24 日
4.5.18 2024 年 6 月 20 日
4.5.17 2024 年 3 月 15 日
4.5.7 2023 年 12 月 28 日
4.0.24 2022 年 11 月 4 日

#1366数据库接口

Download history 307/week @ 2024-05-03 265/week @ 2024-05-10 348/week @ 2024-05-17 412/week @ 2024-05-24 553/week @ 2024-05-31 417/week @ 2024-06-07 503/week @ 2024-06-14 477/week @ 2024-06-21 588/week @ 2024-06-28 913/week @ 2024-07-05 686/week @ 2024-07-12 591/week @ 2024-07-19 760/week @ 2024-07-26 614/week @ 2024-08-02 633/week @ 2024-08-09 439/week @ 2024-08-16

每月 2,562 次下载
用于 20 个模块 (直接使用 2 个)

Apache-2.0

235KB
6.5K SLoC

rbatis html 查询语言代码生成

类似于 HTML 逻辑的代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "https://raw.githubusercontent.com/rbatis/rbatis/master/rbatis-codegen/mybatis-3-mapper.dtd">
<mapper>
    <select id="select_by_condition">
        `select * from biz_activity`
        <where>
            <if test="name != ''">
                ` and name like #{name}`
            </if>
            <if test="dt >= '2009-12-12 00:00:00'">
                ` and create_time < #{dt}`
            </if>
            <choose>
                <when test="true">
                    ` and id != '-1'`
                </when>
                <otherwise>and id != -2</otherwise>
            </choose>
            ` and `
            <trim prefixOverrides=" and">
                ` and name != '' `
            </trim>
        </where>
    </select>
</mapper>

例如源代码

use rbatis::executor::Executor;
use rbatis::rbdc::datetime::DateTime;
use rbatis::plugin::page::{Page, PageRequest};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BizActivity {
    pub id: Option<String>,
    pub name: Option<String>,
    pub pc_link: Option<String>,
    pub h5_link: Option<String>,
    pub pc_banner_img: Option<String>,
    pub h5_banner_img: Option<String>,
    pub sort: Option<String>,
    pub status: Option<i32>,
    pub remark: Option<String>,
    pub create_time: Option<DateTime>,
    pub version: Option<i64>,
    pub delete_flag: Option<i32>,
}
#[html_sql("example/example.html")]
async fn select_by_condition(rb: &dyn Executor, page_req: &PageRequest, name: &str, dt: &DateTime) -> Vec<BizActivity> {
    impled!()
}
2022-08-17 17:16:23.624803 INFO rbatis::plugin::log - [rbatis] [402390551883812864] query  ==> select * from biz_activity where name like ? and create_time < ? and id != '-1' and  name != ''
                                                      [rbatis]                      Args   ==> ["test",DateTime("2022-08-17 17:16:23")]

工作原理

1. 当用户定义 html_sql 方法(当然,py_sql 的实现也是基于将 py_sql 语法树转义为 html_sql

#[html_sql(r#"<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "https://raw.githubusercontent.com/rbatis/rbatis/master/rbatis-codegen/mybatis-3-mapper.dtd">
  <select id="select_by_condition">
        `select * from biz_activity where `
        <if test="name != null">
                ` name like #{name}`
        </if>
  </select>"#)]
async fn select_by_condition(
    rb: &dyn Executor,
    name: &str,
    a: bool,
) -> rbatis::Result<Vec<BizActivity>> {
    impled!()
}

2. RBatis 表达式

  • RBatis 表达式是 #{name}#{age + 1} 和代码测试:<if test="dt >= '2009-12-12 00:00:00'"></if>
  • RBatis 表达式将被转换为原始的 Rust 代码,如果 RBatis 表达式 = #{age + 1},则代码 = rb_arg_map["age"].op_add(1)
  • RBatis 表达式直接使用字符串来比较和处理日期类型,就像 <if test="dt >= '2009-12-12 00:00:00'"></if> #{dt >= '2009-12-12 00:00:00'}

3. 函数体是通过 rbatis-codegen 的过程宏生成的

// pub trait Executor{ //this is rbatis's Executor
// fn exec(&mut self, sql: &str, args: Vec<Value>) -> BoxFuture<'_, Result<ExecResult, Error>>;
//  fn query(&mut self, sql: &str, args: Vec<Value>) -> BoxFuture<'_, Result<Value, Error>>;
// }
pub async fn select_by_condition(
    rb: &dyn Executor,
    name: &str,
    a: bool,
) -> rbatis::Result<Vec<BizActivity>> {
    let mut rb_arg_map = rbs::value::map::ValueMap::new();
    rb_arg_map.insert(
        "name".to_string().into(),
        rbs::to_value(name).unwrap_or_default(),
    );
    rb_arg_map.insert("a".to_string().into(), rbs::to_value(a).unwrap_or_default());
    use rbatis::executor::RBatisRef;
    let driver_type = rb.rb_ref().driver_type()?;
    use rbatis::rbatis_codegen;
    pub fn impl_html_sql(arg: &rbs::Value, _tag: char) -> (String, Vec<rbs::Value>) {
        use rbatis_codegen::ops::*;
        let mut sql = String::with_capacity(55usize);
        let mut args = Vec::with_capacity(20);
        sql.push_str("select * from biz_activity where ");
        if { (&arg["name"]).op_ne(&rbs::Value::Null) }
            .to_owned()
            .into()
        {
            args.push(rbs::to_value({ &arg["name"] }).unwrap_or_default());
            sql.push_str(" name like ?");
        }
        return (sql, args);
    }
    let (mut sql, rb_args) = impl_html_sql(&rbs::Value::Map(rb_arg_map), '?');
    use rbatis::executor::Executor;
    let r = rb.query(&sql, rb_args).await?;
    rbatis::decode::decode(r)
}

依赖项

~4.5–6MB
~139K SLoC