use crate::planner::{ContextProvider, PlannerContext, SqlToRel};
use datafusion_common::{not_impl_err, plan_err, DFSchema, Result};
use datafusion_expr::{
type_coercion::{is_interval, is_timestamp},
Expr, ExprSchemable,
};
use sqlparser::ast::{Expr as SQLExpr, UnaryOperator, Value};
impl<S: ContextProvider> SqlToRel<'_, S> {
pub(crate) fn parse_sql_unary_op(
&self,
op: UnaryOperator,
expr: SQLExpr,
schema: &DFSchema,
planner_context: &mut PlannerContext,
) -> Result<Expr> {
match op {
UnaryOperator::Not => Ok(Expr::Not(Box::new(
self.sql_expr_to_logical_expr(expr, schema, planner_context)?,
))),
UnaryOperator::Plus => {
let operand =
self.sql_expr_to_logical_expr(expr, schema, planner_context)?;
let (data_type, _) = operand.data_type_and_nullable(schema)?;
if data_type.is_numeric()
|| is_interval(&data_type)
|| is_timestamp(&data_type)
{
Ok(operand)
} else {
plan_err!("Unary operator '+' only supports numeric, interval and timestamp types")
}
}
UnaryOperator::Minus => {
match expr {
SQLExpr::Value(Value::Number(n, _)) => {
self.parse_sql_number(&n, true)
}
SQLExpr::Interval(interval) => {
self.sql_interval_to_expr(true, interval)
}
_ => Ok(Expr::Negative(Box::new(self.sql_expr_to_logical_expr(
expr,
schema,
planner_context,
)?))),
}
}
_ => not_impl_err!("Unsupported SQL unary operator {op:?}"),
}
}
}