reifydb_routine/procedure/
error.rs1use reifydb_type::{
5 error::{Diagnostic, Error, IntoDiagnostic, TypeError},
6 fragment::Fragment,
7 value::r#type::Type,
8};
9
10#[derive(Debug, thiserror::Error)]
11pub enum ProcedureError {
12 #[error("procedure {} expects {expected} arguments, got {actual}", procedure.text())]
13 ArityMismatch {
14 procedure: Fragment,
15 expected: usize,
16 actual: usize,
17 },
18
19 #[error("procedure {} argument {} has invalid type: got {actual:?}", procedure.text(), argument_index + 1)]
20 InvalidArgumentType {
21 procedure: Fragment,
22 argument_index: usize,
23 expected: Vec<Type>,
24 actual: Type,
25 },
26
27 #[error("procedure {} execution failed: {reason}", procedure.text())]
28 ExecutionFailed {
29 procedure: Fragment,
30 reason: String,
31 },
32
33 #[error(transparent)]
34 Wrapped(Box<Error>),
35}
36
37impl From<Error> for ProcedureError {
38 fn from(err: Error) -> Self {
39 ProcedureError::Wrapped(Box::new(err))
40 }
41}
42
43impl From<TypeError> for ProcedureError {
44 fn from(err: TypeError) -> Self {
45 ProcedureError::Wrapped(Box::new(Error::from(err)))
46 }
47}
48
49impl From<Box<TypeError>> for ProcedureError {
50 fn from(err: Box<TypeError>) -> Self {
51 ProcedureError::Wrapped(Box::new(Error::from(err)))
52 }
53}
54
55impl ProcedureError {
56 pub fn with_context(self, procedure: Fragment) -> Error {
60 match self {
61 ProcedureError::Wrapped(inner) => {
62 let name = procedure.text().to_string();
63 let mut cause = *inner.0;
64 cause.with_fragment(procedure.clone());
65 Error(Box::new(Diagnostic {
66 code: "PROCEDURE_003".to_string(),
67 statement: None,
68 message: format!("Procedure {} execution failed", name),
69 column: None,
70 fragment: procedure,
71 label: Some("execution failed".to_string()),
72 help: Some("Check procedure arguments and context".to_string()),
73 notes: vec![],
74 cause: Some(Box::new(cause)),
75 operator_chain: None,
76 }))
77 }
78 other => Error(Box::new(other.into_diagnostic())),
79 }
80 }
81}
82
83impl From<ProcedureError> for Error {
84 fn from(err: ProcedureError) -> Self {
85 Error(Box::new(err.into_diagnostic()))
86 }
87}
88
89impl IntoDiagnostic for ProcedureError {
90 fn into_diagnostic(self) -> Diagnostic {
91 match self {
92 ProcedureError::ArityMismatch {
93 procedure,
94 expected,
95 actual,
96 } => {
97 let name = procedure.text().to_string();
98 Diagnostic {
99 code: "PROCEDURE_001".to_string(),
100 statement: None,
101 message: format!(
102 "Procedure {} expects {} arguments, got {}",
103 name, expected, actual
104 ),
105 column: None,
106 fragment: procedure,
107 label: Some("wrong number of arguments".to_string()),
108 help: Some(format!(
109 "Provide exactly {} arguments to procedure {}",
110 expected, name
111 )),
112 notes: vec![],
113 cause: None,
114 operator_chain: None,
115 }
116 }
117 ProcedureError::InvalidArgumentType {
118 procedure,
119 argument_index,
120 expected,
121 actual,
122 } => {
123 let name = procedure.text().to_string();
124 let expected_types =
125 expected.iter().map(|t| format!("{:?}", t)).collect::<Vec<_>>().join(", ");
126 Diagnostic {
127 code: "PROCEDURE_002".to_string(),
128 statement: None,
129 message: format!(
130 "Procedure {} argument {} has invalid type: expected one of [{}], got {:?}",
131 name,
132 argument_index + 1,
133 expected_types,
134 actual
135 ),
136 column: None,
137 fragment: procedure,
138 label: Some("invalid argument type".to_string()),
139 help: Some(format!("Provide an argument of type: {}", expected_types)),
140 notes: vec![],
141 cause: None,
142 operator_chain: None,
143 }
144 }
145 ProcedureError::ExecutionFailed {
146 procedure,
147 reason,
148 } => {
149 let name = procedure.text().to_string();
150 Diagnostic {
151 code: "PROCEDURE_003".to_string(),
152 statement: None,
153 message: format!("Procedure {} execution failed: {}", name, reason),
154 column: None,
155 fragment: procedure,
156 label: Some("execution failed".to_string()),
157 help: Some("Check procedure arguments and context".to_string()),
158 notes: vec![],
159 cause: None,
160 operator_chain: None,
161 }
162 }
163 ProcedureError::Wrapped(err) => *err.0,
164 }
165 }
166}