1use std::fmt;
4
5use prax_query::error::QueryError;
6
7pub type SqliteResult<T> = Result<T, SqliteError>;
9
10#[derive(Debug)]
12pub enum SqliteError {
13 Pool(String),
15 Sqlite(tokio_rusqlite::Error),
17 Config(String),
19 Connection(String),
21 Query(String),
23 Deserialization(String),
25 TypeConversion(String),
27 Timeout(String),
29 Internal(String),
31}
32
33impl SqliteError {
34 pub fn pool(msg: impl Into<String>) -> Self {
36 Self::Pool(msg.into())
37 }
38
39 pub fn config(msg: impl Into<String>) -> Self {
41 Self::Config(msg.into())
42 }
43
44 pub fn connection(msg: impl Into<String>) -> Self {
46 Self::Connection(msg.into())
47 }
48
49 pub fn query(msg: impl Into<String>) -> Self {
51 Self::Query(msg.into())
52 }
53
54 pub fn deserialization(msg: impl Into<String>) -> Self {
56 Self::Deserialization(msg.into())
57 }
58
59 pub fn type_conversion(msg: impl Into<String>) -> Self {
61 Self::TypeConversion(msg.into())
62 }
63
64 pub fn timeout(msg: impl Into<String>) -> Self {
66 Self::Timeout(msg.into())
67 }
68
69 pub fn internal(msg: impl Into<String>) -> Self {
71 Self::Internal(msg.into())
72 }
73}
74
75impl fmt::Display for SqliteError {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 match self {
78 Self::Pool(msg) => write!(f, "Pool error: {}", msg),
79 Self::Sqlite(e) => write!(f, "SQLite error: {}", e),
80 Self::Config(msg) => write!(f, "Configuration error: {}", msg),
81 Self::Connection(msg) => write!(f, "Connection error: {}", msg),
82 Self::Query(msg) => write!(f, "Query error: {}", msg),
83 Self::Deserialization(msg) => write!(f, "Deserialization error: {}", msg),
84 Self::TypeConversion(msg) => write!(f, "Type conversion error: {}", msg),
85 Self::Timeout(msg) => write!(f, "Timeout error: {}", msg),
86 Self::Internal(msg) => write!(f, "Internal error: {}", msg),
87 }
88 }
89}
90
91impl std::error::Error for SqliteError {
92 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
93 match self {
94 Self::Sqlite(e) => Some(e),
95 _ => None,
96 }
97 }
98}
99
100impl From<tokio_rusqlite::Error> for SqliteError {
101 fn from(err: tokio_rusqlite::Error) -> Self {
102 Self::Sqlite(err)
103 }
104}
105
106impl From<rusqlite::Error> for SqliteError {
107 fn from(err: rusqlite::Error) -> Self {
108 Self::Sqlite(tokio_rusqlite::Error::Rusqlite(err))
109 }
110}
111
112impl From<SqliteError> for QueryError {
113 fn from(err: SqliteError) -> Self {
114 match err {
115 SqliteError::Pool(msg) => QueryError::connection(msg),
116 SqliteError::Sqlite(e) => QueryError::database(e.to_string()),
117 SqliteError::Config(msg) => QueryError::internal(format!("config: {}", msg)),
118 SqliteError::Connection(msg) => QueryError::connection(msg),
119 SqliteError::Query(msg) => QueryError::database(msg),
120 SqliteError::Deserialization(msg) => QueryError::serialization(msg),
121 SqliteError::TypeConversion(msg) => QueryError::serialization(format!("type: {}", msg)),
122 SqliteError::Timeout(_) => QueryError::timeout(5000), SqliteError::Internal(msg) => QueryError::internal(msg),
124 }
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131
132 #[test]
133 fn test_error_display() {
134 let err = SqliteError::config("invalid path");
135 assert!(err.to_string().contains("Configuration error"));
136 assert!(err.to_string().contains("invalid path"));
137 }
138
139 #[test]
140 fn test_error_constructors() {
141 assert!(matches!(SqliteError::pool("test"), SqliteError::Pool(_)));
142 assert!(matches!(
143 SqliteError::config("test"),
144 SqliteError::Config(_)
145 ));
146 assert!(matches!(
147 SqliteError::connection("test"),
148 SqliteError::Connection(_)
149 ));
150 assert!(matches!(SqliteError::query("test"), SqliteError::Query(_)));
151 }
152
153 #[test]
154 fn test_error_conversion() {
155 let err = SqliteError::timeout("connection timed out");
156 let query_err: QueryError = err.into();
157 assert!(query_err.is_timeout());
158 }
159}