floz-orm 0.1.7

A lightweight, typesafe Rust ORM — unifying DAO and DSL from a single schema
Documentation
//! Error types for floz operations.

/// All errors that can be returned by floz operations.
#[derive(Debug, thiserror::Error)]
pub enum FlozError {
    /// Record not found (used by `get()`)
    #[error("Record not found")]
    NotFound,

    /// Unique constraint violated
    #[error("Unique constraint violated: {0}")]
    UniqueViolation(String),

    /// Foreign key constraint violated
    #[error("Foreign key constraint violated: {0}")]
    ForeignKeyViolation(String),

    /// Attempted to `save()` an entity with default/uninitialized primary key
    #[error("Cannot save — entity has no primary key (use create() for new records)")]
    UnsavedEntity,

    /// Bulk insert rows have mismatched column sets
    #[error("Bulk insert row {row} is missing column `{column}`")]
    MismatchedBulkInsertColumns {
        row: usize,
        column: String,
    },

    /// DELETE without `.where_()` or `.all()` — safety guard
    #[error("DELETE requires .where_() or .all() — refusing to delete all rows without explicit intent")]
    UnguardedDelete,

    /// UPDATE without `.where_()` — safety guard
    #[error("UPDATE requires .where_() — refusing to update all rows without explicit intent")]
    UnguardedUpdate,

    /// Underlying database error from sqlx
    #[error("Database error: {0}")]
    Database(#[from] sqlx::Error),

    /// Serialization/deserialization error
    #[error("Serialization error: {0}")]
    Serialization(String),

    /// Validation error from a lifecycle hook
    #[error("Validation error: {0}")]
    ValidationError(String),
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn error_display_not_found() {
        let e = FlozError::NotFound;
        assert_eq!(e.to_string(), "Record not found");
    }

    #[test]
    fn error_display_unsaved_entity() {
        let e = FlozError::UnsavedEntity;
        assert!(e.to_string().contains("create()"));
    }

    #[test]
    fn error_display_mismatched_bulk() {
        let e = FlozError::MismatchedBulkInsertColumns {
            row: 2,
            column: "age".to_string(),
        };
        assert!(e.to_string().contains("row 2"));
        assert!(e.to_string().contains("age"));
    }

    #[test]
    fn error_display_unguarded_delete() {
        let e = FlozError::UnguardedDelete;
        assert!(e.to_string().contains(".where_()"));
        assert!(e.to_string().contains(".all()"));
    }

    #[test]
    fn error_display_unique_violation() {
        let e = FlozError::UniqueViolation("users_email_key".into());
        assert!(e.to_string().contains("users_email_key"));
    }

    #[test]
    fn error_is_send_sync() {
        fn assert_send<T: Send>() {}
        fn assert_sync<T: Sync>() {}
        assert_send::<FlozError>();
        assert_sync::<FlozError>();
    }
}