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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
use {
    crate::{
        ast::{DataType, DateTimeField},
        data::Value,
    },
    serde::Serialize,
    std::fmt::Debug,
    strum_macros::Display,
    thiserror::Error,
};

#[derive(Error, Serialize, Debug, PartialEq)]
pub enum ValueError {
    #[error("literal: {literal} is incompatible with data type: {data_type:?}")]
    IncompatibleLiteralForDataType {
        data_type: DataType,
        literal: String,
    },

    #[error("incompatible data type, data type: {data_type:#?}, value: {value:#?}")]
    IncompatibleDataType { data_type: DataType, value: Value },

    #[error("null value on not null field")]
    NullValueOnNotNullField,

    #[error("failed to parse number")]
    FailedToParseNumber,

    #[error("failed to convert Float to Decimal: {0}")]
    FloatToDecimalConversionFailure(f64),

    #[error("failed to parse date: {0}")]
    FailedToParseDate(String),

    #[error("failed to parse timestamp: {0}")]
    FailedToParseTimestamp(String),

    #[error("failed to parse time: {0}")]
    FailedToParseTime(String),

    #[error("failed to UUID: {0}")]
    FailedToParseUUID(String),

    #[error("failed to parse point: {0}")]
    FailedToParsePoint(String),

    #[error("failed to parse Decimal: {0}")]
    FailedToParseDecimal(String),

    #[error("failed to parse hex string: {0}")]
    FailedToParseHexString(String),

    #[error("failed to parse inet string: {0}")]
    FailedToParseInetString(String),

    #[error("non-numeric values {lhs:?} {operator} {rhs:?}")]
    NonNumericMathOperation {
        lhs: Value,
        rhs: Value,
        operator: NumericBinaryOperator,
    },

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

    #[error("unary plus operation for non numeric value")]
    UnaryPlusOnNonNumeric,

    #[error("unary minus operation for non numeric value")]
    UnaryMinusOnNonNumeric,

    #[error("unary factorial operation for non numeric value")]
    FactorialOnNonNumeric,

    #[error("unary factorial operation for non integer value")]
    FactorialOnNonInteger,

    #[error("unary factorial operation for negative numeric value")]
    FactorialOnNegativeNumeric,

    #[error("unary factorial operation overflow")]
    FactorialOverflow,

    #[error("GCD or LCM calculation overflowed on trying to get the absolute value of {0}")]
    GcdLcmOverflow(i64),

    #[error("LCM calculation resulted in a value out of the i64 range")]
    LcmResultOutOfRange,

    #[error("unary bit_not operation for non numeric value")]
    UnaryBitwiseNotOnNonNumeric,

    #[error("unary bit_not operation for non integer value")]
    UnaryBitwiseNotOnNonInteger,

    #[error("unreachable failure on parsing number")]
    UnreachableNumberParsing,

    #[error("unimplemented cast: {value:?} as {data_type}")]
    UnimplementedCast { value: Value, data_type: DataType },

    #[error("failed to cast from hex string to bytea: {0}")]
    CastFromHexToByteaFailed(String),

    #[error("function CONCAT requires at least 1 argument")]
    EmptyArgNotAllowedInConcat,

    // Cast errors from literal to value
    #[error("literal cast failed from text to integer: {0}")]
    LiteralCastFromTextToIntegerFailed(String),

    #[error("literal cast failed from text to Unsigned Int(8): {0}")]
    LiteralCastFromTextToUnsignedInt8Failed(String),

    #[error("literal cast failed from text to UINT16: {0}")]
    LiteralCastFromTextToUint16Failed(String),

    #[error("literal cast failed from text to UINT32: {0}")]
    LiteralCastFromTextToUint32Failed(String),

    #[error("literal cast failed from text to UINT64: {0}")]
    LiteralCastFromTextToUint64Failed(String),

    #[error("literal cast failed from text to UINT128: {0}")]
    LiteralCastFromTextToUint128Failed(String),

    #[error("literal cast failed from text to float: {0}")]
    LiteralCastFromTextToFloatFailed(String),

    #[error("literal cast failed from text to decimal: {0}")]
    LiteralCastFromTextToDecimalFailed(String),

    #[error("literal cast failed to boolean: {0}")]
    LiteralCastToBooleanFailed(String),

    #[error("literal cast failed to date: {0}")]
    LiteralCastToDateFailed(String),

    #[error("literal cast from {1} to {0} failed")]
    LiteralCastToDataTypeFailed(DataType, String),

    #[error("literal cast failed to Int(8): {0}")]
    LiteralCastToInt8Failed(String),

    #[error("literal cast failed to Unsigned Int(8): {0}")]
    LiteralCastToUnsignedInt8Failed(String),

    #[error("literal cast failed to UINT16: {0}")]
    LiteralCastToUint16Failed(String),

    #[error("literal cast failed to UNIT32: {0}")]
    LiteralCastToUint32Failed(String),

    #[error("literal cast failed to UNIT64: {0}")]
    LiteralCastToUint64Failed(String),

    #[error("literal cast failed to UNIT128: {0}")]
    LiteralCastToUint128Failed(String),

    #[error("literal cast failed to time: {0}")]
    LiteralCastToTimeFailed(String),

    #[error("literal cast failed to timestamp: {0}")]
    LiteralCastToTimestampFailed(String),

    #[error("unreachable literal cast from number to integer: {0}")]
    UnreachableLiteralCastFromNumberToInteger(String),

    #[error("unreachable literal cast from number to float: {0}")]
    UnreachableLiteralCastFromNumberToFloat(String),

    #[error("unimplemented literal cast: {literal} as {data_type:?}")]
    UnimplementedLiteralCast {
        data_type: DataType,
        literal: String,
    },

    #[error("unreachable integer overflow: {0}")]
    UnreachableIntegerOverflow(String),

    #[error("operator doesn't exist: {base:?} {case} {pattern:?}", case = if *case_sensitive { "LIKE" } else { "ILIKE" })]
    LikeOnNonString {
        base: Value,
        pattern: Value,
        case_sensitive: bool,
    },

    #[error("extract format not matched: {value:?} FROM {field:?})")]
    ExtractFormatNotMatched { value: Value, field: DateTimeField },

    #[error("big endian export not supported for {0} type")]
    BigEndianExportNotSupported(String),

    #[error("invalid json string: {0}")]
    InvalidJsonString(String),

    #[error("json object type is required")]
    JsonObjectTypeRequired,

    #[error("json array type is required")]
    JsonArrayTypeRequired,

    #[error("unreachable - failed to parse json number: {0}")]
    UnreachableJsonNumberParseFailure(String),

    #[error("selector requires MAP or LIST types")]
    SelectorRequiresMapOrListTypes,

    #[error("overflow occurred: {lhs:?} {operator} {rhs:?}")]
    BinaryOperationOverflow {
        lhs: Value,
        rhs: Value,
        operator: NumericBinaryOperator,
    },

    #[error("non numeric value in sqrt {0:?}")]
    SqrtOnNonNumeric(Value),

    #[error("non-string parameter in position: {} IN {}", String::from(.from), String::from(.sub))]
    NonStringParameterInPosition { from: Value, sub: Value },

    #[error("non-string parameter in find idx: {}, {}", String::from(.sub), String::from(.from))]
    NonStringParameterInFindIdx { sub: Value, from: Value },

    #[error("non positive offset in find idx: {0}")]
    NonPositiveIntegerOffsetInFindIdx(String),

    #[error("failed to convert Value to Expr")]
    ValueToExprConversionFailure,

    #[error("failed to convert Value to u32: {0}")]
    I64ToU32ConversionFailure(String),
}

#[derive(Debug, PartialEq, Eq, Serialize, Display)]
pub enum NumericBinaryOperator {
    #[strum(to_string = "+")]
    Add,
    #[strum(to_string = "-")]
    Subtract,
    #[strum(to_string = "*")]
    Multiply,
    #[strum(to_string = "/")]
    Divide,
    #[strum(to_string = "%")]
    Modulo,
    #[strum(to_string = "&")]
    BitwiseAnd,
    #[strum(to_string = "<<")]
    BitwiseShiftLeft,
    #[strum(to_string = ">>")]
    BitwiseShiftRight,
}