Skip to content

An asynchronous ORM for Rust, support MySQL, PostgreSQL, SQLite and SQL Server.

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

Plato-solutions/cherry

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

71 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Cherry πŸ’

Cherry is an asynchronous ORM, support MySQL, PostgreSQL, SQLite and SQL Server. It's lightweight and build on top of SQLx.

WARNING: This crate is under development (mysql is partial tested at the moment).

Dependency

enable one of the database features ['mysql', 'postgres', 'sqlite', 'mssql'].

And enable 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']. More details see SQLx Feature Flags.

# Cargo.toml
[dependencies]
cherry = { version = "0.2.2", features = ["mysql", "runtime-async-std-rustls"] }
cherry-derive = "0.2.2"

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 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()
        }),
    ];

    // Setup the database connection pools.
    connection::setup_pools(config).await?;

    Ok(())
}

pub struct Foo;
pub struct Bar;

impl DataSource for Foo {}
impl DataSource for Bar {}

Model

#[derive(Cherry)]
struct User {
    id: u64,
    name: String,
}

#[derive(Cherry)]
#[cherry(table = "my_book")] // Change the default table name.
struct Book {
    id: u64,
    name: String,
}

Insert

async fn insert() -> Result<(), Box<dyn Error>> {
    // Insert one
    let user = User { id: 1, name: "Bob".to_owned(), };
    let result = Foo.insert(&user).execute().await?;
    assert_eq!(result.rows_affected(), 1);

    // Insert multiple
    let users = [
        User { id: 2, name: "Sam".to_owned() },
        User { id: 3, name: "Jack".to_owned() }
    ];
    let result = Foo.insert_bulk(&users).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 = Foo.delete::<User>()
        .and_where_eq("id", 100)
        .execute()
        .await?;

    Ok(())
}

Update

async fn update() -> Result<(), Box<dyn Error>> {
    let result = 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>> {
    // Select optional one.
    let result: Option<User> = Foo.select()
        .and_where_eq("id", 123)
        .fetch()
        .await?;

    // Select list.
    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() }
    ];

    // Without transaction
    Foo.insert_bulk(&users).execute().await?;

    // Auto transaction
    Foo.insert_bulk(&users).execute_tx().await?;

    // Manual transaction
    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?;
    // Or tx.rollback().await?;

    Ok(())
}

TODO

  • [] Custom type without sqlx imported (if possible).
  • [] Rename struct field.
  • [] improve databases support and more test.
  • [] JOIN select.

About

An asynchronous ORM for Rust, support MySQL, PostgreSQL, SQLite and SQL Server.

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Rust 100.0%