1use std::fmt::{Debug, Display};
16
17use risingwave_common::array::{ArrayError, ArrayRef};
18use risingwave_common::types::{DataType, DatumRef, ToText};
19use risingwave_pb::PbFieldNotFound;
20use thiserror::Error;
21use thiserror_ext::{AsReport, ReportDebug};
22
23pub type Result<T, E = ExprError> = std::result::Result<T, E>;
25
26pub struct ContextUnavailable(&'static str);
27
28impl ContextUnavailable {
29 pub fn new(field: &'static str) -> Self {
30 Self(field)
31 }
32}
33
34impl From<ContextUnavailable> for ExprError {
35 fn from(e: ContextUnavailable) -> Self {
36 ExprError::Context(e.0)
37 }
38}
39
40#[derive(Error, ReportDebug)]
42pub enum ExprError {
43 #[error("multiple errors:\n{1}")]
45 Multiple(ArrayRef, MultiExprError),
46
47 #[error("Unsupported function: {0}")]
50 UnsupportedFunction(String),
51
52 #[error("Unsupported cast: {0} to {1}")]
53 UnsupportedCast(DataType, DataType),
54
55 #[error("Casting to {0} out of range")]
56 CastOutOfRange(&'static str),
57
58 #[error("Numeric out of range")]
59 NumericOutOfRange,
60
61 #[error("Numeric out of range: underflow")]
62 NumericUnderflow,
63
64 #[error("Numeric out of range: overflow")]
65 NumericOverflow,
66
67 #[error("Division by zero")]
68 DivisionByZero,
69
70 #[error("Parse error: {0}")]
71 Parse(Box<str>),
73
74 #[error("Invalid parameter {name}: {reason}")]
75 InvalidParam {
77 name: &'static str,
78 reason: Box<str>,
79 },
80
81 #[error("Array error: {0}")]
82 Array(
83 #[from]
84 #[backtrace]
85 ArrayError,
86 ),
87
88 #[error("More than one row returned by {0} used as an expression")]
89 MaxOneRow(&'static str),
90
91 #[error(transparent)]
93 Internal(
94 #[from]
95 #[backtrace]
96 anyhow::Error,
97 ),
98
99 #[error("not a constant")]
100 NotConstant,
101
102 #[error("Context {0} not found")]
103 Context(&'static str),
104
105 #[error("field name must not be null")]
106 FieldNameNull,
107
108 #[error("too few arguments for format()")]
109 TooFewArguments,
110
111 #[error(
112 "null value in column \"{col_name}\" of relation \"{table_name}\" violates not-null constraint"
113 )]
114 NotNullViolation {
115 col_name: Box<str>,
116 table_name: Box<str>,
117 },
118
119 #[error("invalid state: {0}")]
120 InvalidState(String),
121
122 #[error("{0}")]
125 Custom(String),
126
127 #[error("error while evaluating expression `{display}`")]
131 Function {
132 display: Box<str>,
133 #[backtrace]
134 source: Box<dyn std::error::Error + Send + Sync>,
136 },
137}
138
139static_assertions::const_assert_eq!(std::mem::size_of::<ExprError>(), 40);
140
141impl ExprError {
142 pub fn function<'a>(
144 fn_name: &str,
145 args: impl IntoIterator<Item = DatumRef<'a>>,
146 source: impl Into<Box<dyn std::error::Error + Send + Sync>>,
147 ) -> Self {
148 use std::fmt::Write;
149
150 let display = {
151 let mut s = String::new();
152 write!(s, "{}(", fn_name).unwrap();
153 for (i, arg) in args.into_iter().enumerate() {
154 if i > 0 {
155 write!(s, ", ").unwrap();
156 }
157 if let Some(arg) = arg {
158 let arg = arg.to_text();
161 if arg.contains('\\') {
162 write!(s, "E").unwrap();
164 }
165 write!(s, "'").unwrap();
166 for c in arg.chars() {
167 match c {
168 '\'' => write!(s, "''").unwrap(),
169 '\\' => write!(s, "\\\\").unwrap(),
170 _ => write!(s, "{}", c).unwrap(),
171 }
172 }
173 write!(s, "'").unwrap();
174 } else {
175 write!(s, "NULL").unwrap();
176 }
177 }
178 write!(s, ")").unwrap();
179 s
180 };
181
182 Self::Function {
183 display: display.into(),
184 source: source.into(),
185 }
186 }
187}
188
189impl From<chrono::ParseError> for ExprError {
190 fn from(e: chrono::ParseError) -> Self {
191 Self::Parse(e.to_report_string().into())
192 }
193}
194
195impl From<PbFieldNotFound> for ExprError {
196 fn from(err: PbFieldNotFound) -> Self {
197 Self::Internal(anyhow::anyhow!(
198 "Failed to decode prost: field not found `{}`",
199 err.0
200 ))
201 }
202}
203
204#[derive(Error, Debug)]
206pub struct MultiExprError(Box<[ExprError]>);
207
208impl MultiExprError {
209 pub fn into_first(self) -> ExprError {
211 self.0.into_vec().into_iter().next().expect("first error")
212 }
213}
214
215impl Display for MultiExprError {
216 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
217 for (i, e) in self.0.iter().enumerate() {
218 writeln!(f, "{i}: {}", e.as_report())?;
219 }
220 Ok(())
221 }
222}
223
224impl From<Vec<ExprError>> for MultiExprError {
225 fn from(v: Vec<ExprError>) -> Self {
226 Self(v.into_boxed_slice())
227 }
228}
229
230impl FromIterator<ExprError> for MultiExprError {
231 fn from_iter<T: IntoIterator<Item = ExprError>>(iter: T) -> Self {
232 Self(iter.into_iter().collect())
233 }
234}
235
236impl IntoIterator for MultiExprError {
237 type IntoIter = std::vec::IntoIter<ExprError>;
238 type Item = ExprError;
239
240 fn into_iter(self) -> Self::IntoIter {
241 self.0.into_vec().into_iter()
242 }
243}