Skip to main content

reifydb_function/
error.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4use std::fmt::{Display, Formatter};
5
6use reifydb_type::{fragment::Fragment, value::r#type::Type};
7
8/// Errors that can occur when executing a scalar function
9#[derive(Debug)]
10pub enum ScalarFunctionError {
11	/// Function called with wrong number of arguments
12	ArityMismatch {
13		function: Fragment,
14		expected: usize,
15		actual: usize,
16	},
17	/// Argument has invalid type
18	InvalidArgumentType {
19		function: Fragment,
20		argument_index: usize,
21		expected: Vec<Type>,
22		actual: Type,
23	},
24	/// Function execution failed
25	ExecutionFailed {
26		function: Fragment,
27		reason: String,
28	},
29	/// Wrapped error from underlying operation
30	Wrapped(Box<reifydb_type::error::Error>),
31}
32
33impl Display for ScalarFunctionError {
34	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
35		match self {
36			ScalarFunctionError::ArityMismatch {
37				function,
38				expected,
39				actual,
40			} => write!(f, "Function {} expects {} arguments, got {}", function.text(), expected, actual),
41			ScalarFunctionError::InvalidArgumentType {
42				function,
43				argument_index,
44				expected,
45				actual,
46			} => {
47				let expected_types =
48					expected.iter().map(|t| format!("{:?}", t)).collect::<Vec<_>>().join(", ");
49				write!(
50					f,
51					"Function {} argument {} has invalid type: expected one of [{}], got {:?}",
52					function.text(),
53					argument_index + 1,
54					expected_types,
55					actual
56				)
57			}
58			ScalarFunctionError::ExecutionFailed {
59				function,
60				reason,
61			} => {
62				write!(f, "Function {} execution failed: {}", function.text(), reason)
63			}
64			ScalarFunctionError::Wrapped(err) => {
65				write!(f, "{}", err)
66			}
67		}
68	}
69}
70
71impl From<reifydb_type::error::Error> for ScalarFunctionError {
72	fn from(err: reifydb_type::error::Error) -> Self {
73		ScalarFunctionError::Wrapped(Box::new(err))
74	}
75}
76
77impl std::error::Error for ScalarFunctionError {}
78
79impl From<ScalarFunctionError> for reifydb_type::error::Error {
80	fn from(err: ScalarFunctionError) -> Self {
81		use reifydb_type::error::diagnostic::function::{
82			arity_mismatch, execution_failed, invalid_argument_type,
83		};
84
85		match err {
86			ScalarFunctionError::ArityMismatch {
87				function,
88				expected,
89				actual,
90			} => reifydb_type::error!(arity_mismatch(function, expected, actual)),
91			ScalarFunctionError::InvalidArgumentType {
92				function,
93				argument_index,
94				expected,
95				actual,
96			} => reifydb_type::error!(invalid_argument_type(function, argument_index, expected, actual)),
97			ScalarFunctionError::ExecutionFailed {
98				function,
99				reason,
100			} => reifydb_type::error!(execution_failed(function, reason)),
101			ScalarFunctionError::Wrapped(err) => *err,
102		}
103	}
104}
105
106/// Errors that can occur when executing an aggregate function
107#[derive(Debug)]
108pub enum AggregateFunctionError {
109	/// Function called with wrong number of arguments
110	ArityMismatch {
111		function: Fragment,
112		expected: usize,
113		actual: usize,
114	},
115	/// Argument has invalid type
116	InvalidArgumentType {
117		function: Fragment,
118		argument_index: usize,
119		expected: Vec<Type>,
120		actual: Type,
121	},
122	/// Function execution failed
123	ExecutionFailed {
124		function: Fragment,
125		reason: String,
126	},
127	/// Wrapped error from underlying operation
128	Wrapped(Box<reifydb_type::error::Error>),
129}
130
131impl Display for AggregateFunctionError {
132	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
133		match self {
134			AggregateFunctionError::ArityMismatch {
135				function,
136				expected,
137				actual,
138			} => write!(f, "Function {} expects {} arguments, got {}", function.text(), expected, actual),
139			AggregateFunctionError::InvalidArgumentType {
140				function,
141				argument_index,
142				expected,
143				actual,
144			} => {
145				let expected_types =
146					expected.iter().map(|t| format!("{:?}", t)).collect::<Vec<_>>().join(", ");
147				write!(
148					f,
149					"Function {} argument {} has invalid type: expected one of [{}], got {:?}",
150					function.text(),
151					argument_index + 1,
152					expected_types,
153					actual
154				)
155			}
156			AggregateFunctionError::ExecutionFailed {
157				function,
158				reason,
159			} => {
160				write!(f, "Function {} execution failed: {}", function.text(), reason)
161			}
162			AggregateFunctionError::Wrapped(err) => {
163				write!(f, "{}", err)
164			}
165		}
166	}
167}
168
169impl std::error::Error for AggregateFunctionError {}
170
171impl From<reifydb_type::error::Error> for AggregateFunctionError {
172	fn from(err: reifydb_type::error::Error) -> Self {
173		AggregateFunctionError::Wrapped(Box::new(err))
174	}
175}
176
177impl From<AggregateFunctionError> for reifydb_type::error::Error {
178	fn from(err: AggregateFunctionError) -> Self {
179		use reifydb_type::error::diagnostic::function::{
180			arity_mismatch, execution_failed, invalid_argument_type,
181		};
182
183		match err {
184			AggregateFunctionError::ArityMismatch {
185				function,
186				expected,
187				actual,
188			} => reifydb_type::error!(arity_mismatch(function, expected, actual)),
189			AggregateFunctionError::InvalidArgumentType {
190				function,
191				argument_index,
192				expected,
193				actual,
194			} => reifydb_type::error!(invalid_argument_type(function, argument_index, expected, actual)),
195			AggregateFunctionError::ExecutionFailed {
196				function,
197				reason,
198			} => reifydb_type::error!(execution_failed(function, reason)),
199			AggregateFunctionError::Wrapped(err) => *err,
200		}
201	}
202}
203
204/// Errors that can occur when executing a generator function
205#[derive(Debug)]
206pub enum GeneratorFunctionError {
207	/// Function called with wrong number of arguments
208	ArityMismatch {
209		function: Fragment,
210		expected: usize,
211		actual: usize,
212	},
213	/// Argument has invalid type
214	InvalidArgumentType {
215		function: Fragment,
216		argument_index: usize,
217		expected: Vec<Type>,
218		actual: Type,
219	},
220	/// Function execution failed
221	ExecutionFailed {
222		function: Fragment,
223		reason: String,
224	},
225	/// Generator function not found
226	NotFound {
227		function: Fragment,
228	},
229	/// Wrapped error from underlying operation
230	Wrapped(Box<reifydb_type::error::Error>),
231}
232
233impl Display for GeneratorFunctionError {
234	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
235		match self {
236			GeneratorFunctionError::ArityMismatch {
237				function,
238				expected,
239				actual,
240			} => write!(f, "Function {} expects {} arguments, got {}", function.text(), expected, actual),
241			GeneratorFunctionError::InvalidArgumentType {
242				function,
243				argument_index,
244				expected,
245				actual,
246			} => {
247				let expected_types =
248					expected.iter().map(|t| format!("{:?}", t)).collect::<Vec<_>>().join(", ");
249				write!(
250					f,
251					"Function {} argument {} has invalid type: expected one of [{}], got {:?}",
252					function.text(),
253					argument_index + 1,
254					expected_types,
255					actual
256				)
257			}
258			GeneratorFunctionError::ExecutionFailed {
259				function,
260				reason,
261			} => {
262				write!(f, "Function {} execution failed: {}", function.text(), reason)
263			}
264			GeneratorFunctionError::NotFound {
265				function,
266			} => {
267				write!(f, "Generator function '{}' not found", function.text())
268			}
269			GeneratorFunctionError::Wrapped(err) => {
270				write!(f, "{}", err)
271			}
272		}
273	}
274}
275
276impl std::error::Error for GeneratorFunctionError {}
277
278impl From<reifydb_type::error::Error> for GeneratorFunctionError {
279	fn from(err: reifydb_type::error::Error) -> Self {
280		GeneratorFunctionError::Wrapped(Box::new(err))
281	}
282}
283
284impl From<GeneratorFunctionError> for reifydb_type::error::Error {
285	fn from(err: GeneratorFunctionError) -> Self {
286		use reifydb_type::error::diagnostic::function::{
287			arity_mismatch, execution_failed, generator_not_found, invalid_argument_type,
288		};
289
290		match err {
291			GeneratorFunctionError::ArityMismatch {
292				function,
293				expected,
294				actual,
295			} => reifydb_type::error!(arity_mismatch(function, expected, actual)),
296			GeneratorFunctionError::InvalidArgumentType {
297				function,
298				argument_index,
299				expected,
300				actual,
301			} => reifydb_type::error!(invalid_argument_type(function, argument_index, expected, actual)),
302			GeneratorFunctionError::ExecutionFailed {
303				function,
304				reason,
305			} => reifydb_type::error!(execution_failed(function, reason)),
306			GeneratorFunctionError::NotFound {
307				function,
308			} => reifydb_type::error!(generator_not_found(function)),
309			GeneratorFunctionError::Wrapped(err) => *err,
310		}
311	}
312}
313
314/// Result type for scalar function operations
315pub type ScalarFunctionResult<T> = Result<T, ScalarFunctionError>;
316
317/// Result type for aggregate function operations
318pub type AggregateFunctionResult<T> = Result<T, AggregateFunctionError>;
319
320/// Result type for generator function operations
321pub type GeneratorFunctionResult<T> = Result<T, GeneratorFunctionError>;