1use thiserror::Error;
8
9pub type Result<T> = std::result::Result<T, KitError>;
10
11#[derive(Debug, Error, Clone, PartialEq)]
13pub enum KitError {
14 #[error("validation error: {0}")]
15 Validation(String),
16 #[error("duplicate key: {0}")]
17 Duplicate(String),
18 #[error("foreign key violation: {0}")]
19 ForeignKey(String),
20 #[error("restrict violation: {0}")]
21 Restrict(String),
22 #[error("migration error: {0}")]
23 Migration(String),
24 #[error("conflict: {0}")]
25 Conflict(String),
26 #[error("trigger validation error: {0}")]
27 TriggerValidation(String),
28 #[error("storage error: {0}")]
29 Storage(String),
30 #[error("integrity error: {0}")]
31 Integrity(String),
32}
33
34impl From<std::io::Error> for KitError {
35 fn from(e: std::io::Error) -> Self {
36 KitError::Storage(e.to_string())
37 }
38}
39
40impl From<mongreldb_core::MongrelError> for KitError {
41 fn from(e: mongreldb_core::MongrelError) -> Self {
42 use mongreldb_core::MongrelError;
43 match e {
44 MongrelError::Conflict(msg) if is_trigger_error(&msg) => {
45 KitError::TriggerValidation(msg)
46 }
47 MongrelError::Conflict(msg) => KitError::Conflict(msg),
48 MongrelError::InvalidArgument(msg) if is_trigger_error(&msg) => {
49 KitError::TriggerValidation(msg)
50 }
51 MongrelError::InvalidArgument(msg) => KitError::Validation(msg),
52 MongrelError::Schema(msg) => KitError::Validation(msg),
53 MongrelError::ColumnNotFound(msg) => KitError::Integrity(msg),
54 MongrelError::NotFound(msg) => KitError::Integrity(msg),
55 MongrelError::Io(e) => KitError::Storage(e.to_string()),
56 MongrelError::Serialization(e) => KitError::Storage(e.to_string()),
57 MongrelError::ChecksumMismatch { .. }
58 | MongrelError::MagicMismatch { .. }
59 | MongrelError::CorruptWal { .. }
60 | MongrelError::TornWrite { .. } => KitError::Integrity(e.to_string()),
61 MongrelError::EncryptionDisabled
62 | MongrelError::Encryption(_)
63 | MongrelError::Decryption(_) => KitError::Integrity(e.to_string()),
64 MongrelError::Full(msg) => KitError::Storage(msg),
65 MongrelError::Other(msg) => KitError::Storage(msg),
66 _ => KitError::Storage(e.to_string()),
67 }
68 }
69}
70
71fn is_trigger_error(message: &str) -> bool {
72 message.contains("trigger ")
73 || message.contains("Trigger ")
74 || message.contains("external trigger bridge")
75}
76
77impl From<mongreldb_kit_core::schema::SchemaError> for KitError {
78 fn from(e: mongreldb_kit_core::schema::SchemaError) -> Self {
79 KitError::Validation(e.to_string())
80 }
81}
82
83impl From<mongreldb_kit_core::validation::ValidationError> for KitError {
84 fn from(e: mongreldb_kit_core::validation::ValidationError) -> Self {
85 KitError::Validation(e.to_string())
86 }
87}
88
89impl From<mongreldb_kit_core::planner::PlannerError> for KitError {
90 fn from(e: mongreldb_kit_core::planner::PlannerError) -> Self {
91 match e {
92 mongreldb_kit_core::planner::PlannerError::TableNotFound(msg) => {
93 KitError::Integrity(msg)
94 }
95 mongreldb_kit_core::planner::PlannerError::CircularDelete(msg) => {
96 KitError::Restrict(msg)
97 }
98 }
99 }
100}
101
102impl From<serde_json::Error> for KitError {
103 fn from(e: serde_json::Error) -> Self {
104 KitError::Storage(e.to_string())
105 }
106}
107
108impl From<mongreldb_query::MongrelQueryError> for KitError {
109 fn from(e: mongreldb_query::MongrelQueryError) -> Self {
110 use mongreldb_query::MongrelQueryError;
111 match e {
112 MongrelQueryError::Core(core) => KitError::from(core),
116 MongrelQueryError::Schema(msg) => KitError::Validation(msg),
117 MongrelQueryError::Arrow(msg) | MongrelQueryError::DataFusion(msg) => {
118 KitError::Storage(msg)
119 }
120 _ => KitError::Storage(e.to_string()),
121 }
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use super::KitError;
128
129 #[test]
130 fn maps_trigger_core_errors_to_trigger_validation() {
131 let conflict = KitError::from(mongreldb_core::MongrelError::Conflict(
132 "trigger raised".into(),
133 ));
134 assert_eq!(
135 conflict,
136 KitError::TriggerValidation("trigger raised".into())
137 );
138
139 let invalid = KitError::from(mongreldb_core::MongrelError::InvalidArgument(
140 "external trigger bridge rejected".into(),
141 ));
142 assert_eq!(
143 invalid,
144 KitError::TriggerValidation("external trigger bridge rejected".into())
145 );
146 }
147}