Skip to main content

nodedb_query/
cast.rs

1//! CAST evaluation for SqlExpr.
2
3use crate::value_ops::{is_truthy, value_to_display_string};
4use nodedb_types::Value;
5
6pub fn eval_cast(val: &Value, to_type: &crate::expr::CastType) -> Value {
7    use crate::expr::CastType;
8    match to_type {
9        CastType::Int => match val {
10            Value::Integer(_) => val.clone(),
11            Value::Float(f) => Value::Integer(*f as i64),
12            Value::String(s) => s.parse::<i64>().map(Value::Integer).unwrap_or(Value::Null),
13            Value::Bool(b) => Value::Integer(*b as i64),
14            Value::Decimal(d) => {
15                use rust_decimal::prelude::ToPrimitive;
16                d.to_i64().map(Value::Integer).unwrap_or(Value::Null)
17            }
18            _ => Value::Null,
19        },
20        CastType::Float => match val {
21            Value::Float(_) => val.clone(),
22            Value::Integer(i) => Value::Float(*i as f64),
23            Value::String(s) => s
24                .parse::<f64>()
25                .map(Value::Float)
26                .ok()
27                .unwrap_or(Value::Null),
28            Value::Decimal(d) => {
29                use rust_decimal::prelude::ToPrimitive;
30                d.to_f64().map(Value::Float).unwrap_or(Value::Null)
31            }
32            _ => Value::Null,
33        },
34        CastType::String => Value::String(value_to_display_string(val)),
35        CastType::Bool => Value::Bool(is_truthy(val)),
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42    use crate::expr::CastType;
43
44    #[test]
45    fn cast_string_to_int() {
46        assert_eq!(
47            eval_cast(&Value::String("42".into()), &CastType::Int),
48            Value::Integer(42)
49        );
50    }
51
52    #[test]
53    fn cast_float_to_int() {
54        assert_eq!(
55            eval_cast(&Value::Float(3.7), &CastType::Int),
56            Value::Integer(3)
57        );
58    }
59
60    #[test]
61    fn cast_int_to_string() {
62        assert_eq!(
63            eval_cast(&Value::Integer(42), &CastType::String),
64            Value::String("42".into())
65        );
66    }
67
68    #[test]
69    fn cast_to_bool() {
70        assert_eq!(
71            eval_cast(&Value::Integer(1), &CastType::Bool),
72            Value::Bool(true)
73        );
74        assert_eq!(
75            eval_cast(&Value::Integer(0), &CastType::Bool),
76            Value::Bool(false)
77        );
78        assert_eq!(
79            eval_cast(&Value::String(String::new()), &CastType::Bool),
80            Value::Bool(false)
81        );
82        assert_eq!(
83            eval_cast(&Value::String("x".into()), &CastType::Bool),
84            Value::Bool(true)
85        );
86    }
87}