1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
use {
    crate::ast::{Aggregate, BinaryOperator, Expr, ToSql},
    serde::{Serialize, Serializer},
    std::fmt::Debug,
    thiserror::Error,
};

#[derive(Error, Serialize, Debug, PartialEq, Eq)]
pub enum EvaluateError {
    #[error(transparent)]
    #[serde(serialize_with = "error_serialize")]
    FormatParseError(#[from] chrono::format::ParseError),

    #[error("literal add on non-numeric")]
    LiteralAddOnNonNumeric,

    #[error("function requires string value: {0}")]
    FunctionRequiresStringValue(String),

    #[error("function requires integer value: {0}")]
    FunctionRequiresIntegerValue(String),

    #[error("function requires float or integer value: {0}")]
    FunctionRequiresFloatOrIntegerValue(String),

    #[error("function requires usize value: {0}")]
    FunctionRequiresUSizeValue(String),

    #[error("function requires float value: {0}")]
    FunctionRequiresFloatValue(String),

    #[error("extract format does not support value: {0}")]
    ExtractFormatNotMatched(String),

    #[error("function requires map value: {0}")]
    FunctionRequiresMapValue(String),

    #[error("function requires point value: {0}")]
    FunctionRequiresPointValue(String),

    #[error("function requires date or datetime value: {0}")]
    FunctionRequiresDateOrDateTimeValue(String),

    #[error("function requires one of string, list, map types: {0}")]
    FunctionRequiresStrOrListOrMapValue(String),

    #[error("identifier not found: {0}")]
    IdentifierNotFound(String),

    #[error("identifier not found: {table_alias}.{column_name}")]
    CompoundIdentifierNotFound {
        table_alias: String,
        column_name: String,
    },

    #[error("only boolean value is accepted: {0}")]
    BooleanTypeRequired(String),

    #[error("expr requires map or list value")]
    MapOrListTypeRequired,

    #[error("expr requires map value")]
    MapTypeRequired,

    #[error("expr requires list value")]
    ListTypeRequired,

    #[error("all elements in the list must be comparable to each other")]
    InvalidSortType,

    #[error("sort order must be either ASC or DESC")]
    InvalidSortOrder,

    #[error("map or string value required for json map conversion: {0}")]
    MapOrStringValueRequired(String),

    #[error("text literal required for json map conversion: {0}")]
    TextLiteralRequired(String),

    #[error("unsupported stateless expression: {}", .0.to_sql())]
    UnsupportedStatelessExpr(Expr),

    #[error("context is required for identifier evaluation: {}", .0.to_sql())]
    ContextRequiredForIdentEvaluation(Expr),

    #[error("unreachable empty aggregate value: {0:?}")]
    UnreachableEmptyAggregateValue(Aggregate),

    #[error("incompatible bit operation between {0} and {1}")]
    IncompatibleBitOperation(String, String),

    #[error("the divisor should not be zero")]
    DivisorShouldNotBeZero,

    #[error("negative substring length not allowed")]
    NegativeSubstrLenNotAllowed,

    #[error("subquery returns more than one row")]
    MoreThanOneRowReturned,

    #[error("subquery returns more than one column")]
    MoreThanOneColumnReturned,

    #[error("schemaless projection is not allowed for IN (subquery)")]
    SchemalessProjectionForInSubQuery,

    #[error("schemaless projection is not allowed for subquery")]
    SchemalessProjectionForSubQuery,

    #[error("format function does not support following data_type: {0}")]
    UnsupportedExprForFormatFunction(String),

    #[error("support single character only")]
    AsciiFunctionRequiresSingleCharacterValue,

    #[error("non-ascii character not allowed")]
    NonAsciiCharacterNotAllowed,

    #[error("function requires integer value in range")]
    ChrFunctionRequiresIntegerValueInRange0To255,

    #[error("unsupported evaluate binary operation {} {} {}", .left, .op.to_sql(), .right)]
    UnsupportedBinaryOperation {
        left: String,
        op: BinaryOperator,
        right: String,
    },

    #[error("unsupported evaluate string unary plus: {0}")]
    UnsupportedUnaryPlus(String),

    #[error("unsupported evaluate string unary minus: {0}")]
    UnsupportedUnaryMinus(String),

    #[error("unsupported evaluate string unary factorial: {0}")]
    UnsupportedUnaryFactorial(String),

    #[error("incompatible bit operation ~{0}")]
    IncompatibleUnaryBitwiseNotOperation(String),

    #[error("unsupported custom function in subqueries")]
    UnsupportedCustomFunction,

    #[error(r#"The function "{function_name}" requires at least {required_minimum} argument(s), but {found} were provided."#)]
    FunctionRequiresMoreArguments {
        function_name: String,
        required_minimum: usize,
        found: usize,
    },

    #[error("function args.length not matching: {name}, expected: {expected_minimum} ~ {expected_maximum}, found: {found}")]
    FunctionArgsLengthNotWithinRange {
        name: String,
        expected_minimum: usize,
        expected_maximum: usize,
        found: usize,
    },

    #[error("unsupported function: {0}")]
    UnsupportedFunction(String),

    #[error("The provided arguments are non-comparable: {0}")]
    NonComparableArgumentError(String),

    #[error("function requires at least one argument: {0}")]
    FunctionRequiresAtLeastOneArgument(String),
}

fn error_serialize<S>(error: &chrono::format::ParseError, serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    let display = format!("{}", error);
    serializer.serialize_str(&display)
}