use sqlparser::ast;
pub fn as_usize_literal(value: &ast::Value) -> Option<usize> {
match value {
ast::Value::Number(n, _) => n.parse::<usize>().ok(),
ast::Value::SingleQuotedString(s) => s.parse::<usize>().ok(),
_ => None,
}
}
pub fn expr_as_usize_literal(expr: &ast::Expr) -> Option<usize> {
if let ast::Expr::Value(v) = expr {
as_usize_literal(&v.value)
} else {
None
}
}
pub fn as_f64_literal(value: &ast::Value) -> Option<f64> {
match value {
ast::Value::Number(n, _) => n.parse::<f64>().ok(),
ast::Value::SingleQuotedString(s) => s.parse::<f64>().ok(),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn usize_from_number() {
assert_eq!(
as_usize_literal(&ast::Value::Number("42".into(), false)),
Some(42)
);
}
#[test]
fn usize_from_unknown_param_text() {
assert_eq!(
as_usize_literal(&ast::Value::SingleQuotedString("42".into())),
Some(42)
);
}
#[test]
fn usize_rejects_non_numeric_text() {
assert_eq!(
as_usize_literal(&ast::Value::SingleQuotedString("abc".into())),
None
);
}
#[test]
fn usize_rejects_negative() {
assert_eq!(
as_usize_literal(&ast::Value::SingleQuotedString("-1".into())),
None
);
}
#[test]
fn f64_from_unknown_param_text() {
assert_eq!(
as_f64_literal(&ast::Value::SingleQuotedString("1.5".into())),
Some(1.5)
);
}
#[test]
fn usize_rejects_overflow_number() {
let huge = format!("{}0", usize::MAX);
assert_eq!(as_usize_literal(&ast::Value::Number(huge, false)), None);
}
#[test]
fn usize_rejects_overflow_text() {
let huge = format!("{}0", usize::MAX);
assert_eq!(
as_usize_literal(&ast::Value::SingleQuotedString(huge)),
None
);
}
#[test]
fn usize_rejects_fractional_number() {
assert_eq!(
as_usize_literal(&ast::Value::Number("1.5".into(), false)),
None
);
}
#[test]
fn usize_rejects_fractional_text() {
assert_eq!(
as_usize_literal(&ast::Value::SingleQuotedString("1.5".into())),
None
);
}
#[test]
fn usize_rejects_scientific_notation() {
assert_eq!(
as_usize_literal(&ast::Value::Number("1e3".into(), false)),
None
);
}
#[test]
fn usize_accepts_zero() {
assert_eq!(
as_usize_literal(&ast::Value::Number("0".into(), false)),
Some(0)
);
}
#[test]
fn usize_accepts_max() {
let max_str = usize::MAX.to_string();
assert_eq!(
as_usize_literal(&ast::Value::Number(max_str, false)),
Some(usize::MAX)
);
}
#[test]
fn f64_accepts_negative() {
assert_eq!(
as_f64_literal(&ast::Value::SingleQuotedString("-1.5".into())),
Some(-1.5)
);
}
#[test]
fn f64_overflow_produces_infinity() {
let out = as_f64_literal(&ast::Value::Number("1e400".into(), false));
assert!(matches!(out, Some(f) if f.is_infinite()));
}
#[test]
fn f64_rejects_non_numeric_text() {
assert_eq!(
as_f64_literal(&ast::Value::SingleQuotedString("foo".into())),
None
);
}
}