Skip to main content

nodedb_query/
cast.rs

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