@@ -56,9 +56,9 @@ use datafusion_expr::expr::GroupingSet;
5656use sqlparser:: ast:: {
5757 ArrayAgg , BinaryOperator , DataType as SQLDataType , DateTimeField , Expr as SQLExpr ,
5858 Fetch , FunctionArg , FunctionArgExpr , Ident , Join , JoinConstraint , JoinOperator ,
59- ObjectName , Offset as SQLOffset , Query , Select , SelectItem , SetExpr , SetOperator ,
60- ShowStatementFilter , TableFactor , TableWithJoins , TrimWhereField , UnaryOperator ,
61- Value , Values as SQLValues ,
59+ ObjectName , Offset as SQLOffset , PercentileCont , Query , Select , SelectItem , SetExpr ,
60+ SetOperator , ShowStatementFilter , TableFactor , TableWithJoins , TrimWhereField ,
61+ UnaryOperator , Value , Values as SQLValues ,
6262} ;
6363use sqlparser:: ast:: { ColumnDef as SQLColumnDef , ColumnOption } ;
6464use sqlparser:: ast:: { ObjectType , OrderByExpr , Statement } ;
@@ -1440,22 +1440,27 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
14401440
14411441 let order_by_rex = order_by
14421442 . into_iter ( )
1443- . map ( |e| self . order_by_to_sort_expr ( e, plan. schema ( ) ) )
1443+ . map ( |e| self . order_by_to_sort_expr ( e, plan. schema ( ) , true ) )
14441444 . collect :: < Result < Vec < _ > > > ( ) ?;
14451445
14461446 LogicalPlanBuilder :: from ( plan) . sort ( order_by_rex) ?. build ( )
14471447 }
14481448
14491449 /// convert sql OrderByExpr to Expr::Sort
1450- fn order_by_to_sort_expr ( & self , e : OrderByExpr , schema : & DFSchema ) -> Result < Expr > {
1450+ fn order_by_to_sort_expr (
1451+ & self ,
1452+ e : OrderByExpr ,
1453+ schema : & DFSchema ,
1454+ parse_indexes : bool ,
1455+ ) -> Result < Expr > {
14511456 let OrderByExpr {
14521457 asc,
14531458 expr,
14541459 nulls_first,
14551460 } = e;
14561461
14571462 let expr = match expr {
1458- SQLExpr :: Value ( Value :: Number ( v, _) ) => {
1463+ SQLExpr :: Value ( Value :: Number ( v, _) ) if parse_indexes => {
14591464 let field_index = v
14601465 . parse :: < usize > ( )
14611466 . map_err ( |err| DataFusionError :: Plan ( err. to_string ( ) ) ) ?;
@@ -2313,7 +2318,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
23132318 let order_by = window
23142319 . order_by
23152320 . into_iter ( )
2316- . map ( |e| self . order_by_to_sort_expr ( e, schema) )
2321+ . map ( |e| self . order_by_to_sort_expr ( e, schema, true ) )
23172322 . collect :: < Result < Vec < _ > > > ( ) ?;
23182323 let window_frame = window
23192324 . window_frame
@@ -2441,6 +2446,8 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
24412446
24422447 SQLExpr :: ArrayAgg ( array_agg) => self . parse_array_agg ( array_agg, schema) ,
24432448
2449+ SQLExpr :: PercentileCont ( percentile_cont) => self . parse_percentile_cont ( percentile_cont, schema) ,
2450+
24442451 _ => Err ( DataFusionError :: NotImplemented ( format ! (
24452452 "Unsupported ast node {:?} in sqltorel" ,
24462453 sql
@@ -2494,6 +2501,42 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
24942501 } )
24952502 }
24962503
2504+ fn parse_percentile_cont (
2505+ & self ,
2506+ percentile_cont : PercentileCont ,
2507+ input_schema : & DFSchema ,
2508+ ) -> Result < Expr > {
2509+ let PercentileCont { expr, within_group } = percentile_cont;
2510+
2511+ // Some dialects have special syntax for percentile_cont. DataFusion only supports it like a function.
2512+ let expr = self . sql_expr_to_logical_expr ( * expr, input_schema) ?;
2513+ let ( order_by_expr, asc, nulls_first) =
2514+ match self . order_by_to_sort_expr ( * within_group, input_schema, false ) ? {
2515+ Expr :: Sort {
2516+ expr,
2517+ asc,
2518+ nulls_first,
2519+ } => ( expr, asc, nulls_first) ,
2520+ _ => {
2521+ return Err ( DataFusionError :: Internal (
2522+ "PercentileCont expected Sort expression in ORDER BY" . to_string ( ) ,
2523+ ) )
2524+ }
2525+ } ;
2526+ let asc_expr = Expr :: Literal ( ScalarValue :: Boolean ( Some ( asc) ) ) ;
2527+ let nulls_first_expr = Expr :: Literal ( ScalarValue :: Boolean ( Some ( nulls_first) ) ) ;
2528+
2529+ let args = vec ! [ expr, * order_by_expr, asc_expr, nulls_first_expr] ;
2530+ // next, aggregate built-ins
2531+ let fun = aggregates:: AggregateFunction :: PercentileCont ;
2532+
2533+ Ok ( Expr :: AggregateFunction {
2534+ fun,
2535+ distinct : false ,
2536+ args,
2537+ } )
2538+ }
2539+
24972540 fn function_args_to_expr (
24982541 & self ,
24992542 args : Vec < FunctionArg > ,
@@ -4133,6 +4176,15 @@ mod tests {
41334176 quick_test ( sql, expected) ;
41344177 }
41354178
4179+ #[ test]
4180+ fn select_percentile_cont ( ) {
4181+ let sql = "SELECT percentile_cont(0.5) WITHIN GROUP (ORDER BY age) FROM person" ;
4182+ let expected = "Projection: #PERCENTILECONT(Float64(0.5),person.age,Boolean(true),Boolean(false))\
4183+ \n Aggregate: groupBy=[[]], aggr=[[PERCENTILECONT(Float64(0.5), #person.age, Boolean(true), Boolean(false))]]\
4184+ \n TableScan: person projection=None";
4185+ quick_test ( sql, expected) ;
4186+ }
4187+
41364188 #[ test]
41374189 fn select_scalar_func ( ) {
41384190 let sql = "SELECT sqrt(age) FROM person" ;
0 commit comments