Giter Site home page Giter Site logo

rbatis / rbatis Goto Github PK

View Code? Open in Web Editor NEW
2.1K 46.0 150.0 6.22 MB

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

Home Page: https://rbatis.github.io/rbatis.io

License: Apache License 2.0

Rust 99.51% Shell 0.01% HTML 0.47% Python 0.02%
orm rust tokio-async-std mysql postgres sqlite tokio sql database rocket actix-web mybatis mybatis-plus

rbatis's Introduction

WebSite | Showcase | Example

Build Status doc.rs unsafe forbidden codecov GitHub release discussions

a compile-time code generation ORM that balances ease of writing with performance and robustness

It is an ORM, a small compiler, a dynamic SQL languages

Thanks to SQLX, deadpool,mobc, Tiberius, MyBatis, xorm and so on reference design or code implementation. Release of V4 is Inspired and supported by these frameworks.**

Performance

  • this bench test is MockTable,MockDriver,MockConnection to Assume that the network I/O time is 0
  • run code rbatis.query_decode::<Vec<i32>>("", vec![]).await; on benches bench_raw()
  • run code MockTable::insert(&rbatis,&t).await; on benches bench_insert()
  • run code MockTable::select_all(&rbatis).await.unwrap(); on benches bench_select()
  • see bench code
---- bench_raw stdout ----(windows/SingleThread)
Time: 52.4187ms ,each:524 ns/op
QPS: 1906435 QPS/s

---- bench_select stdout ----(macos-M1Cpu/SingleThread)
Time: 112.927916ms ,each:1129 ns/op
QPS: 885486 QPS/s

---- bench_insert stdout ----(macos-M1Cpu/SingleThread)
Time: 346.576666ms ,each:3465 ns/op
QPS: 288531 QPS/s

Supported OS/Platforms by Workflows CI

  • Rust compiler version v1.75+ later
platform is supported
Linux(unbutu laster***)
Apple/MacOS(laster)
Windows(latest)

Supported data structures

data structure is supported
Option
Vec
HashMap
i32,i64,f32,f64,bool,String...more rust base type
rbatis::rbdc::types::{Bytes,Date,DateTime,Time,Timestamp,Decimal,Json}
rbatis::plugin::page::{Page, PageRequest}
rbs::Value
serde_json::Value ...more serde type
rdbc-mysql::types::*
rdbc-pg::types::*
rdbc-sqlite::types::*
rdbc-mssql::types::*

Supported database driver

database(crates.io) github_link
Mysql rbatis/rbdc-mysql
Postgres rbatis/rbdc-pg
Sqlite rbatis/rbdc-sqlite
Mssql rbatis/rbdc-mssql
MariaDB rbatis/rbdc-mysql
TiDB rbatis/rbdc-mysql
CockroachDB rbatis/rbdc-pg
Oracle chenpengfan/rbdc-oracle
TDengine tdcare/rbdc-tdengine

how to write my DataBase Driver for RBatis?

  • first. define your driver project ,add Cargo.toml deps
[features]
default = ["tls-rustls"]
tls-rustls=["rbdc/tls-rustls"]
tls-native-tls=["rbdc/tls-native-tls"]
[dependencies]
rbs = { version = "4.5"}
rbdc = { version = "4.5", default-features = false,  optional = true }
fastdate = { version = "0.3" }
tokio = { version = "1", features = ["full"] }
  • then. you should impl rbdc::db::{ConnectOptions, Connection, ExecResult, MetaData, Placeholder, Row} trait
  • finish. your driver is finish (you just need call RB.init() methods). it's support RBatis Connection Pool/tls(native,rustls)
#[tokio::main]
async fn main(){
  let rb = rbatis::RBatis::new();
  rb.init(YourDriver {}, "YourDriver://****").unwrap();
}

Supported Connection Pools

database(crates.io) github_link
FastPool-default rbatis/fast_pool
Deadpool Deadpool
MobcPool MobcPool

Supported Web Frameworks

  • any web Frameworks just like ntex, actix-web, axum, hyper, rocket, tide, warp, salvo and more.
Quick example: QueryWrapper and common usages (see example/crud_test.rs for details)
  • Cargo.toml

default

#rbatis deps
rbs = { version = "4.5"}
rbatis = { version = "4.5"}
rbdc-sqlite = { version = "4.5" }
#rbdc-mysql={version="4.5"}
#rbdc-pg={version="4.5"}
#rbdc-mssql={version="4.5"}

#other deps
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
log = "0.4"
fast_log = "1.6"

(option) 'native-tls'

rbs = { version = "4.5" }
rbdc-sqlite = { version = "4.5", default-features = false, features = ["tls-native-tls"] }
#rbdc-mysql={version="4.5", default-features = false, features = ["tls-native-tls"]}
#rbdc-pg={version="4.5", default-features = false, features = ["tls-native-tls"]}
#rbdc-mssql={version="4.5", default-features = false, features = ["tls-native-tls"]}
rbatis = { version = "4.5"}
#other deps
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
log = "0.4"
fast_log = "1.6"

default use

//#[macro_use] define in 'root crate' or 'mod.rs' or 'main.rs'
#[macro_use]
extern crate rbatis;
extern crate rbdc;
use rbatis::rbdc::datetime::DateTime;

#[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>,
}
crud!(BizActivity{});//crud = insert+select_by_column+update_by_column+delete_by_column

impl_select!(BizActivity{select_all_by_id(id:&str,name:&str) => "`where id = #{id} and name = #{name}`"});
impl_select!(BizActivity{select_by_id(id:String) -> Option => "`where id = #{id} limit 1`"});
impl_update!(BizActivity{update_by_name(name:&str) => "`where id = 1`"});
impl_delete!(BizActivity {delete_by_name(name:&str) => "`where name= '2'`"});
impl_select_page!(BizActivity{select_page(name:&str) => "`where name != #{name}`"});

#[tokio::main]
async fn main() {
    /// enable log crate to show sql logs
    fast_log::init(fast_log::Config::new().console()).expect("rbatis init fail");
    /// initialize rbatis. also you can call rb.clone(). this is  an Arc point
    let rb = RBatis::new();
    /// connect to database  
    // sqlite 
    rb.init(SqliteDriver {}, "sqlite://target/sqlite.db").unwrap();
    // mysql 
    // rb.init(MysqlDriver{},"mysql://root:123456@localhost:3306/test").unwrap();
    // postgresql 
    // rb.init(PgDriver{},"postgres://postgres:123456@localhost:5432/postgres").unwrap();
    // mssql/sqlserver
    // rb.init(MssqlDriver{},"jdbc:sqlserver://localhost:1433;User=SA;Password={TestPass!123456};Database=test").unwrap();

    let activity = BizActivity {
        id: Some("2".into()),
        name: Some("2".into()),
        pc_link: Some("2".into()),
        h5_link: Some("2".into()),
        pc_banner_img: None,
        h5_banner_img: None,
        sort: None,
        status: Some(2),
        remark: Some("2".into()),
        create_time: Some(DateTime::now()),
        version: Some(1),
        delete_flag: Some(1),
    };
    let data = BizActivity::insert(&rb, &activity).await;
    println!("insert = {:?}", data);

    let data = BizActivity::select_all_by_id(&rb, "1", "1").await;
    println!("select_all_by_id = {:?}", data);

    let data = BizActivity::select_by_id(&rb, "1".to_string()).await;
    println!("select_by_id = {:?}", data);

    let data = BizActivity::update_by_column(&rb, &activity, "id").await;
    println!("update_by_column = {:?}", data);

    let data = BizActivity::update_by_name(&rb, &activity, "test").await;
    println!("update_by_name = {:?}", data);

    let data = BizActivity::delete_by_column(&rb, "id", &"2".into()).await;
    println!("delete_by_column = {:?}", data);

    let data = BizActivity::delete_by_name(&rb, "2").await;
    println!("delete_by_column = {:?}", data);

    let data = BizActivity::select_page(&rb, &PageRequest::new(1, 10), "2").await;
    println!("select_page = {:?}", data);
}
///...more usage,see crud.rs
  • raw-sql
#[tokio::main]
pub async fn main() {
    use rbatis::RBatis;
    use rbdc_sqlite::driver::SqliteDriver;
    #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
    pub struct BizActivity {
        pub id: Option<String>,
        pub name: Option<String>,
    }
    fast_log::init(fast_log::Config::new().console()).expect("rbatis init fail");
    let rb = RBatis::new();
    rb.init(SqliteDriver {}, "sqlite://target/sqlite.db").unwrap();
    let table: Option<BizActivity> = rb
        .query_decode("select * from biz_activity limit ?", vec![rbs::to_value!(1)])
        .await
        .unwrap();
    let count: u64 = rb
        .query_decode("select count(1) as count from biz_activity", vec![])
        .await
        .unwrap();
    println!(">>>>> table={:?}", table);
    println!(">>>>> count={}", count);
}

macros

  • Important update (pysql removes runtime, directly compiles to static rust code) This means that the performance of SQL generated using py_sql,html_sql is roughly similar to that of handwritten code.

Because of the compile time, the annotations need to declare the database type to be used.

    #[py_sql("select * from biz_activity where delete_flag = 0
                  if name != '':
                    `and name=#{name}`")]
async fn py_sql_tx(rb: &RBatis, tx_id: &String, name: &str) -> Vec<BizActivity> { impled!() }
  • Added html_sql support, a form of organization similar to MyBatis, to facilitate migration of Java systems to Rust( Note that it is also compiled as Rust code at build time and performs close to handwritten code) this is very faster

Because of the compile time, the annotations need to declare the database type to be used

<!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 != ''">
            name like #{name}
        </if>
    </select>
</mapper>
    ///select page must have  '?:&PageRequest' arg and return 'Page<?>'
#[html_sql("example/example.html")]
async fn select_by_condition(rb: &dyn Executor, page_req: &PageRequest, name: &str) -> Page<BizActivity> { impled!() }
use once_cell::sync::Lazy;

pub static RB: Lazy<RBatis> = Lazy::new(|| RBatis::new());

/// Macro generates execution logic based on method definition, similar to @select dynamic SQL of Java/Mybatis
/// RB is the name referenced locally by RBatis, for example DAO ::RB, com:: XXX ::RB... Can be
/// The second parameter is the standard driver SQL. Note that the corresponding database parameter mysql is? , pg is $1...
/// macro auto edit method to  'pub async fn select(name: &str) -> rbatis::core::Result<BizActivity> {}'
///
#[sql("select * from biz_activity where id = ?")]
pub async fn select(rb: &RBatis, name: &str) -> BizActivity {}
//or: pub async fn select(name: &str) -> rbatis::core::Result<BizActivity> {}

#[tokio::test]
pub async fn test_macro() {
    fast_log::init(fast_log::Config::new().console()).expect("rbatis init fail");
    RB.link("mysql://root:123456@localhost:3306/test").await.unwrap();
    let a = select(&RB, "1").await.unwrap();
    println!("{:?}", a);
}

How it works

Rely on rbatis-codegen to create the source code of the corresponding structure from the html file at compile time (with debug_mode(Cargo.toml- rbatis = { features = ["debug_mode"]}) enabled, you can observe the code-generated function), and call the generated method directly at run time. We know that compilation is generally divided into three steps, lexes, syntactic analysis, semantic analysis, and intermediate code generation. In rbatis, Lexical analysis is handled by the dependent func.rs in rbatis-codegen, which relies on syn and quote. Parsing is done by parser_html and parser_pysql in rbatis-codegen The generated syntax tree is a structure defined in the syntax_tree package in rbatis-codegen Intermediate code generation has func.rs generation function, all supported functions are defined in rbatis-codegen

What is described above occurs during the cargo build phase, which is the compilation phase of the rust procedural macro, where the code generated by rbatis-codegen is handed back to the rust compiler for LLVM compilation to produce pure machine code

So I think rbatis is Truly zero overhead dynamic SQL compile-time ORM.

Submit PR(Pull Requests)

You are welcome to submit the merge, and make sure that any functionality you add has the appropriate mock unit test function added under the test package.

Roadmap

  • table sync plugin,auto create table/column (sqlite/mysql/mssql/postgres)
  • customize connection pooling,connection pool add more dynamically configured parameters
  • V5 version

Ask AI For Help(AI帮助)

  • discussions

联系方式/捐赠,或 rbatis 点star

捐赠

zxj347284221

联系方式(添加好友请备注'rbatis') 微信群:先加微信,然后拉进群

zxj347284221

rbatis's People

Contributors

abtzz avatar caisin avatar chrislearn avatar clevertension avatar dependabot[bot] avatar foldingfan avatar frederikhors avatar ggggxiaolong avatar insanebaba avatar jzow avatar kaoimin avatar kotlin2018 avatar litcc avatar lzm420241 avatar minghuaw avatar pickfire avatar pull[bot] avatar pymongo avatar quake avatar umaynit avatar uuz2333 avatar xdevs23 avatar zhuxiujia avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rbatis's Issues

failed to resolve: could not find `core_reexport` in `futures_core`

error[E0433]: failed to resolve: could not find core_reexport in futures_core
--> /Users/__/.cargo/registry/src/github.com-1ecc6299db9ec823/rbatis-1.7.24/src/wrapper.rs:3:19
|
3 | use futures_core::core_reexport::any::Any;
| ^^^^^^^^^^^^^ could not find core_reexport in futures_core

futures 0.3.7出现的问题,无法启动

i128 or u128 is un support

3ks.
I will test #48 later on my project.

I had found a new problem that I can't ensure that is whether in Rbatis.
Doc of serde said that i128 or u128 can implement by macro , but I never found the place or medium to get this.

Pull request for Postgis point support added

Hi There,
Kindly review the pull request #23 for postgis point. I have tested reading columns with postgres and it works, but writing is not yet tested. let me know if you can merge it. I'll update further when I find time about writing point type to database.

kindly check the serialization and deserialization in point.rs file , as it might not be optimal, and can be improved(currently using format macro)

Can you add changelog ?

It's difficult to keep track of changes in different versions with frequent releases. Would be great to have a changelog.
Thank you

快不快?

有数据吗?比如比较 drogon getFastDbClient、diesel、sqlx 和其它的性能。

数据库表模型全是 Option<T>

这个模型的定义里每个字段都是 Option,我用每个字段都需要判空,这样 Rust 一大优势就没了。

#[derive(Serialize, Deserialize, Clone, Debug)]
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<NaiveDateTime>,
    pub version: Option<i32>,
    pub delete_flag: Option<i32>,
}

这里能不能设计成跟数据库的 not null 设置成一致的,只有可以为 null 的字段才是 Option。如果一定要先初始化struct再填值,不知道使用builder模式能不能解决。

不成熟的小建议,仅供参考。

type of Mysql isn't support.

Error : un support database type for:"BIT"!

ddl of sql :

removed      bit       default b'0'              null comment 'is soft deleted',
creator      bigint    default -1                null,
create_at    timestamp default CURRENT_TIMESTAMP null,
updater      bigint    default -1                null,
update_at    timestamp default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP

Inserting point type column in postgres is not working

Encoding method is currently inserting point type as text in pgbuffer which throws error, I don't know what's the correct way to encode.

db : postgres
query log:

 [2020-09-25T08:02:07Z INFO  rbatis::rbatis] [rbatis] [] Exec ==> INSERT INTO demo (coordinates,id) VALUES ( $1 , $2 )
[2020-09-25T08:02:07Z INFO  rbatis::rbatis] [rbatis] [] Args ==> [{"x":12.1,"y":2.12},2]
[2020-09-25T08:02:09Z INFO  rbatis::rbatis] [rbatis] [] RowsAffected <== 0

error message : {"Err":"column "coordinates" is of type point but expression is of type text"}

If anyone knows how to encode to pgbuffer, let me know, I'll fix it

提交一个小bug

db_adapter.rs中第252行,

return Ok(DBPoolConn {
driver_type: DriverType::Mssql,
mysql: None,
postgres: None,
sqlite: None,
mssql: Some(conn.unwrap()),
});

应该是这样的把。好像是拷贝的时候,把sqllite的驱动类型名称拷贝过来了 @zhuxiujia

openssl-sys v0.9.58错误

error: failed to run custom build command for openssl-sys v0.9.58
此错误会导致
cargo:rustc-cfg=const_fn
cargo:rerun-if-env-changed=X86_64_UNKNOWN_LINUX_GNU_OPENSSL_LIB_DIR
X86_64_UNKNOWN_LINUX_GNU_OPENSSL_LIB_DIR unset

$HOST = x86_64-unknown-linux-gnu
$TARGET = x86_64-unknown-linux-gnu
openssl-sys = 0.9.58
把rbatis依赖去除,则构建成功,具体原因未知

分页插件,统计sql 多了 ORDER BY,PostgreSQL数据库

let req = PageRequest::new(1, 1); //分页请求,页码,条数
    let wraper = RB
        .new_wrapper()
        .eq("1", 1)
        .order_by(false, &["create_date"])
        .check()
        .unwrap();
    let r: rbatis_core::Result<Page<CyCustomZtzts>> =
        RB.fetch_page_by_wrapper("", &wraper, &req).await;

生成了sql:

SELECT count(1) FROM cy_custom_ztzts WHERE 1 = $1 ORDER BY create_date DESC

含有ORDER BY 无法正常运行

can't distinguish Raw identifiers when use in fields.

eg:

#[derive(CRUDEnable, Debug, Clone, Serialize, Deserialize)]
pub struct SomeThing {
    pub id: String,
    pub r#type: String,
}

it will generate sql like SELECT id,r#type FROM SomeThing .

by the way, would i customize the table name while using the macro CRUDEnable ?

partial CRUDEnable implementation

Greetings!

First of all thanks for your great tool. It works like a charm :)

My problem is that I can't override CRUDEnable implementation if derive clause used. Example:

#[derive(CRUDEnable, Serialize, Deserialize, Clone, Debug)]
pub struct Source {
    pub id: u32,
    pub name: String,
    pub origin: String,
}

I want to use table_name = "sources" but currently there are two options:

  1. not to use #[derive(CRUDEnable)] and implement all trait methods
  2. use #[derive(CRUDEnable)] and accept library logic. So in that case I have to rename database table from sources to source.

It would be great if I can use some kind of macro for that.

can't use array as query parameters

Hi!
I can't find a way to use an array in queries. Here is an example:

#[tokio::main]
async fn main() {
    db::RB
        .link("postgres://user:[email protected]:5432/db")
        .await
        .expect("can't initialize pool");
    let guids = vec!["1", "2", "3"];  // absolutely the same result with `let guids = ("1", "2", "3")`
    let exists: Vec<String> = db::RB
        .fetch_prepare(
            "",
            r#"
        SELECT guid 
        FROM records
        WHERE guid = ANY($1)
        AND source_id = $2"#,
            &vec![json!(&guids), json!(&1)],
        )
        .await
        .unwrap();
}

Logs:

[2020-11-04T11:45:51Z INFO  rbatis::plugin::log] [rbatis] [] Query ==> 
            SELECT guid 
            FROM records
            WHERE guid = ANY($1)
            AND source_id = $2
[2020-11-04T11:45:51Z INFO  rbatis::plugin::log] [rbatis] [] Args  ==> [["1","2","3"],1]
[2020-11-04T11:45:51Z INFO  sqlx::query] /* SQLx ping */; rows: 0, elapsed: 614.743µs
[2020-11-04T11:45:51Z INFO  sqlx::query] SELECT guid FROM records …; rows: 0, elapsed: 1.014ms
    
    SELECT
      guid
    FROM
      records
    WHERE
      guid = ANY($1)
      AND source_id = $2
    
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: E("error returned from database: op ANY/ALL (array) requires array on right side")', src/main.rs:48:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

where 不加条件,仅使用order_by ,sql会自动加上一个 AND

配置:
let mut rbatis = Rbatis::new(); //logic plugin 设置逻辑删除插件 rbatis.logic_plugin = Some(Box::new(RbatisLogicDeletePlugin::new_opt("del",1,0)));

wrapper
let mut wrapper = RB.new_wrapper().order_by(false,&["create_time"]).check()?;
生成的错误语句:
SELECT count(1) FROM t_test WHERE del = 0 AND ORDER BY create_time DESC

现在临时的办法是:
let mut wrapper = RB.new_wrapper().eq("1","1").order_by(false,&["create_time"]).check()?;

静态定义一个Rabtis实例,执行第一个sql没问题,第二个就卡主了

lazy_static!{
pub static ref Rb: Rbatis<'static>={
let rb = Rbatis::new();
async_std::task::block_on(async{
rb.link(&CONFIG.database.url).await;
});
return rb;
};
}

Rb.fetch_by_wrapper()===>success

Rb.remove_by_wrapper() ===>卡主一直不会动

==============================
我改成
pub async fn connect()->Rbatis<'static>{
let rb = Rbatis::new();
rb.link(&CONFIG.database.url).await;
return rb;
}

connecti().await.fetch_by_wrapper()===>success
connecti().await.remove_by_wrapper()===>success
这个就正常了。请问这个是什么原因

postgresql serialization error fail to insert :{"Err":"column \"chefid\" of relation \"offer\" does not exist"}

fail to insert on postgres

DB Schema
ordinal_position | column_name | data_type | character_maximum_length | modifier | notnull | hasdefault
------------------+----------------+-----------+--------------------------+----------+---------+------------
1 | id | uuid | 16 | -1 | t | t
2 | create_date | timestamp | 8 | -1 | t | t
3 | update_date | timestamp | 8 | -1 | t | t
4 | version | int4 | 4 | -1 | t | f
5 | is_active | bool | 1 | -1 | t | t
6 | dateOfDelivery | timestamp | 8 | -1 | t | f
7 | tokenValue | int4 | 4 | -1 | t | t
8 | maxQuantity | int4 | 4 | -1 | t | t
9 | status | varchar | -1 | 54 | t | t
10 | coordinates | point | 16 | -1 | f | f
11 | chefId | uuid | 16 | -1 | f | f
12 | dishId | uuid | 16 | -1 | t | f
(12 rows)

RUST CODE

let off = Offer {
        id: Some(Uuid::new_v4()),
        create_date: Some(Utc::now().naive_local()),
        update_date: Some(Utc::now().naive_local()),
        version: Some(1),
        is_active: Some(true),
        date_of_delivery: Some(Utc::now().naive_local()),
        token_value: Some(2),
        max_quantity: Some(2),
        status: Some("OUT_OF_DELIVERY".to_string()),
        // coordinates: None,
        chefId: Some(Uuid::parse_str("ebb787b4-d90c-4b0f-9bbe-7324f3d90efe").unwrap()),
        dishId: Some(Uuid::parse_str("85357370-8aef-4262-bf68-f6d38522cf6b").unwrap()),
    };
    Json(RB.save_batch("", &vec![off]).await)

log

[2020-09-26T12:22:06Z INFO  rbatis::rbatis] [rbatis] [] Exec ==> INSERT INTO Offer (chefId,create_date,date_of_delivery,dishId,id,is_active,max_quantity,status,token_value,update_date,version) VALUES ( $1 ,cast( $2  as timestamp),cast( $3  as timestamp), $4 , $5 , $6 , $7 , $8 , $9 ,cast( $10  as timestamp), $11 )
[2020-09-26T12:22:06Z INFO  rbatis::rbatis] [rbatis] [] Args ==> ["ebb787b4-d90c-4b0f-9bbe-7324f3d90efe","2020-09-26T12:22:06.537112100","2020-09-26T12:22:06.537112100","85357370-8aef-4262-bf68-f6d38522cf6b","3d30b1fa-4d41-4b54-88e4-9e9065904b9f",true,2,"OUT_OF_DELIVERY",2,"2020-09-26T12:22:06.537112100",1]
[2020-09-26T12:22:06Z INFO  rbatis::rbatis] [rbatis] [] RowsAffected <== 0

分页插件的count统计有问题

在统计分页(count)的时候,加入limit了,当页数大于0的时候,是统计不了总数。
rbatis::rbatis-242]: [rbatis] [] Query ==> SELECT count(1) FROM t_test WHERE del = 0 LIMIT 2,10

具体在:在RbatisPagePlugin类的create_page_sql的方法里面创建count_sql有问题。
希望作者修复一下。谢谢了。

有个相关的问题。

既然rbatis底层使用了sqlx。那么我想问一个问题。sqlx的Pool在使用之后是不是需要close?
按理说随着生命周期的结束,连接应该是被释放了,但是既然Pool有一个close方法,似乎问题有没有那么简单。还是说close方法是关闭整个连接池呢?我英文不是太好,在sqlx中提出的Issues没人理,似乎没人看懂。。哈哈。希望大佬给与解答。

逻辑删除插件,new函数里的deleted和un_deleted可能搞反了

代码如下:

  pub fn new(column: &str) -> Self {
        Self {
            column: column.to_string(),
            deleted: 0,
            un_deleted: 1,
        }
    }

结合abs_admin工程里的使用示例:

let del = RbatisLogicDeletePlugin::new("del");

可见通常是用诸如del作为逻辑删除的字段名,那么deleted为1,un_deleted为0,和字面意思是相符的,但代码实际上是反过来的了

可以给CRUDEnable增加 #[serde(flatten)]这个支持吗?

这样就相当于增加了嵌入结构体的支持了
#[derive(Serialize, Deserialize)]
pub struct One{
pub name: String,
pub code: String,
}
#[derive(Serialize, Deserialize, Clone, Debug, Default, CRUDEnable)]
pub struct Two {
#[serde(flatten)]
pub one: One,
pub id: String,
}

DOMAIN 层 简化

我看到Domain层的逻辑

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct SysUser {
    pub id: Option<String>,
    pub account: Option<String>,
    pub password: Option<String>,
    pub name: Option<String>,
    pub del: Option<i32>,
    pub create_time: Option<NaiveDateTime>,
}


impl CRUDEnable for SysUser {
    type IdType = String;
}

可以用宏来简洁一下

Sqlite 报错 ColumnNotFound("0")

panicked at 'called `Result::unwrap()` on an `Err` value: ColumnNotFound("0")', /home/mrtan/.cargo/registry/src/github.com-1ecc6299db9ec823/rbatis-core-1.5.2/src/sqlite/cursor.rs:78:83

下面是debug的跟踪数据, 应该是row的key不能直接是"0,1,2.."

image

image

image

image

image

Support for similar functionality to `sqlx::types::Json`.

About working with JSON, JSONB postgres fields.

Does this library support defining crud enabled structs with json fields that do not have type serde_json::Value, but has rust structure with implemented serde serialization, deserialization.

For example sqlx has syntax support for the following syntax when fetching data from database:

#[derive(Clone, Serialize, Deserialize, Debug)]
struct Example {
   ...
   json_field: sqlx::types::Json<MyRustType>,
   ...
}

Then in sqlx::query_as! sql you would write something like this for JSONB field to pass compile time validation.

SELECT
     ...
     json_field as "json_field: sqlx::types::Json<MyRustType>",
     ...

This allows not to use identical intermediate rust structures with serde_json::Value type fields.

how can i set null value

就是在entity的基础上再额外设置某个字段是null值该怎么做呢(现在的逻辑应该是None字段不做更改的吧)

or()和like()有问题

  1. 使用like 的时候, 生成的语句在?的左右会有空格,导致找不到数据。
    SELECT count(1) FROM t_test WHERE del = 0 AND TITLE LIKE '% ? %' ORDER BY create_time DESC
  2. or 是怎么用的? 会无端端多了一个or,其他的用了and.
    RB.new_wrapper() .eq("1","1") .or() .like("TITLE",&str) .or() .like("ORIGINAL_NAME",&str)
    生成的语句:
    SELECT count(1) FROM t_test WHERE del = 0 AND 1 = ? OR OR TITLE LIKE '% ? %' OR OR ORIGINAL_NAME LIKE '% ? %'

`serverTimezone=Asia/Shanghai` in mysql url not work

I connect mysql with url mysql://root:123456@localhost:3306/test?serverTimezone=Asia/Shanghai&characterEncoding=utf8, then execute sql select NOW(), however the result is a time with UTC.

Does rbatis support the url option serverTimezone=Asia/Shanghai ? Maybe I miss something about other way to set connection session timezone, how can I find the document about it?

Thank you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.