baichun_framework_db/
error.rs

1//! 数据库错误处理模块
2//!
3//! 本模块定义了数据库操作过程中可能遇到的各种错误类型,包括:
4//! - 连接错误
5//! - 查询错误
6//! - 事务错误
7//! - 连接池错误
8//! - 配置错误
9//! - 迁移错误
10//! - 验证错误
11//!
12//! 同时提供了错误处理的工具函数和类型别名。
13
14use std::fmt::Debug;
15use thiserror::Error;
16
17/// 数据库模块错误类型
18///
19/// 定义了数据库操作中可能出现的所有错误类型。
20/// 每种错误类型都包含详细的错误信息。
21#[derive(Debug, Error)]
22pub enum DbError {
23    /// 数据库连接错误
24    ///
25    /// 当无法建立数据库连接时发生,可能的原因包括:
26    /// - 网络问题
27    /// - 认证失败
28    /// - 数据库服务未启动
29    #[error("Database connection error: {0}")]
30    #[allow(dead_code)]
31    Connection(String),
32
33    /// 数据库查询错误
34    ///
35    /// 执行 SQL 查询时发生的错误,可能的原因包括:
36    /// - SQL 语法错误
37    /// - 表或字段不存在
38    /// - 数据类型不匹配
39    #[error("Database query error: {0}")]
40    #[allow(dead_code)]
41    Query(String),
42
43    /// 数据库事务错误
44    ///
45    /// 在事务处理过程中发生的错误,例如:
46    /// - 事务提交失败
47    /// - 事务回滚失败
48    /// - 事务超时
49    #[error("Database transaction error: {0}")]
50    #[allow(dead_code)]
51    Transaction(String),
52
53    /// 数据库连接池错误
54    ///
55    /// 连接池管理相关的错误,例如:
56    /// - 连接池已满
57    /// - 无法创建新连接
58    /// - 连接获取超时
59    #[error("Database pool error: {0}")]
60    #[allow(dead_code)]
61    Pool(String),
62
63    /// 数据库配置错误
64    ///
65    /// 配置相关的错误,例如:
66    /// - 配置参数无效
67    /// - 必要配置缺失
68    /// - 配置格式错误
69    #[error("Database configuration error: {0}")]
70    #[allow(dead_code)]
71    Config(String),
72
73    /// 数据库迁移错误
74    ///
75    /// 数据库架构迁移过程中的错误,例如:
76    /// - 迁移脚本执行失败
77    /// - 版本冲突
78    /// - 回滚失败
79    #[error("Database migration error: {0}")]
80    #[allow(dead_code)]
81    Migration(String),
82
83    /// 数据库验证错误
84    ///
85    /// 数据验证相关的错误,例如:
86    /// - 字段值不符合约束条件
87    /// - 数据完整性检查失败
88    #[error("Database validation error: {0}")]
89    #[allow(dead_code)]
90    Validation(String),
91
92    /// IO 错误
93    ///
94    /// 文件操作相关的错误
95    #[error("IO error: {0}")]
96    Io(#[from] std::io::Error),
97
98    /// 序列化错误
99    ///
100    /// JSON 数据序列化/反序列化过程中的错误
101    #[error("Serialization error: {0}")]
102    Serialization(#[from] serde_json::Error),
103}
104
105/// 通用结果类型
106///
107/// 为模块中的函数提供统一的返回类型,
108/// 使用 `Error` 作为错误类型。
109pub type Result<T> = std::result::Result<T, Error>;
110
111/// 核心错误类型
112///
113/// 定义了框架中使用的主要错误类型,
114/// 包含了所有可能出现的错误情况。
115#[derive(Error, Debug)]
116pub enum Error {
117    /// 数据库错误
118    ///
119    /// 来自 SQLx 的原始数据库错误
120    #[error("Database error: {0}")]
121    Database(#[from] sqlx::Error),
122
123    /// 连接池错误
124    ///
125    /// 连接池管理相关的错误
126    #[error("Pool error: {0}")]
127    Pool(String),
128
129    /// 事务错误
130    ///
131    /// 事务处理过程中的错误
132    #[error("Transaction error: {0}")]
133    Transaction(String),
134
135    /// 查询错误
136    ///
137    /// SQL 查询执行过程中的错误
138    #[error("Query error: {0}")]
139    Query(String),
140
141    /// 值转换错误
142    ///
143    /// 数据类型转换过程中的错误
144    #[error("Value conversion error: {0}")]
145    Conversion(String),
146
147    /// 配置错误
148    ///
149    /// 配置相关的错误
150    #[error("Configuration error: {0}")]
151    Config(String),
152
153    /// 其他错误
154    ///
155    /// 未分类的通用错误
156    #[error(transparent)]
157    Other(#[from] anyhow::Error),
158
159    /// 记录未找到错误
160    ///
161    /// 查询结果为空时的错误
162    #[error("Row not found")]
163    RowNotFound,
164}
165
166impl Error {
167    /// 检查是否为记录未找到错误
168    ///
169    /// 返回 `true` 如果错误类型为 `RowNotFound`
170    pub fn is_not_found(&self) -> bool {
171        matches!(self, Error::RowNotFound)
172    }
173
174    /// 检查是否为唯一约束违反错误
175    ///
176    /// 返回 `true` 如果错误是由唯一约束违反导致的
177    pub fn is_unique_violation(&self) -> bool {
178        matches!(self, Error::Database(e) if e.as_database_error()
179            .map(|e| matches!(e.kind(), sqlx::error::ErrorKind::UniqueViolation))
180            .unwrap_or(false))
181    }
182
183    /// 检查是否为外键约束违反错误
184    ///
185    /// 返回 `true` 如果错误是由外键约束违反导致的
186    pub fn is_foreign_key_violation(&self) -> bool {
187        matches!(self, Error::Database(e) if e.as_database_error()
188            .map(|e| matches!(e.kind(), sqlx::error::ErrorKind::ForeignKeyViolation))
189            .unwrap_or(false))
190    }
191}