use crate::planner::{ContextProvider, PlannerContext, SqlToRel};
use datafusion_common::{
not_impl_err, plan_datafusion_err, plan_err, Column, DFSchema, Result,
};
use datafusion_expr::expr::Sort;
use datafusion_expr::{Expr, SortExpr};
use sqlparser::ast::{Expr as SQLExpr, OrderByExpr, Value};
impl<S: ContextProvider> SqlToRel<'_, S> {
pub(crate) fn order_by_to_sort_expr(
&self,
exprs: Vec<OrderByExpr>,
input_schema: &DFSchema,
planner_context: &mut PlannerContext,
literal_to_column: bool,
additional_schema: Option<&DFSchema>,
) -> Result<Vec<SortExpr>> {
if exprs.is_empty() {
return Ok(vec![]);
}
let mut combined_schema;
let order_by_schema = match additional_schema {
Some(schema) => {
combined_schema = input_schema.clone();
combined_schema.merge(schema);
&combined_schema
}
None => input_schema,
};
let mut expr_vec = vec![];
for e in exprs {
let OrderByExpr {
asc,
expr,
nulls_first,
with_fill,
} = e;
if let Some(with_fill) = with_fill {
return not_impl_err!("ORDER BY WITH FILL is not supported: {with_fill}");
}
let expr = match expr {
SQLExpr::Value(Value::Number(v, _)) if literal_to_column => {
let field_index = v
.parse::<usize>()
.map_err(|err| plan_datafusion_err!("{}", err))?;
if field_index == 0 {
return plan_err!(
"Order by index starts at 1 for column indexes"
);
} else if input_schema.fields().len() < field_index {
return plan_err!(
"Order by column out of bounds, specified: {}, max: {}",
field_index,
input_schema.fields().len()
);
}
Expr::Column(Column::from(
input_schema.qualified_field(field_index - 1),
))
}
e => {
self.sql_expr_to_logical_expr(e, order_by_schema, planner_context)?
}
};
let asc = asc.unwrap_or(true);
expr_vec.push(Sort::new(
expr,
asc,
nulls_first.unwrap_or(!asc),
))
}
Ok(expr_vec)
}
}