cherry-0.2.0 has been yanked.
Cherry
WARNING: This crate is under development and not fully tested (mysql is partial tested at the moment).
Cherry is a lightweight asynchronous ORM, which is build on top of
SQLx.
Dependency
Must enable one of the database features: ['mysql', 'postgres', 'sqlite', 'mssql'].
And only one database enable allowed at the same moment.
One of the features ['runtime-actix-native-tls', 'runtime-async-std-native-tls',
'runtime-tokio-native-tls', 'runtime-actix-rustls', 'runtime-async-std-rustls',
'runtime-tokio-rustls'] must be enabled. More details see
Cargo Feature Flags.
[dependencies]
cherry = { version = "0.2.0", features = ["mysql", "runtime-async-std-rustls"] }
cherry-derive = "0.2.0"
DataSource
You can set multiple DataSources as you need.
use std::any::Any;
use std::error::Error;
use cherry::connection::{self, PoolConfig};
use cherry::DataSource;
pub struct Foo;
pub struct Bar;
impl DataSource for Foo {}
impl DataSource for Bar {}
pub async fn setup() -> Result<(), Box<dyn Error>> {
let config = [
(Foo.type_id(), PoolConfig {
url: "mysql://root:12345678@localhost:3306/foo".to_owned(),
..Default::default()
}),
(Bar.type_id(), PoolConfig {
url: "mysql://root:12345678@localhost:3306/bar".to_owned(),
..Default::default()
}),
];
connection::setup_pools(config).await?;
Ok(())
}
Model
#[macro_use]
extern crate cherry_derive;
#[derive(Cherry)]
#[cherry(table = "my_user")] pub struct User {
pub id: u64,
pub name: String,
}
#[derive(Cherry)]
pub struct Book {
pub id: u64,
pub name: String,
}
Insert
use cherry::sqlx::MySqlQueryResult;
async fn insert() -> Result<(), Box<dyn Error>> {
let user = User { id: 1, name: "Bob".to_owned(), };
let result: MySqlQueryResult = Foo.insert(&user).execute().await?;
assert_eq!(result.rows_affected(), 1);
let user1 = User { id: 2, name: "Sam".to_owned() };
let user2 = User { id: 3, name: "Jack".to_owned() };
let result: MySqlQueryResult = Foo.insert_bulk(&[user1, user2]).execute().await?;
assert_eq!(result.rows_affected(), 2);
Ok(())
}
Also support other insertion such as: insert replace, insert ignore ...
Delete
async fn delete() -> Result<(), Box<dyn Error>> {
let result: MySqlQueryResult = Foo.delete::<User>()
.and_where_eq("id", 100)
.execute()
.await?;
Ok(())
}
Update
async fn update() -> Result<(), Box<dyn Error>> {
let result: MySqlQueryResult = Foo.update::<User>()
.set("name", "New Name")
.or_where_lt("id", 100)
.or_where_gt("id", 200)
.execute()
.await?;
Ok(())
}
Select
async fn select() -> Result<(), Box<dyn Error>> {
let result: Option<User> = Foo.select()
.and_where_eq("id", 123)
.fetch()
.await?;
let result: Vec<User> = Foo.select()
.and_where_between("id", 100, 200)
.and_where_ne("name", "Jack")
.fetch_all()
.await?;
Ok(())
}
Transaction
use cherry::types::Transaction;
async fn transaction() -> Result<(), Box<dyn Error>> {
let users = [
User { id: 1, name: "Henry".to_owned() },
User { id: 2, name: "Jane".to_owned() }
];
let books = [
Book { id: 1, name: "Book name 1".to_owned() },
Book { id: 2, name: "Book name 2".to_owned() }
];
Foo.insert_bulk(&users).execute().await?;
Foo.insert_bulk(&users).execute_tx().await?;
let mut tx: Transaction = Foo.begin().await?;
Foo.insert_bulk(&users).execute_with(&mut tx).await?;
Foo.insert_bulk(&books).execute_with(&mut tx).await?;
tx.commit().await?;
Ok(())
}
TODO
- [] Custom type without sqlx imported (if possible).
- [] Rename struct field.
- [] improve databases support and more test.
- [] JOIN select.