Crates.io | cdbc |
lib.rs | cdbc |
version | 0.1.23 |
source | src |
created_at | 2021-12-20 14:09:26.41675 |
updated_at | 2022-03-06 13:28:35.653523 |
description | Rust Coroutine Database Driver Connectivity |
homepage | |
repository | https://github.com/co-rs/cdbc |
max_upload_size | |
id | 500699 |
size | 239,217 |
Coroutine Database driver Connectivity.based on mco
High concurrency,based on coroutine
No Future<'q,Output=*>
,No async fn
, No .await
, no Poll* func,No Pin
Optimize the trait system so that it has intelligent hints of the base method
NativeTls and TCP connections are supported
Low coupling,The database driver and the abstraction layer are designed separately
Lightweight, no over-design, only have macro with intelligent tips
Inspired by golang, mco, sqlx
crates | Concurrency | feature level | All Smart tips | Libc |
have proc macro | separation driver | support env/crates |
---|---|---|---|---|---|---|---|
cdbc | CSP(mco) | lower | √ | only sqlite | Don't need | √ | mco , mco/std/http , native-thread ,tokio-spawn_blocking |
rbatis | Future(tokio) | heavy-weight | √ | only sqlite | only py_sql,html_sql | x | tokio, async_std, smol |
sqlx | Future(tokio) | lower | x | only sqlite | only derive(StructOpt) | x | tokio, async_std, smol |
diesel | Native Thread | lower | x | all-libc | derive(Queryable) | x | native thread |
crates | Requests/sec | Mem | CpuLoad |
---|---|---|---|
cdbc-mco-http | 4606 | 30MB | 6% |
sqlx-axum-tokio | 4560 | 17MB | 8% |
sqlx-actix-async-std | 559.00 | 22MB | 2% |
diesel | * | * | * |
benchmark with wrk(docker run -it --net=host --rm williamyeh/wrk -t12 -c400 -d30s http://192.168.28.235:8000)
see detail benchmark
cdbc
The driver abstraction lib.cdbc-mysql
CDBC mysql driver librarycdbc-pg
CDBC postgres driver librarycdbc-sqlite
CDBC sqlite driver librarycdbc-mssql
CDBC microsoft mssql driver libraryVec
].Pool: begin(),commit(),rollback()
Connection: begin(),commit(),rollback()
use example:
cargo.toml
#must dep
cdbc = {version = "0.1"}
#optional dep
cdbc-mysql = {version = "0.1"}
cdbc-pg = {version = "0.1"}
cdbc-sqlite = {version = "0.1"}
#[cdbc::crud]
#[derive(Debug, Clone)]
pub struct BizActivity {
pub id: Option<String>,
pub name: Option<String>,
pub age: Option<i32>,
pub delete_flag: Option<i32>,
}
fn main() -> cdbc::Result<()> {
let pool = make_sqlite()?;
let arg = BizActivity {
id: Some("2".to_string()),
name: Some("2".to_string()),
age: Some(2),
delete_flag: Some(1),
};
CRUD::insert(&mut pool,arg.clone());
let v:BizActivity = CRUD::find(&mut tx,"id = 1")?;
CRUD::update( &mut pool.clone(), arg.clone(),"id = 1");
CRUD::delete(&mut pool.clone(),"id = 1");
}
fn make_sqlite() -> cdbc::Result<SqlitePool> {
//first. create sqlite dir/file
std::fs::create_dir_all("target/db/");
File::create("target/db/sqlite.db");
//next create table and query result
let pool = SqlitePool::connect("sqlite://target/db/sqlite.db")?;
let mut conn = pool.acquire()?;
conn.execute("CREATE TABLE biz_activity( id string, name string,age int, delete_flag int) ");
conn.execute("INSERT INTO biz_activity (id,name,age,delete_flag) values (\"1\",\"1\",1,0)");
Ok(pool)
}
use cdbc::{impl_scan};
use cdbc::scan::{Scan,Scans};
pub struct BizActivity {
pub id: Option<String>,
pub name: Option<String>,
pub delete_flag: Option<i32>,
}
impl_scan!(SqliteRow,BizActivity{id:None,name:None,delete_flag:None});
let v:Vec<BizActivity > = query!("select * from biz_activity limit 1").fetch_all(pool)?.scan()?;
use std::fs::File;
use cdbc::Executor;
use cdbc_sqlite::SqlitePool;
fn main() -> cdbc::Result<()> {
let pool = make_sqlite()?;
#[derive(Debug)]
pub struct BizActivity {
pub id: Option<String>,
pub name: Option<String>,
pub delete_flag: Option<i32>,
}
//execute
let data = pool.acquire()?.execute("update biz_activity set delete_flag where id = \"1\"")?;
println!("{:?}", data.rows_affected());
//fetch_all
let query = cdbc::query("select * from biz_activity where id = ?")
.bind("1");
let row = pool.acquire()?.fetch_all(query)?;
let data = cdbc::row_scans!(row,BizActivity{id:None,name:None,delete_flag:None})?;
println!("{:?}", data);
//fetch_one
let data = cdbc::row_scan!(
cdbc::query("select * from biz_activity where id = ?")
.bind("1")
.fetch_one(pool)?,
BizActivity{id:None,name:None,delete_flag:None})?;
println!("{:?}", data);
//transaction
let mut tx = pool.acquire()?.begin()?;
let data=tx.execute("update biz_activity set delete_flag where id = \"1\"")?;
println!("{:?}", data.rows_affected());
tx.commit()?;
Ok(())
}
fn make_sqlite() -> cdbc::Result<SqlitePool> {
//first. create sqlite dir/file
std::fs::create_dir_all("target/db/");
File::create("target/db/sqlite.db");
//next create table and query result
let pool = SqlitePool::connect("sqlite://target/db/sqlite.db")?;
let mut conn = pool.acquire()?;
conn.execute("CREATE TABLE biz_activity( id string, name string,age int, delete_flag int) ");
conn.execute("INSERT INTO biz_activity (id,name,age,delete_flag) values (\"1\",\"1\",1,0)");
Ok(pool)
}
main.rs
use std::collections::BTreeMap;
use cdbc::{Column, Decode, Executor, Row};
use cdbc::io::chan_stream::{ChanStream, TryStream};
use cdbc_sqlite::{Sqlite, SqliteRow};
use crate::make_sqlite;
#[test]
fn test_stream_sqlite() -> cdbc::Result<()> {
//first. create sqlite dir/file
let pool = make_sqlite().unwrap();
//next create table and query result
let mut conn = pool.acquire()?;
let mut data: ChanStream<SqliteRow> = conn.fetch("select * from biz_activity;");
data.try_for_each(|item| {
let mut m = BTreeMap::new();
for column in item.columns() {
let v = item.try_get_raw(column.name())?;
let r: Option<String> = Decode::<'_, Sqlite>::decode(v)?;
m.insert(column.name().to_string(), r);
}
println!("{:?}", m);
drop(m);
Ok(())
})?;
Ok(())
}