gluesql_core/executor/evaluate/
error.rs

1use {
2    crate::ast::{Aggregate, BinaryOperator, DataType, Expr, ToSql},
3    serde::{Serialize, Serializer},
4    std::fmt::Debug,
5    thiserror::Error,
6};
7
8#[derive(Error, Serialize, Debug, PartialEq, Eq)]
9pub enum EvaluateError {
10    #[error(transparent)]
11    #[serde(serialize_with = "error_serialize")]
12    FormatParseError(#[from] chrono::format::ParseError),
13
14    #[error("literal add on non-numeric")]
15    LiteralAddOnNonNumeric,
16
17    #[error("function requires string value: {0}")]
18    FunctionRequiresStringValue(String),
19
20    #[error("function requires integer or string value: {0}")]
21    FunctionRequiresIntegerOrStringValue(String),
22
23    #[error("arrow base requires MAP or LIST types")]
24    ArrowBaseRequiresMapOrList,
25
26    #[error("arrow selector requires integer or string value: {0}")]
27    ArrowSelectorRequiresIntegerOrString(String),
28
29    #[error("function requires integer value: {0}")]
30    FunctionRequiresIntegerValue(String),
31
32    #[error("function requires float or integer value: {0}")]
33    FunctionRequiresFloatOrIntegerValue(String),
34
35    #[error("function requires usize value: {0}")]
36    FunctionRequiresUSizeValue(String),
37
38    #[error("function requires float value: {0}")]
39    FunctionRequiresFloatValue(String),
40
41    #[error("extract format does not support value: {0}")]
42    ExtractFormatNotMatched(String),
43
44    #[error("function requires map value: {0}")]
45    FunctionRequiresMapValue(String),
46
47    #[error("function requires point value: {0}")]
48    FunctionRequiresPointValue(String),
49
50    #[error("function requires date or datetime value: {0}")]
51    FunctionRequiresDateOrDateTimeValue(String),
52
53    #[error("function requires one of string, list, map types: {0}")]
54    FunctionRequiresStrOrListOrMapValue(String),
55
56    #[error("identifier not found: {0}")]
57    IdentifierNotFound(String),
58
59    #[error("identifier not found: {table_alias}.{column_name}")]
60    CompoundIdentifierNotFound {
61        table_alias: String,
62        column_name: String,
63    },
64
65    #[error("only boolean value is accepted: {0}")]
66    BooleanTypeRequired(String),
67
68    #[error("expr requires map or list value")]
69    MapOrListTypeRequired,
70
71    #[error("expr requires map value")]
72    MapTypeRequired,
73
74    #[error("expr requires list value")]
75    ListTypeRequired,
76
77    #[error("all elements in the list must be comparable to each other")]
78    InvalidSortType,
79
80    #[error("sort order must be either ASC or DESC")]
81    InvalidSortOrder,
82
83    #[error("map or string value required for json map conversion: {0}")]
84    MapOrStringValueRequired(String),
85
86    #[error("text literal required for json map conversion: {0}")]
87    TextLiteralRequired(String),
88
89    #[error("unsupported stateless expression: {}", .0.to_sql())]
90    UnsupportedStatelessExpr(Box<Expr>),
91
92    #[error("context is required for identifier evaluation: {}", .0.to_sql())]
93    ContextRequiredForIdentEvaluation(Box<Expr>),
94
95    #[error("unreachable empty aggregate value: {0:?}")]
96    UnreachableEmptyAggregateValue(Box<Aggregate>),
97
98    #[error("filter context is required for aggregate function: {0:?}")]
99    FilterContextRequiredForAggregate(Box<Aggregate>),
100
101    #[error("incompatible bit operation between {0} and {1}")]
102    IncompatibleBitOperation(String, String),
103
104    #[error("the divisor should not be zero")]
105    DivisorShouldNotBeZero,
106
107    #[error("negative substring length not allowed")]
108    NegativeSubstrLenNotAllowed,
109
110    #[error("subquery returns more than one row")]
111    MoreThanOneRowReturned,
112
113    #[error("subquery returns more than one column")]
114    MoreThanOneColumnReturned,
115
116    #[error("schemaless projection is not allowed for IN (subquery)")]
117    SchemalessProjectionForInSubQuery,
118
119    #[error("schemaless projection is not allowed for subquery")]
120    SchemalessProjectionForSubQuery,
121
122    #[error("format function does not support following data_type: {0}")]
123    UnsupportedExprForFormatFunction(String),
124
125    #[error("support single character only")]
126    AsciiFunctionRequiresSingleCharacterValue,
127
128    #[error("non-ascii character not allowed")]
129    NonAsciiCharacterNotAllowed,
130
131    #[error("function requires integer value in range")]
132    ChrFunctionRequiresIntegerValueInRange0To255,
133
134    #[error("unsupported evaluate binary operation {} {} {}", .left, .op.to_sql(), .right)]
135    UnsupportedBinaryOperation {
136        left: String,
137        op: BinaryOperator,
138        right: String,
139    },
140
141    #[error("unsupported evaluate string unary plus: {0}")]
142    UnsupportedUnaryPlus(String),
143
144    #[error("unsupported evaluate string unary minus: {0}")]
145    UnsupportedUnaryMinus(String),
146
147    #[error("unary factorial requires numeric literal: {0}")]
148    UnaryFactorialRequiresNumericLiteral(String),
149
150    #[error("unary bitwise-not requires integer literal: {0}")]
151    UnaryBitwiseNotRequiresIntegerLiteral(String),
152
153    #[error("operator doesn't exist: {base} {case} {pattern}", case = if *case_sensitive { "LIKE" } else { "ILIKE" })]
154    LikeOnNonStringLiteral {
155        base: String,
156        pattern: String,
157        case_sensitive: bool,
158    },
159
160    #[error("unsupported custom function in subqueries")]
161    UnsupportedCustomFunction,
162
163    #[error(r#"The function "{function_name}" requires at least {required_minimum} argument(s), but {found} were provided."#)]
164    FunctionRequiresMoreArguments {
165        function_name: String,
166        required_minimum: usize,
167        found: usize,
168    },
169
170    #[error(
171        "function args.length not matching: {name}, expected: {expected_minimum} ~ {expected_maximum}, found: {found}"
172    )]
173    FunctionArgsLengthNotWithinRange {
174        name: String,
175        expected_minimum: usize,
176        expected_maximum: usize,
177        found: usize,
178    },
179
180    #[error("unsupported function: {0}")]
181    UnsupportedFunction(String),
182
183    #[error("The provided arguments are non-comparable: {0}")]
184    NonComparableArgumentError(String),
185
186    #[error("function requires at least one argument: {0}")]
187    FunctionRequiresAtLeastOneArgument(String),
188
189    #[error("function CONCAT requires at least 1 argument")]
190    EmptyArgNotAllowedInConcat,
191
192    #[error("LCM calculation resulted in a value out of the i64 range")]
193    LcmResultOutOfRange,
194
195    #[error("GCD or LCM calculation overflowed on trying to get the absolute value of {0}")]
196    GcdLcmOverflow(i64),
197
198    #[error("failed to convert Value to u32: {0}")]
199    I64ToU32ConversionFailure(String),
200
201    #[error("failed to parse number {literal:?} to {data_type}")]
202    NumberParseFailed {
203        literal: String,
204        data_type: DataType,
205    },
206
207    #[error("failed to cast number {literal:?} to {data_type}")]
208    NumberCastFailed {
209        literal: String,
210        data_type: DataType,
211    },
212
213    #[error("failed to parse text {literal:?} to {data_type}")]
214    TextParseFailed {
215        literal: String,
216        data_type: DataType,
217    },
218
219    #[error("failed to cast text {literal:?} to {data_type}")]
220    TextCastFailed {
221        literal: String,
222        data_type: DataType,
223    },
224}
225
226#[allow(clippy::trivially_copy_pass_by_ref)]
227fn error_serialize<S>(error: &chrono::format::ParseError, serializer: S) -> Result<S::Ok, S::Error>
228where
229    S: Serializer,
230{
231    let display = format!("{error}");
232    serializer.serialize_str(&display)
233}