unistore-sqlite 0.1.0

SQLite embedded database capability for UniStore
Documentation
//! SQLite 错误类型
//!
//! 职责:定义 SQLite 操作的所有错误类型

use std::fmt;

/// SQLite 操作错误
#[derive(Debug)]
pub enum SqliteError {
    /// 数据库打开失败
    OpenFailed(String),

    /// 数据库已关闭
    DatabaseClosed,

    /// 迁移失败
    MigrationFailed(String),

    /// 查询执行失败
    QueryFailed(String),

    /// 事务失败
    TransactionFailed(String),

    /// 类型转换失败
    TypeConversion(String),

    /// 参数错误
    InvalidParameter(String),

    /// 表不存在
    TableNotFound(String),

    /// 约束违反(唯一、外键等)
    ConstraintViolation(String),

    /// IO 错误
    IoError(String),

    /// 序列化/反序列化错误
    SerdeError(String),

    /// 内部错误
    Internal(String),
}

impl fmt::Display for SqliteError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::OpenFailed(msg) => write!(f, "数据库打开失败: {}", msg),
            Self::DatabaseClosed => write!(f, "数据库已关闭"),
            Self::MigrationFailed(msg) => write!(f, "迁移失败: {}", msg),
            Self::QueryFailed(msg) => write!(f, "查询失败: {}", msg),
            Self::TransactionFailed(msg) => write!(f, "事务失败: {}", msg),
            Self::TypeConversion(msg) => write!(f, "类型转换失败: {}", msg),
            Self::InvalidParameter(msg) => write!(f, "参数错误: {}", msg),
            Self::TableNotFound(table) => write!(f, "表不存在: {}", table),
            Self::ConstraintViolation(msg) => write!(f, "约束违反: {}", msg),
            Self::IoError(msg) => write!(f, "IO 错误: {}", msg),
            Self::SerdeError(msg) => write!(f, "序列化错误: {}", msg),
            Self::Internal(msg) => write!(f, "内部错误: {}", msg),
        }
    }
}

impl std::error::Error for SqliteError {}

impl From<std::io::Error> for SqliteError {
    fn from(err: std::io::Error) -> Self {
        Self::IoError(err.to_string())
    }
}

impl From<serde_json::Error> for SqliteError {
    fn from(err: serde_json::Error) -> Self {
        Self::SerdeError(err.to_string())
    }
}

impl From<rusqlite::Error> for SqliteError {
    fn from(err: rusqlite::Error) -> Self {
        use rusqlite::Error;
        match &err {
            Error::SqliteFailure(e, msg) => {
                let detail = msg.as_deref().unwrap_or("unknown");
                // 检查约束违反
                if e.extended_code == 2067 || e.extended_code == 1555 {
                    // UNIQUE constraint
                    Self::ConstraintViolation(detail.to_string())
                } else if e.extended_code == 787 {
                    // FOREIGN KEY constraint
                    Self::ConstraintViolation(format!("外键约束: {}", detail))
                } else {
                    Self::QueryFailed(format!("{:?}: {}", e.code, detail))
                }
            }
            Error::QueryReturnedNoRows => Self::QueryFailed("查询无结果".to_string()),
            Error::InvalidColumnType(idx, name, _) => {
                Self::TypeConversion(format!("{}({}) 类型不匹配", name, idx))
            }
            _ => Self::QueryFailed(err.to_string()),
        }
    }
}

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

    #[test]
    fn test_error_display() {
        let err = SqliteError::OpenFailed("permission denied".into());
        assert!(err.to_string().contains("数据库打开失败"));

        let err = SqliteError::TableNotFound("users".into());
        assert!(err.to_string().contains("users"));
    }

    #[test]
    fn test_io_error_conversion() {
        let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
        let sqlite_err: SqliteError = io_err.into();
        assert!(matches!(sqlite_err, SqliteError::IoError(_)));
    }
}