30 个稳定版本
4.5.20 | 2024 年 7 月 24 日 |
---|---|
4.5.18 | 2024 年 6 月 20 日 |
4.5.17 | 2024 年 3 月 15 日 |
4.5.7 |
|
4.0.24 | 2022 年 11 月 4 日 |
#1366 在 数据库接口
每月 2,562 次下载
用于 20 个模块 (直接使用 2 个)
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