cdbc
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
Why cdbc ?
| 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 |
concurrency benchmark performance(Compare the SQLX/Tokio/Async-std)
| 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 |
* |
* |
* |
Database Support:
cdbc The driver abstraction lib.
cdbc-mysql CDBC mysql driver library
cdbc-pg CDBC postgres driver library
cdbc-sqlite CDBC sqlite driver library
cdbc-mssql CDBC microsoft mssql driver library
Supported functions
- execute: Execute the query and return the total number of rows affected.
- execute_many: Execute multiple queries and return the rows affected from each query, in a stream.
- fetch: Execute the query and return the generated results as a stream.
- fetch_many: Execute multiple queries and return the generated results as a stream,from each query, in a stream.
- fetch_all: Execute the query and return all the generated results, collected into a [
Vec].
- fetch_one: Execute the query and returns exactly one row.
- fetch_optional: Execute the query and returns at most one row.
- prepare: Prepare the SQL query to inspect the type information of its parameters and results
- prepare_with: Prepare the SQL query, with parameter type information, to inspect the type information about its parameters and results.
Supported transaction
- Pool: begin(),commit(),rollback()
- Connection: begin(),commit(),rollback()
use example:
cargo.toml
cdbc = {version = "0.1"}
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> {
std::fs::create_dir_all("target/db/");
File::create("target/db/sqlite.db");
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>,
}
let data = pool.acquire()?.execute("update biz_activity set delete_flag where id = \"1\"")?;
println!("{:?}", data.rows_affected());
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);
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);
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> {
std::fs::create_dir_all("target/db/");
File::create("target/db/sqlite.db");
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<()> {
let pool = make_sqlite().unwrap();
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(())
}