tideorm 0.9.7

A developer-friendly ORM for Rust with clean, expressive syntax
Documentation
use super::{
    build_count_select, build_exists_any_statement, count_to_u64, scoped_find,
    supports_batch_insert_returning,
};
use crate::config::DatabaseType;
use crate::internal::{Backend, ColumnTrait, Condition, InternalModel, OrmBackend, QueryTrait};

#[tideorm::model(table = "internal_count_users")]
struct InternalCountUser {
    #[tideorm(primary_key, auto_increment)]
    id: i64,
    name: String,
}

#[tideorm::model(table = "internal_soft_delete_users", soft_delete)]
struct InternalSoftDeleteUser {
    #[tideorm(primary_key, auto_increment)]
    id: i64,
    name: String,
    deleted_at: Option<chrono::DateTime<chrono::Utc>>,
}

#[test]
fn batch_insert_returning_supports_postgres_backend_without_config() {
    assert!(supports_batch_insert_returning(None, Backend::Postgres));
}

#[test]
fn batch_insert_returning_rejects_mysql_backend_without_mariadb_config() {
    assert!(!supports_batch_insert_returning(None, Backend::MySql));
    assert!(!supports_batch_insert_returning(
        Some(DatabaseType::MySQL),
        Backend::MySql,
    ));
}

#[test]
fn batch_insert_returning_accepts_mariadb_config_on_mysql_backend() {
    assert!(supports_batch_insert_returning(
        Some(DatabaseType::MariaDB),
        Backend::MySql,
    ));
}

#[test]
fn batch_insert_returning_rejects_sqlite_even_though_it_supports_returning() {
    assert!(!supports_batch_insert_returning(
        Some(DatabaseType::SQLite),
        Backend::Sqlite,
    ));
}

#[test]
fn batch_insert_returning_rejects_config_backend_mismatches() {
    assert!(!supports_batch_insert_returning(
        Some(DatabaseType::Postgres),
        Backend::MySql,
    ));
    assert!(!supports_batch_insert_returning(
        Some(DatabaseType::MariaDB),
        Backend::Postgres,
    ));
}

#[test]
fn count_select_omits_where_without_condition() {
    let statement = build_count_select::<InternalCountUser>(None).build(OrmBackend::Postgres);

    assert_eq!(
        statement.sql,
        "SELECT COUNT(*) AS \"count\" FROM \"internal_count_users\""
    );
}

#[test]
fn exists_any_statement_uses_select_exists_probe() {
    let statement = build_exists_any_statement::<InternalCountUser>(Backend::Postgres);

    assert_eq!(
        statement.sql,
        "SELECT EXISTS(SELECT 1 FROM \"internal_count_users\")"
    );
    assert!(statement.values.is_none());
}

#[test]
fn scoped_find_has_no_soft_delete_filter_for_regular_models() {
    let statement = scoped_find::<InternalCountUser>().build(OrmBackend::Postgres);

    assert_eq!(
        statement.sql,
        "SELECT \"internal_count_users\".\"id\", \"internal_count_users\".\"name\" FROM \"internal_count_users\""
    );
}

#[test]
fn scoped_find_applies_soft_delete_filter_for_soft_delete_models() {
    let statement = scoped_find::<InternalSoftDeleteUser>().build(OrmBackend::Postgres);

    assert!(
        statement
            .sql
            .contains("FROM \"internal_soft_delete_users\"")
    );
    assert!(
        statement
            .sql
            .contains("WHERE \"internal_soft_delete_users\".\"deleted_at\" IS NULL")
    );
}

#[test]
fn exists_any_statement_preserves_soft_delete_scope() {
    let statement = build_exists_any_statement::<InternalSoftDeleteUser>(Backend::Postgres);

    assert!(
        statement
            .sql
            .contains("SELECT EXISTS(SELECT 1 FROM \"internal_soft_delete_users\"")
    );
    assert!(
        statement
            .sql
            .contains("WHERE \"internal_soft_delete_users\".\"deleted_at\" IS NULL")
    );
    assert!(statement.values.is_none());
}

#[test]
fn count_select_applies_optional_condition() {
    let condition = Condition::all().add(
        InternalCountUser::column_from_str("name")
            .expect("generated model should expose the name column")
            .eq("alice"),
    );
    let statement =
        build_count_select::<InternalCountUser>(Some(condition)).build(OrmBackend::Postgres);

    assert!(
        statement
            .sql
            .contains("WHERE \"internal_count_users\".\"name\" = $1")
    );
    assert!(statement.values.is_some());
}

#[test]
fn count_to_u64_rejects_negative_counts() {
    let err = count_to_u64(-1, "count(*)").unwrap_err();

    assert!(err.to_string().contains("negative count"));
    assert!(err.to_string().contains("count(*)"));
}