Fold a `SqlExpr` to a literal `SqlValue` at plan time, or return `None` if the expression depends on row/runtime state (column refs, subqueries, unknown functions, etc.).
(expr: &SqlExpr, registry: &FunctionRegistry)
| 45 | /// `None` if the expression depends on row/runtime state (column refs, |
| 46 | /// subqueries, unknown functions, etc.). |
| 47 | pub fn fold_constant(expr: &SqlExpr, registry: &FunctionRegistry) -> Option<SqlValue> { |
| 48 | match expr { |
| 49 | SqlExpr::Literal(v) => Some(v.clone()), |
| 50 | SqlExpr::UnaryOp { |
| 51 | op: UnaryOp::Neg, |
| 52 | expr, |
| 53 | } => match fold_constant(expr, registry)? { |
| 54 | SqlValue::Int(i) => Some(SqlValue::Int(-i)), |
| 55 | SqlValue::Float(f) => Some(SqlValue::Float(-f)), |
| 56 | SqlValue::Decimal(d) => Some(SqlValue::Decimal(-d)), |
| 57 | _ => None, |
| 58 | }, |
| 59 | SqlExpr::BinaryOp { left, op, right } => { |
| 60 | let l = fold_constant(left, registry)?; |
| 61 | let r = fold_constant(right, registry)?; |
| 62 | fold_binary(l, *op, r) |
| 63 | } |
| 64 | SqlExpr::Function { name, args, .. } => fold_function_call(name, args, registry), |
| 65 | SqlExpr::Cast { expr, to_type } => fold_cast(fold_constant(expr, registry)?, to_type), |
| 66 | _ => None, |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | /// Fold a CAST at plan time. Only applies when the inner expression is already |
| 71 | /// a constant. The `to_type` string comes from sqlparser's `format!("{data_type}")` |