nodedb_sql/resolver/expr/
value.rs1use sqlparser::ast::Value;
4
5use crate::error::{Result, SqlError};
6use crate::types::*;
7
8pub fn convert_value(val: &Value) -> Result<SqlValue> {
15 match val {
16 Value::Number(n, _) => {
17 if let Ok(i) = n.parse::<i64>() {
18 Ok(SqlValue::Int(i))
19 } else if n.contains('.') || n.contains('e') || n.contains('E') {
20 if let Ok(d) = rust_decimal::Decimal::from_str_exact(n) {
22 Ok(SqlValue::Decimal(d))
23 } else if let Ok(f) = n.parse::<f64>() {
24 Ok(SqlValue::Float(f))
25 } else {
26 Ok(SqlValue::String(n.clone()))
27 }
28 } else if let Ok(f) = n.parse::<f64>() {
29 Ok(SqlValue::Float(f))
30 } else {
31 Ok(SqlValue::String(n.clone()))
32 }
33 }
34 Value::SingleQuotedString(s) => Ok(SqlValue::String(s.clone())),
35 Value::Boolean(b) => Ok(SqlValue::Bool(*b)),
36 Value::Null => Ok(SqlValue::Null),
37 Value::HexStringLiteral(s) => Ok(SqlValue::Bytes(decode_hex_literal(s)?)),
40 _ => Err(SqlError::Unsupported {
41 detail: format!("value literal: {val}"),
42 }),
43 }
44}
45
46fn decode_hex_literal(s: &str) -> Result<Vec<u8>> {
49 parse_hex_bytes(s).map_err(|reason| SqlError::Parse {
50 detail: format!("hex literal {reason}: X'{s}'"),
51 })
52}
53
54pub(crate) fn parse_hex_bytes(s: &str) -> std::result::Result<Vec<u8>, &'static str> {
60 if !s.len().is_multiple_of(2) {
61 return Err("must have an even number of digits");
62 }
63 (0..s.len())
64 .step_by(2)
65 .map(|i| u8::from_str_radix(&s[i..i + 2], 16).map_err(|_| "contains an invalid hex digit"))
66 .collect()
67}
68
69pub(super) fn parse_interval_to_micros(s: &str) -> Option<i64> {
74 let s = s.trim();
75 if s.is_empty() {
76 return None;
77 }
78
79 if let Some(dur) = nodedb_types::NdbDuration::parse(s) {
81 return Some(dur.micros);
82 }
83
84 if let Ok(ms) = nodedb_types::kv_parsing::parse_interval_to_ms(s) {
86 return Some(ms as i64 * 1000); }
88
89 None
90}