rbatis

Rust Compile Time ORM robustness,async, pure Rust Dynamic SQL

APACHE-2.0 License

Downloads
1.1M
Stars
2.3K
Committers
25

Bot releases are hidden (Show)

rbatis - v1.8.69

Published by zhuxiujia over 3 years ago

v1.8.69 中文更新日志

  • up sqlx-core to 0.5.1
  • Performance Optimization format macro,This is going to be converted to a function
#[crud_enable(formats_pg: "id:{}::uuid")] 

to

 |arg:&str|->String{
    format!("{}::uuid",arg)
}
  • Performance optimization for update_by_id() Because it use method get_id() replace Json serialization
  • Rename CRUDEnable to CRUDTable,and add get_id() method
  • add to_ids() method for all vec/map type for
   #[crud_enable]
#[derive(Clone, Debug)]
pub struct BizActivity {
    pub id: Option<String>,
    pub name: Option<String>,
}
    let biz_activitys = rbatis.fetch_list::<BizActivity>("").await.unwrap();
    /// to_ids() support HashSet.to_ids(),Vec.to_ids(),Array.to_ids(),HashMap.to_ids(),LinkedList.to_ids(),BtreeMap.to_ids()....
    let ids = biz_activitys.to_ids();
    println("{}",ids);//->   ["1","2","3"]
  • CRUD trait use of the Fetch beginning,for example:
    async fn fetch_by_id<T>(&self, context_id: &str, id: &T::IdType) -> Result<T> where  T: CRUDTable;
    async fn fetch_by_wrapper<T>(&self, context_id: &str, w: &Wrapper) -> Result<T>
    where
        T: CRUDTable;
    async fn fetch_page_by_wrapper<T>(
        &self,
        context_id: &str,
        w: &Wrapper,
        page: &dyn IPageRequest,
    ) -> Result<Page<T>> where  T: CRUDTable;
    async fn fetch_list<T>(&self, context_id: &str) -> Result<Vec<T>>  where  T: CRUDTable;
    async fn fetch_list_by_ids<T>(&self, context_id: &str, ids: &[T::IdType]) -> Result<Vec<T>>where   T: CRUDTable;
    async fn fetch_list_by_wrapper<T>(&self, context_id: &str, w: &Wrapper) -> Result<Vec<T>> where T: CRUDTable;
rbatis - v1.8.67

Published by zhuxiujia over 3 years ago

v1.8.67

Hello everyone, welcome to introduce the new version of RBatis

  • fix VersionLockPlugin newVersion is written back to entity!
  • add tokio1.0 support
  • add VersionLockPlugin(It's also called 'optimistic lock') for #69
  • Wrapper now doesn't need to rust call.check()? or rust call.check().unwrap()
  • Py_SQL uses local structure caching, which improves some performance
rbatis - v1.8.65

Published by zhuxiujia almost 4 years ago

v1.8.65

  • fix remove_by_id() method Id_name incorrect's bug
  • py_sql and sql macro support wirte code into block
    for example:
    #[py_sql(RB, "select * from biz_activity group by id")]
    async fn group_by(page_req: &PageRequest) -> Page<BizActivity> {
        println!("{:?}",page_req);
    }
rbatis - v1.8.64

Published by zhuxiujia almost 4 years ago

v1.8.64

  • fix #[crud_enable] not show impl code
  • fix Option not use self struct method
rbatis - v1.8.63

Published by zhuxiujia almost 4 years ago

v1.8.63

  • fix update_by_id sql build error
  • Wrapper use move to reduce clone method
rbatis - v1.8.62

Published by zhuxiujia almost 4 years ago

v1.8.62

  • fix use package error, use 'std::fmt::*' replace 'serde::fmt'
  • fix Postgres TIMESTAMPTZ to decode into rust chrono::DateTime<Utc>
  • add save_by_wrapper
  • support use 'table_name' format arg to change table's name for *by_wrapper method
    for example:
    #[async_std::test]
    pub async fn test_intercept() {
        fast_log::init_log("requests.log", 1000, log::Level::Info, None, true);
        let rb = Rbatis::new();
        rb.link("mysql://root:123456@localhost:3306/test").await.unwrap();
        let mut w = rb.new_wrapper()
            .eq("id", "1")
            .check().unwrap();
        w.formats.insert("table_name".to_string(),"new_table".to_string());
        let r: Result<Option<BizActivity>, Error> = rb.fetch_by_wrapper("", &w).await;
    }                          
 SELECT id,name,pc_link,h5_link,pc_banner_img,h5_banner_img,sort,status,remark,create_time,version,delete_flag FROM new_table WHERE id = ?
rbatis - v1.8.61

Published by zhuxiujia almost 4 years ago

v1.8.61

  • Self-incrementing IDs do not add into SQL
rbatis - v1.8.59

Published by zhuxiujia almost 4 years ago

v1.8.59

  • For now, just dep on the Rbatis library,You don't need to dep on rbatis-macro-driver crate
  • macro_use rbatis_macro_driver need change to macro_use extern crate rbatis;
    for example:
#[macro_use]
extern crate rbatis;
rbatis - v1.8.58

Published by zhuxiujia almost 4 years ago

v1.8.58

  • expr interpreter used stand-alone crate(name 'rexpr: v1.0.*')
  • expr interpreter Add parse validation, Refused to some exception formats
rbatis - v1.8.57

Published by zhuxiujia almost 4 years ago

v1.8.57

  • recode PagePlugin, Automatically determines how 'Group By' keyword uses PackPagePlugin(count stmt sql)
    for example:
    #[py_sql(RB, "select * from biz_activity group by id")]
    async fn group_by(page_req: &PageRequest) -> Page<BizActivity> {}
   //[rbatis] [] Query ==> SELECT count(1) FROM (SELECT * FROM biz_activity group by id) a
  // [rbatis] [] Query ==> SELECT * FROM biz_activity group by id LIMIT 0,10
  • PostgresSQL add config "ssl-mode" "sslmode" identify
rbatis - v1.8.56

Published by zhuxiujia almost 4 years ago

v1.8.56

  • 2.5 times better concurrency Cache performance!! Runtime Cache use DashMap Replace RwLock/HashMap, Because of the poor performance of the latter combination, about 160ns。
    So this change can greatly improve the speed of concurrent cases(It is 2.5 times better than RwLock)

  • this is the performance test for ExprRuntime and PySqlRuntime (use DashMap to Cache data)


    // (Windows10 6Core16GBMem) use Time: 84.0079ms ,each:84 ns/op use QPS: 11900823 QPS/s
    #[test]
    fn test_bench_expr_runtime() {
        let runtime = ExprRuntime::new();
        runtime.eval("1+1", &serde_json::Value::Null);
        runtime.eval("1+1", &serde_json::Value::Null);
        let total = 1000000;
        let now = std::time::Instant::now();
        for _ in 0..total {
            let r = runtime.eval("1+1", &serde_json::Value::Null).unwrap();
            //println!("{}",r);
        }
        now.time(total);
        now.qps(total);
    }

   //(Windows10 6Core16GBMem) use Time: 916.1591ms ,each:916 ns/op use QPS: 1091470 QPS/s
    #[test]
    fn test_bench_pysql_runtime() {
        let runtime = PyRuntime::new(vec![]);
        let mut engine =ExprRuntime::new();
        let py_sql="SELECT * FROM biz_activity where
    if  name!=null:
      name = #{name}
    WHERE id  = 'end';";
        let mut env=serde_json::json!({});
        runtime.eval(&DriverType::Mysql, &py_sql, &mut env, &mut engine).unwrap();
        let total = 1000000;
        let now = std::time::Instant::now();
        for _ in 0..total {
            runtime.eval(&DriverType::Mysql, &py_sql, &mut env, &mut engine).unwrap();
        }
        now.time(total);
        now.qps(total);
    }
rbatis - v1.8.55

Published by zhuxiujia almost 4 years ago

v1.8.55

  • py_sql add some safety check
  • db_adapter add more safety result convert
rbatis - v1.8.54

Published by zhuxiujia almost 4 years ago

v1.8.54

  • The type not yet supported is deserialization as Vec<u8>,so you can use all of database type
  • fix py_sql choose's default value bug
  • py_sql add some simplify style
    for example:
    let info = 'yes':
    bind infos = 'ok':
    choose:
        when age == -1:
          AND age = -1
        _:
          age = 0
  • py_sql add print method support.
    for example:
SELECT * FROM biz_activity where
                         print sql:
                             hello this is sql data
                         print arg_array:
                         print name:
                         print 1+1:
        let mut env = json!({
        "name": "1",
        "age": 27,
        "del":1,
        "ids":[1,2,3]
    });


sql: "SELECT * FROM biz_activity where hello this is sql data"
arg_array: []
name: "1"
1+1: 2
result sql:SELECT * FROM biz_activity where hello this is sql data 
arg array:[]
rbatis - v1.8.53

Published by zhuxiujia almost 4 years ago

v1.8.53

  • up 'sqlx-core' driver version to 0.4.2
  • impl all Debug for Rbatis
  • 'tx:' prefix move to TxManager, so you can Custom transaction ID identification prefix
rbatis - v1.8.52

Published by zhuxiujia almost 4 years ago

v1.8.52

  • fix add decimal serde feature support
rbatis - v1.8.51

Published by zhuxiujia almost 4 years ago

v1.8.51

*#[py_sql] and #[sql] macro must define async fn(Prevent THE IDE from predicting ambiguity, and understand it)

  • PostgresSQL add "VARBIT", "BIT","VARBIT[]","BIT[]" decode support.
  • format some log print
rbatis - v1.8.50

Published by zhuxiujia almost 4 years ago

v1.8.50

  • add 'debug_mode' allow show rbatis decode raw json data
    for example(cargo.toml):
rbatis = { version="1.8", features = ["debug_mode"] }
    #[async_std::test]
    pub async fn test_macro_sql_select() {
        fast_log::init_log("requests.log", 1000, log::Level::Info, None, true);
        //use static ref
        RB.link("mysql://root:123456@localhost:3306/test").await.unwrap();
        #[py_sql(RB, "select * from biz_activity where delete_flag = #{del}")]
        fn select_activities(del: i32) -> Vec<BizActivity> {}
        let ret = select_activities(1).await;
    }

2020-12-15 17:36:59.826470 +08:00    INFO rbatis::plugin::log - [rbatis] [] Query ==> select * from biz_activity where delete_flag = ?
                                                                [rbatis] [] Args  ==> [1]
2020-12-15 17:36:59.837442 +08:00    INFO rbatis::plugin::log - [rbatis] [] ReturnRows <== 1
[rbatis] [debug_mode] => [
  {
    "id": "12312",
    "name": "123",
    "pc_link": null,
    "h5_link": null,
    "sort": "1",
    "status": 1,
    "version": "1",
    "remark": null,
    "create_time": "2020-11-11T17:41:03",
    "delete_flag": 1,
    "pc_banner_img": null,
    "h5_banner_img": null
  }
]
  • rbatis_core add OptionToResult trait, you can Option is convert to Rbatis Result
    for example:
        let op=Option::Some(1);
        let v=op.to_result("fail info")?;
rbatis - v1.8.49

Published by zhuxiujia almost 4 years ago

v1.8.49

  • support macro (format) ,formats_pg:,formats_postgres:,formats_mysql:,formats_mssql:,formats_sqlite
#[crud_enable(formats_pg:"id:{}::uuid)]
pub struct Table{
  pub id:Option<Uuid>,
  pub name:Option<String>
}
#[crud_enable(id_name:"id"|id_type:"Uuid"|table_name:"biz_activity"|table_columns:"id,'status'"|formats_pg:"id:{}::uuid")]
pub struct Table{
  pub id:Option<Uuid>,
  pub status:Option<String>
}
rbatis - v1.8.47

Published by zhuxiujia almost 4 years ago

v1.8.47

  • fix #59 #61
  • add #[crud_enable(formats_pg: column:format_data)] macro for #59 . so you can format any table column for mysql,pg,sqlite,mssql....(also include Wrapper support format)
    for example( ‘id:{}::uuid’ That means by column format to 'id_value::uuid' ):
    #[async_std::test]
    pub async fn test_postgres_uuid() {
        fast_log::init_log("requests.log", 1000, log::Level::Info, None, true);
        let rb = Rbatis::new();
        rb.link("postgres://postgres:123456@localhost:5432/postgres").await.unwrap();

        //'formats_pg' use postgres format
        //'id' ->  table column 'id'
        //'{}::uuid' -> format data str
        #[crud_enable(formats_pg:id:{}::uuid)]
        #[derive(Clone, Debug)]
        pub struct BizUuid {
            pub id: Option<Uuid>,
            pub name: Option<String>,
        }
        let uuid = Uuid::from_str("df07fea2-b819-4e05-b86d-dfc15a5f52a9").unwrap();
        //create table
        rb.exec("", "CREATE TABLE biz_uuid( id uuid, name VARCHAR, PRIMARY KEY(id));").await;
        //insert table
        rb.save("", &BizUuid { id: Some(uuid), name: Some("test".to_string()) }).await;
        //update table
        rb.update_by_id("",&BizUuid{ id: Some(uuid.clone()), name: Some("test_updated".to_string()) }).await;
        //query table
        let data: BizUuid = rb.fetch_by_id("", &uuid).await.unwrap();
        println!("{:?}", data);
        //delete table
        rb.remove_by_id::<BizUuid>("",&uuid).await;
    }

exec result log

2020-12-14 14:26:58.072638 +08:00    INFO rbatis::plugin::log - [rbatis] [] Exec  ==> CREATE TABLE biz_uuid( id uuid, name VARCHAR, PRIMARY KEY(id));
2020-12-14 14:26:58.084423 +08:00    INFO rbatis::plugin::log - [rbatis] [] Exec  ==> INSERT INTO biz_uuid (id,name) VALUES ($1::uuid,$2)
                                                                [rbatis] [] Args  ==> ["df07fea2-b819-4e05-b86d-dfc15a5f52a9","test"]
2020-12-14 14:26:58.092696 +08:00    INFO rbatis::plugin::log - [rbatis] [] RowsAffected <== Ok(
    DBExecResult {
        rows_affected: 1,
        last_insert_id: None,
    },
)
2020-12-14 14:26:58.093312 +08:00    INFO rbatis::plugin::log - [rbatis] [] Exec  ==> UPDATE biz_uuid SET  name = $1 WHERE id = $2::uuid
                                                                [rbatis] [] Args  ==> ["test_updated","df07fea2-b819-4e05-b86d-dfc15a5f52a9"]
2020-12-14 14:26:58.103709 +08:00    INFO rbatis::plugin::log - [rbatis] [] RowsAffected <== Ok(
    DBExecResult {
        rows_affected: 1,
        last_insert_id: None,
    },
)
2020-12-14 14:26:58.103995 +08:00    INFO rbatis::plugin::log - [rbatis] [] Query ==> SELECT id,name FROM biz_uuid WHERE id = $1::uuid
                                                                [rbatis] [] Args  ==> ["df07fea2-b819-4e05-b86d-dfc15a5f52a9"]
2020-12-14 14:26:58.125231 +08:00    INFO rbatis::plugin::log - [rbatis] [] ReturnRows <== 1
2020-12-14 14:26:58.125965 +08:00    INFO rbatis::plugin::log - [rbatis] [] Exec  ==> DELETE FROM biz_uuid WHERE id = $1::uuid
                                                                [rbatis] [] Args  ==> ["df07fea2-b819-4e05-b86d-dfc15a5f52a9"]
BizUuid { id: Some(df07fea2-b819-4e05-b86d-dfc15a5f52a9), name: Some("test_updated") }

rbatis - v1.8.46

Published by zhuxiujia almost 4 years ago

v1.8.46

  • fix Wrapper: If the condition is null, there is a where bug in front of the ORDER BY statement
  • fix Wrapper: trim inaccurate
  • Wrapper change do_math method. for example:
    #[test]
    fn test_do_match() {
        let p = 1;
        let w = Wrapper::new(&DriverType::Postgres)
            .do_match(&[
                (p == 0, |w| w.eq("0", "some")),
                (p == 1, |w| w.eq("1", "some")),
            ], |w| w.eq("default", "default"))
            .check().unwrap();
        assert_eq!(&w.sql,"1 = $1");
    }