vibe_ready/store/db/enums/
db_error.rs1#[cfg(any(feature = "log-diesel", feature = "store-diesel-sqlite"))]
2use diesel::result::Error as DieselError;
3#[cfg(any(feature = "log-diesel", feature = "store-diesel-sqlite"))]
4use diesel::ConnectionError;
5use serde::Serialize;
6use std::panic::Location;
7use std::sync::PoisonError;
8use tokio::task::JoinError;
9
10#[repr(i32)]
11#[derive(Debug, Clone, PartialEq, Serialize)]
12pub enum DbError {
14 OpenFailed,
16 DatabaseIOError,
18 NotOpen,
20 TargetNotFound,
22
23 DatabaseThreadError,
25
26 DatabaseUnlockError,
28
29 JoinError,
31
32 NotSupportedYet,
34 InvalidArgumentPageToken,
36 GeneralBusinessError,
38}
39
40#[derive(Debug)]
41pub struct VibeDbErrorInfo {
43 location: String,
44 desc: String,
45 code: DbError,
46 sql: Option<String>,
47}
48
49impl VibeDbErrorInfo {
50 #[track_caller]
51 #[cfg(any(feature = "log-diesel", feature = "store-diesel-sqlite"))]
52 pub fn from_connection(value: ConnectionError) -> Self {
58 let location = Self::gen_location(Location::caller());
59 VibeDbErrorInfo::new(location, value.to_string(), DbError::OpenFailed, None)
60 }
61
62 #[track_caller]
63 #[cfg(any(feature = "log-diesel", feature = "store-diesel-sqlite"))]
64 pub fn from_diesel(value: DieselError, sql: Option<&str>) -> Self {
71 let location = Self::gen_location(Location::caller());
72 let code = match value {
73 DieselError::NotFound => DbError::TargetNotFound,
74 DieselError::DatabaseError(_, _) => DbError::DatabaseIOError,
75 _ => DbError::DatabaseIOError,
76 };
77 VibeDbErrorInfo::new(
78 location,
79 value.to_string(),
80 code,
81 sql.map(std::string::ToString::to_string),
82 )
83 }
84
85 #[track_caller]
91 pub fn from_lock<T>(error: PoisonError<T>) -> Self {
92 let location = Self::gen_location(Location::caller());
93 let ext = VibeDbErrorInfo::new(
94 location.clone(),
95 error.to_string(),
96 DbError::DatabaseUnlockError,
97 None,
98 );
99 ext
100 }
101
102 #[track_caller]
108 pub fn from_thread(desc: String) -> Self {
109 let location = Self::gen_location(Location::caller());
110 let ext = VibeDbErrorInfo::new(
111 location.clone(),
112 desc.clone(),
113 DbError::DatabaseThreadError,
114 None,
115 );
116 ext
117 }
118
119 #[track_caller]
125 pub fn from_join_error(db_error: JoinError) -> Self {
126 let location = Self::gen_location(Location::caller());
127 let ext = VibeDbErrorInfo::new(
128 location.clone(),
129 db_error.to_string(),
130 DbError::JoinError,
131 None,
132 );
133 ext
134 }
135
136 #[track_caller]
142 pub fn from_io(desc: String) -> Self {
143 let location = Self::gen_location(Location::caller());
144 let ext = VibeDbErrorInfo::new(
145 location.clone(),
146 desc.to_string(),
147 DbError::OpenFailed,
148 None,
149 );
150 ext
151 }
152
153 #[track_caller]
159 pub fn from_not_found() -> Self {
160 let location = Self::gen_location(Location::caller());
161 let ext = VibeDbErrorInfo::new(
162 location.clone(),
163 "Target Not Found".to_string(),
164 DbError::TargetNotFound,
165 None,
166 );
167 ext
168 }
169
170 #[track_caller]
176 pub fn from_not_supported(desc: String) -> Self {
177 let location = Self::gen_location(Location::caller());
178 VibeDbErrorInfo::new(location, desc, DbError::NotSupportedYet, None)
179 }
180
181 fn gen_location(location: &'static Location<'static>) -> String {
182 let location_str = format!(
183 "{}:{}:{}",
184 location.file(),
185 location.line(),
186 location.column()
187 );
188 location_str
189 }
190}
191
192impl VibeDbErrorInfo {
193 pub fn new(location: String, desc: String, code: DbError, sql: Option<String>) -> Self {
208 Self {
209 location,
210 desc,
211 code,
212 sql,
213 }
214 }
215
216 pub fn location(&self) -> String {
222 self.location.clone()
223 }
224
225 pub fn desc(&self) -> String {
231 self.desc.clone()
232 }
233
234 pub fn code(&self) -> DbError {
240 self.code.clone()
241 }
242
243 pub fn sql(&self) -> String {
249 match &self.sql {
250 None => String::from(""),
251 Some(val) => val.clone(),
252 }
253 }
254}
255
256impl std::fmt::Display for VibeDbErrorInfo {
257 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
258 write!(
259 f,
260 "DbError[{:?}] at {}: {}{}",
261 self.code,
262 self.location,
263 self.desc,
264 if let Some(sql) = &self.sql {
265 format!(" (SQL: {})", sql)
266 } else {
267 String::new()
268 }
269 )
270 }
271}
272
273#[cfg(test)]
274mod strict_tests {
275 use super::*;
276 include!(concat!(
277 env!("CARGO_MANIFEST_DIR"),
278 "/test/unit/store/db_error_tests.rs"
279 ));
280}