luna-orm 0.3.6

ORM based on sqlx
Documentation
use luna_orm::prelude::*;
use luna_orm::LunaOrmResult;
use sqlx::sqlx_macros;
mod common;
use common::mutex::get_test_mutex;

#[derive(Selection, Default, Debug, Clone)]
pub struct HelloSelection {
    id: bool,
    content: bool,
}

#[derive(Primary, Default, Debug, Clone)]
#[TableName = "article"]
pub struct HelloPrimary {
    id: i32,
}

#[derive(SelectedEntity, Debug, Clone, PartialEq, Eq)]
pub struct HelloSelectedEntity {
    id: Option<i32>,
    content: Option<String>,
}

#[derive(Entity, Clone, Debug)]
#[TableName = "article"]
pub struct HelloEntity {
    #[PrimaryKey]
    id: i32,
    content: String,
}

#[derive(Mutation, Clone, Debug)]
pub struct HelloMutation {
    content: Option<String>,
}

#[derive(Location, Clone, Debug)]
#[TableName = "article"]
pub struct HelloLocation {
    id: Option<LocationExpr<i32>>,
    content: Option<LocationExpr<String>>,
}

async fn build_db() -> DB<SqliteDatabase> {
    let config = SqliteLocalConfig {
        work_dir: "./workspace".to_string(),
        db_file: "test.db".to_string(),
    };
    let db = SqliteDatabase::build(config).await.unwrap();
    let mut trx = db.transaction().await.unwrap();
    trx.query("DROP TABLE IF EXISTS `article`").await.unwrap();
    trx.query("CREATE TABLE IF NOT EXISTS `article`(`id` INT PRIMARY KEY, `content` VARCHAR(64))")
        .await
        .unwrap();
    trx.query("DELETE FROM `article`").await.unwrap();
    trx.commit().await.unwrap();
    return DB(db);
}

async fn clear_db(db: &mut DB<SqliteDatabase>) {
    db.execute_plain("DELETE FROM `article`").await.unwrap();
}

#[sqlx_macros::test]
pub async fn test_transaction() -> LunaOrmResult<()> {
    let test_mutex = get_test_mutex();
    let test_lock = test_mutex.lock();
    let mut db = build_db().await;

    inner_test_transaction(&db).await?;
    clear_db(&mut db).await;
    test_transaction_commit(&mut db).await?;
    clear_db(&mut db).await;
    test_transaction_rollback(&db).await?;
    clear_db(&mut db).await;
    test_transaction_rollback2(&mut db).await?;
    return Ok(());
}

async fn inner_test_transaction(db: &DB<SqliteDatabase>) -> LunaOrmResult<()> {
    let mut trx = db.transaction().await?;

    let entity = HelloEntity {
        id: 23,
        content: "test".to_string(),
    };
    let result = trx.insert(&entity).await?;
    assert_eq!(result, true);

    let primary = HelloPrimary { id: 23 };
    let selection = HelloSelection {
        id: false,
        content: true,
    };

    //let mut trx = db.transaction().await?;

    let result: Option<HelloSelectedEntity> = trx.remove(&primary, &selection).await?;
    let selected_entity = HelloSelectedEntity {
        id: None,
        content: Some("test".to_string()),
    };
    assert_eq!(result, Some(selected_entity));

    let primary = HelloPrimary { id: 23 };
    let selection = HelloSelection {
        id: false,
        content: true,
    };
    let result: Option<HelloSelectedEntity> = trx.select(&primary, &selection).await?;
    assert_eq!(result, None);

    trx.commit().await?;

    Ok(())
}
async fn test_transaction_rollback(db: &DB<SqliteDatabase>) -> LunaOrmResult<()> {
    let mut trx = db.transaction().await?;

    let entity = HelloEntity {
        id: 23,
        content: "test".to_string(),
    };
    let result = trx.insert(&entity).await?;
    assert_eq!(result, true);

    let primary = HelloPrimary { id: 23 };
    let selection = HelloSelection {
        id: false,
        content: true,
    };
    trx.rollback().await?;

    let mut trx = db.transaction().await?;
    let result: Option<HelloSelectedEntity> = trx.select(&primary, &selection).await?;
    let _selected_entity = HelloSelectedEntity {
        id: None,
        content: Some("test".to_string()),
    };
    assert_eq!(result, None);

    return Ok(());
}

async fn expect_rollback_transaction<'a, G: SqlGenerator + Sync + std::fmt::Debug>(
    mut trx: Transaction<'a, G>,
) -> LunaOrmResult<()> {
    let entity = HelloEntity {
        id: 23,
        content: "test".to_string(),
    };
    let result = trx.insert(&entity).await?;
    assert_eq!(result, true);
    return Ok(());
}

async fn expect_commit_transaction<'a, G: SqlGenerator + Sync + std::fmt::Debug>(
    mut trx: Transaction<'a, G>,
) -> LunaOrmResult<()> {
    let entity = HelloEntity {
        id: 23,
        content: "test".to_string(),
    };
    let result = trx.insert(&entity).await?;
    assert_eq!(result, true);
    trx.commit().await?;
    return Ok(());
}

pub async fn test_transaction_rollback2(db: &mut DB<SqliteDatabase>) -> LunaOrmResult<()> {
    let trx = db.transaction().await?;
    let _ = expect_rollback_transaction(trx).await;

    let primary = HelloPrimary { id: 23 };
    let selection = HelloSelection {
        id: false,
        content: true,
    };
    let result: Option<HelloSelectedEntity> = db.select(&primary, &selection).await?;
    assert_eq!(result, None);

    return Ok(());
}

pub async fn test_transaction_commit(db: &mut DB<SqliteDatabase>) -> LunaOrmResult<()> {
    let trx = db.transaction().await?;
    let _ = expect_commit_transaction(trx).await;

    let primary = HelloPrimary { id: 23 };
    let selection = HelloSelection {
        id: false,
        content: true,
    };
    let result: Option<HelloSelectedEntity> = db.select(&primary, &selection).await?;

    let selected_entity = HelloSelectedEntity {
        id: None,
        content: Some("test".to_string()),
    };
    assert_eq!(result, Some(selected_entity));

    return Ok(());
}