use sqlparser::ast::Value;
use crate::error::{Result, SqlError};
use crate::types::*;
pub fn convert_value(val: &Value) -> Result<SqlValue> {
match val {
Value::Number(n, _) => {
if let Ok(i) = n.parse::<i64>() {
Ok(SqlValue::Int(i))
} else if n.contains('.') || n.contains('e') || n.contains('E') {
if let Ok(d) = rust_decimal::Decimal::from_str_exact(n) {
Ok(SqlValue::Decimal(d))
} else if let Ok(f) = n.parse::<f64>() {
Ok(SqlValue::Float(f))
} else {
Ok(SqlValue::String(n.clone()))
}
} else if let Ok(f) = n.parse::<f64>() {
Ok(SqlValue::Float(f))
} else {
Ok(SqlValue::String(n.clone()))
}
}
Value::SingleQuotedString(s) => Ok(SqlValue::String(s.clone())),
Value::Boolean(b) => Ok(SqlValue::Bool(*b)),
Value::Null => Ok(SqlValue::Null),
Value::HexStringLiteral(s) => Ok(SqlValue::Bytes(decode_hex_literal(s)?)),
_ => Err(SqlError::Unsupported {
detail: format!("value literal: {val}"),
}),
}
}
fn decode_hex_literal(s: &str) -> Result<Vec<u8>> {
parse_hex_bytes(s).map_err(|reason| SqlError::Parse {
detail: format!("hex literal {reason}: X'{s}'"),
})
}
pub(crate) fn parse_hex_bytes(s: &str) -> std::result::Result<Vec<u8>, &'static str> {
if !s.len().is_multiple_of(2) {
return Err("must have an even number of digits");
}
(0..s.len())
.step_by(2)
.map(|i| u8::from_str_radix(&s[i..i + 2], 16).map_err(|_| "contains an invalid hex digit"))
.collect()
}
pub(super) fn parse_interval_to_micros(s: &str) -> Option<i64> {
let s = s.trim();
if s.is_empty() {
return None;
}
if let Some(dur) = nodedb_types::NdbDuration::parse(s) {
return Some(dur.micros);
}
if let Ok(ms) = nodedb_types::kv_parsing::parse_interval_to_ms(s) {
return Some(ms as i64 * 1000); }
None
}