1use std::{
3 fmt::Display,
4 ops::{Add, Div, Mul, Neg, Not, Rem, Sub},
5};
6
7use ordered_float::OrderedFloat;
8use sqlparser::ast::{self, DataType};
9
10use crate::{
11 expr::{BinOp, UnOp},
12 vm::RuntimeError,
13};
14
15#[derive(Debug, PartialEq, PartialOrd, Clone, Eq, Ord)]
19pub enum Value {
20 Null,
21
22 Bool(bool),
23
24 Int64(i64),
28
29 Float64(OrderedFloat<f64>),
36
37 String(String),
42
43 Binary(Vec<u8>),
44}
45
46impl Display for Value {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 match self {
49 Self::Null => write!(f, "NULL"),
50 Self::Bool(v) => write!(f, "{}", v),
51 Self::Int64(v) => write!(f, "{}", v),
52 Self::Float64(v) => write!(f, "{}", v),
53 Self::String(v) => write!(f, "{}", v),
54 Self::Binary(v) => write!(f, "{:?}", v),
55 }
56 }
57}
58
59impl Value {
60 pub fn is_true(self) -> Result<Value, ValueUnaryOpError> {
61 match self {
62 Value::Bool(lhs) => Ok(Value::Bool(lhs)),
63 _ => Err(ValueUnaryOpError {
64 operator: UnOp::IsTrue,
65 value: self,
66 }),
67 }
68 }
69
70 pub fn is_false(self) -> Result<Value, ValueUnaryOpError> {
71 match self {
72 Value::Bool(lhs) => Ok(Value::Bool(!lhs)),
73 _ => Err(ValueUnaryOpError {
74 operator: UnOp::IsFalse,
75 value: self,
76 }),
77 }
78 }
79
80 pub fn is_null(self) -> Result<Value, ValueUnaryOpError> {
81 match self {
82 Value::Null => Ok(Value::Bool(true)),
83 _ => Ok(Value::Bool(false)),
84 }
85 }
86
87 pub fn is_not_null(self) -> Result<Value, ValueUnaryOpError> {
88 match self {
89 Value::Null => Ok(Value::Bool(false)),
90 _ => Ok(Value::Bool(true)),
91 }
92 }
93
94 pub fn like(self, rhs: Value) -> Result<Value, ValueBinaryOpError> {
95 match (&self, &rhs) {
96 (Value::String(lhs), Value::String(rhs)) => Ok(Value::Bool(lhs.contains(rhs))),
98 _ => Err(ValueBinaryOpError {
99 operator: BinOp::Like,
100 values: (self, rhs),
101 }),
102 }
103 }
104
105 pub fn ilike(self, rhs: Value) -> Result<Value, ValueBinaryOpError> {
106 match (&self, &rhs) {
107 (Value::String(lhs), Value::String(rhs)) => Ok(Value::Bool(
109 lhs.to_lowercase().contains(&rhs.to_lowercase()),
110 )),
111 _ => Err(ValueBinaryOpError {
112 operator: BinOp::Like,
113 values: (self, rhs),
114 }),
115 }
116 }
117
118 pub fn data_type(&self) -> DataType {
120 match self {
121 Self::Null => DataType::Int(None),
122 Self::Bool(_) => DataType::Boolean,
123 Self::Int64(_) => DataType::Int(None),
124 Self::Float64(_) => DataType::Float(None),
125 Self::String(_) => DataType::String,
126 Self::Binary(_) => DataType::Bytea,
127 }
128 }
129
130 pub(crate) fn sentinel_value(data_type: &DataType) -> Result<Self, RuntimeError> {
132 Ok(match data_type {
133 DataType::Boolean => Self::Bool(false),
134 DataType::Int(_) => Self::Int64(0),
135 DataType::UnsignedInt(_) => Self::Int64(0),
136 DataType::Float(_) => Self::Float64(0.0.into()),
137 DataType::String => Self::String("".to_owned()),
138 DataType::Bytea => Self::Binary(vec![]),
139 _ => return Err(RuntimeError::UnsupportedType(data_type.clone())),
140 })
141 }
142}
143
144impl TryFrom<ast::Value> for Value {
145 type Error = ValueError;
146
147 fn try_from(val: ast::Value) -> Result<Self, Self::Error> {
148 match val {
149 ast::Value::Null => Ok(Value::Null),
150 ast::Value::Boolean(b) => Ok(Value::Bool(b)),
151 ast::Value::SingleQuotedString(s) => Ok(Value::String(s)),
152 ast::Value::DoubleQuotedString(s) => Ok(Value::String(s)),
153 ast::Value::Number(ref s, _long) => {
154 if let Ok(int) = s.parse::<i64>() {
155 Ok(Value::Int64(int))
156 } else {
157 if let Ok(float) = s.parse::<f64>() {
158 Ok(Value::Float64(float.into()))
159 } else {
160 Err(ValueError {
161 reason: "Unsupported number format",
162 value: val.clone(),
163 })
164 }
165 }
166 }
167 _ => Err(ValueError {
168 reason: "Unsupported value format",
169 value: val,
170 }),
171 }
172 }
173}
174
175impl Add for Value {
176 type Output = Result<Value, ValueBinaryOpError>;
177
178 fn add(self, rhs: Self) -> Self::Output {
179 match self {
180 Value::Null | Value::Bool(_) | Value::String(_) | Value::Binary(_) => {
181 Err(ValueBinaryOpError {
182 operator: BinOp::Plus,
183 values: (self, rhs),
184 })
185 }
186 Value::Int64(lhs) => match rhs {
187 Value::Int64(rhs) => Ok(Value::Int64(lhs + rhs)),
188 _ => Err(ValueBinaryOpError {
189 operator: BinOp::Plus,
190 values: (self, rhs),
191 }),
192 },
193 Value::Float64(lhs) => match rhs {
194 Value::Float64(rhs) => Ok(Value::Float64(lhs + rhs)),
195 _ => Err(ValueBinaryOpError {
196 operator: BinOp::Plus,
197 values: (self, rhs),
198 }),
199 },
200 }
201 }
202}
203
204impl Sub for Value {
205 type Output = Result<Value, ValueBinaryOpError>;
206
207 fn sub(self, rhs: Self) -> Self::Output {
208 match self {
209 Value::Null | Value::Bool(_) | Value::String(_) | Value::Binary(_) => {
210 Err(ValueBinaryOpError {
211 operator: BinOp::Minus,
212 values: (self, rhs),
213 })
214 }
215 Value::Int64(lhs) => match rhs {
216 Value::Int64(rhs) => Ok(Value::Int64(lhs - rhs)),
217 _ => Err(ValueBinaryOpError {
218 operator: BinOp::Minus,
219 values: (self, rhs),
220 }),
221 },
222 Value::Float64(lhs) => match rhs {
223 Value::Float64(rhs) => Ok(Value::Float64(lhs - rhs)),
224 _ => Err(ValueBinaryOpError {
225 operator: BinOp::Minus,
226 values: (self, rhs),
227 }),
228 },
229 }
230 }
231}
232
233impl Mul for Value {
234 type Output = Result<Value, ValueBinaryOpError>;
235
236 fn mul(self, rhs: Self) -> Self::Output {
237 match self {
238 Value::Null | Value::Bool(_) | Value::String(_) | Value::Binary(_) => {
239 Err(ValueBinaryOpError {
240 operator: BinOp::Multiply,
241 values: (self, rhs),
242 })
243 }
244 Value::Int64(lhs) => match rhs {
245 Value::Int64(rhs) => Ok(Value::Int64(lhs * rhs)),
246 _ => Err(ValueBinaryOpError {
247 operator: BinOp::Multiply,
248 values: (self, rhs),
249 }),
250 },
251 Value::Float64(lhs) => match rhs {
252 Value::Float64(rhs) => Ok(Value::Float64(lhs * rhs)),
253 _ => Err(ValueBinaryOpError {
254 operator: BinOp::Multiply,
255 values: (self, rhs),
256 }),
257 },
258 }
259 }
260}
261
262impl Div for Value {
263 type Output = Result<Value, ValueBinaryOpError>;
264
265 fn div(self, rhs: Self) -> Self::Output {
266 match self {
267 Value::Null | Value::Bool(_) | Value::String(_) | Value::Binary(_) => {
268 Err(ValueBinaryOpError {
269 operator: BinOp::Divide,
270 values: (self, rhs),
271 })
272 }
273 Value::Int64(lhs) => match rhs {
274 Value::Int64(rhs) => Ok(Value::Int64(lhs / rhs)),
275 _ => Err(ValueBinaryOpError {
276 operator: BinOp::Divide,
277 values: (self, rhs),
278 }),
279 },
280 Value::Float64(lhs) => match rhs {
281 Value::Float64(rhs) => Ok(Value::Float64(lhs / rhs)),
282 _ => Err(ValueBinaryOpError {
283 operator: BinOp::Divide,
284 values: (self, rhs),
285 }),
286 },
287 }
288 }
289}
290
291impl Rem for Value {
292 type Output = Result<Value, ValueBinaryOpError>;
293
294 fn rem(self, rhs: Self) -> Self::Output {
295 match self {
296 Value::Null | Value::Bool(_) | Value::String(_) | Value::Binary(_) => {
297 Err(ValueBinaryOpError {
298 operator: BinOp::Modulo,
299 values: (self, rhs),
300 })
301 }
302 Value::Int64(lhs) => match rhs {
303 Value::Int64(rhs) => Ok(Value::Int64(lhs % rhs)),
304 _ => Err(ValueBinaryOpError {
305 operator: BinOp::Modulo,
306 values: (self, rhs),
307 }),
308 },
309 Value::Float64(lhs) => match rhs {
310 Value::Float64(rhs) => Ok(Value::Float64(lhs % rhs)),
311 _ => Err(ValueBinaryOpError {
312 operator: BinOp::Modulo,
313 values: (self, rhs),
314 }),
315 },
316 }
317 }
318}
319
320impl Neg for Value {
321 type Output = Result<Value, ValueUnaryOpError>;
322
323 fn neg(self) -> Self::Output {
324 match self {
325 Value::Null | Value::Bool(_) | Value::String(_) | Value::Binary(_) => {
326 Err(ValueUnaryOpError {
327 operator: UnOp::Minus,
328 value: self,
329 })
330 }
331 Value::Int64(lhs) => Ok(Value::Int64(-lhs)),
332 Value::Float64(lhs) => Ok(Value::Float64(-lhs)),
333 }
334 }
335}
336
337impl Not for Value {
338 type Output = Result<Value, ValueUnaryOpError>;
339
340 fn not(self) -> Self::Output {
341 match self {
342 Value::Bool(lhs) => Ok(Value::Bool(!lhs)),
343 _ => Err(ValueUnaryOpError {
344 operator: UnOp::Not,
345 value: self,
346 }),
347 }
348 }
349}
350
351#[derive(Debug, PartialEq)]
353pub struct ValueBinaryOpError {
354 pub operator: BinOp,
355 pub values: (Value, Value),
356}
357
358impl Display for ValueBinaryOpError {
359 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
360 write!(
361 f,
362 "ValueBinaryOpError: unsupported operation '{}' between '{:?}' and '{:?}'",
363 self.operator, self.values.0, self.values.1
364 )
365 }
366}
367
368#[derive(Debug, PartialEq)]
370pub struct ValueUnaryOpError {
371 pub operator: UnOp,
372 pub value: Value,
373}
374
375impl Display for ValueUnaryOpError {
376 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
377 write!(
378 f,
379 "ValueUnaryOpError: unsupported operation '{}' for '{:?}'",
380 self.operator, self.value
381 )
382 }
383}
384
385#[derive(Debug, PartialEq)]
387pub struct ValueError {
388 pub reason: &'static str,
389 pub value: ast::Value,
390}
391
392impl Display for ValueError {
393 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
394 write!(f, "ValueError: {}: {}", self.reason, self.value)
395 }
396}
397
398#[cfg(test)]
399mod tests {
400 use sqlparser::ast;
401
402 use crate::value::ValueError;
403
404 use super::Value;
405
406 #[test]
407 fn create_value() {
408 let value = Value::Null;
409 assert_eq!(value, Value::Null);
410 assert!(value != Value::String("test".to_owned()));
411 }
412
413 #[test]
414 fn conversion_from_ast() {
415 assert_eq!(Value::try_from(ast::Value::Null), Ok(Value::Null));
416
417 assert_eq!(
418 Value::try_from(ast::Value::Number("1000".to_owned(), false)),
419 Ok(Value::Int64(1000))
420 );
421
422 assert_eq!(
423 Value::try_from(ast::Value::Number("1000".to_owned(), true)),
424 Ok(Value::Int64(1000))
425 );
426
427 assert_eq!(
428 Value::try_from(ast::Value::Number("1000.0".to_owned(), false)),
429 Ok(Value::Float64(1000.0.into()))
430 );
431
432 assert_eq!(
433 Value::try_from(ast::Value::Number("0.300000000000000004".to_owned(), false)),
434 Ok(Value::Float64(0.300000000000000004.into()))
435 );
436
437 assert_eq!(
438 Value::try_from(ast::Value::Number("-1".to_owned(), false)),
439 Ok(Value::Int64(-1))
440 );
441
442 assert_eq!(
443 Value::try_from(ast::Value::Number("9223372036854775807".to_owned(), false)),
444 Ok(Value::Int64(9223372036854775807))
445 );
446
447 assert_eq!(
448 Value::try_from(ast::Value::HexStringLiteral("brr".to_owned())),
449 Err(ValueError {
450 reason: "Unsupported value format",
451 value: ast::Value::HexStringLiteral("brr".to_owned())
452 })
453 )
454 }
455}