@@ -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 } ;
@@ -1437,22 +1437,27 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
14371437
14381438 let order_by_rex = order_by
14391439 . into_iter ( )
1440- . map ( |e| self . order_by_to_sort_expr ( e, plan. schema ( ) ) )
1440+ . map ( |e| self . order_by_to_sort_expr ( e, plan. schema ( ) , true ) )
14411441 . collect :: < Result < Vec < _ > > > ( ) ?;
14421442
14431443 LogicalPlanBuilder :: from ( plan) . sort ( order_by_rex) ?. build ( )
14441444 }
14451445
14461446 /// convert sql OrderByExpr to Expr::Sort
1447- fn order_by_to_sort_expr ( & self , e : OrderByExpr , schema : & DFSchema ) -> Result < Expr > {
1447+ fn order_by_to_sort_expr (
1448+ & self ,
1449+ e : OrderByExpr ,
1450+ schema : & DFSchema ,
1451+ parse_indexes : bool ,
1452+ ) -> Result < Expr > {
14481453 let OrderByExpr {
14491454 asc,
14501455 expr,
14511456 nulls_first,
14521457 } = e;
14531458
14541459 let expr = match expr {
1455- SQLExpr :: Value ( Value :: Number ( v, _) ) => {
1460+ SQLExpr :: Value ( Value :: Number ( v, _) ) if parse_indexes => {
14561461 let field_index = v
14571462 . parse :: < usize > ( )
14581463 . map_err ( |err| DataFusionError :: Plan ( err. to_string ( ) ) ) ?;
@@ -2310,7 +2315,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
23102315 let order_by = window
23112316 . order_by
23122317 . into_iter ( )
2313- . map ( |e| self . order_by_to_sort_expr ( e, schema) )
2318+ . map ( |e| self . order_by_to_sort_expr ( e, schema, true ) )
23142319 . collect :: < Result < Vec < _ > > > ( ) ?;
23152320 let window_frame = window
23162321 . window_frame
@@ -2438,6 +2443,8 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
24382443
24392444 SQLExpr :: ArrayAgg ( array_agg) => self . parse_array_agg ( array_agg, schema) ,
24402445
2446+ SQLExpr :: PercentileCont ( percentile_cont) => self . parse_percentile_cont ( percentile_cont, schema) ,
2447+
24412448 _ => Err ( DataFusionError :: NotImplemented ( format ! (
24422449 "Unsupported ast node {:?} in sqltorel" ,
24432450 sql
@@ -2491,6 +2498,42 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
24912498 } )
24922499 }
24932500
2501+ fn parse_percentile_cont (
2502+ & self ,
2503+ percentile_cont : PercentileCont ,
2504+ input_schema : & DFSchema ,
2505+ ) -> Result < Expr > {
2506+ let PercentileCont { expr, within_group } = percentile_cont;
2507+
2508+ // Some dialects have special syntax for percentile_cont. DataFusion only supports it like a function.
2509+ let expr = self . sql_expr_to_logical_expr ( * expr, input_schema) ?;
2510+ let ( order_by_expr, asc, nulls_first) =
2511+ match self . order_by_to_sort_expr ( * within_group, input_schema, false ) ? {
2512+ Expr :: Sort {
2513+ expr,
2514+ asc,
2515+ nulls_first,
2516+ } => ( expr, asc, nulls_first) ,
2517+ _ => {
2518+ return Err ( DataFusionError :: Internal (
2519+ "PercentileCont expected Sort expression in ORDER BY" . to_string ( ) ,
2520+ ) )
2521+ }
2522+ } ;
2523+ let asc_expr = Expr :: Literal ( ScalarValue :: Boolean ( Some ( asc) ) ) ;
2524+ let nulls_first_expr = Expr :: Literal ( ScalarValue :: Boolean ( Some ( nulls_first) ) ) ;
2525+
2526+ let args = vec ! [ expr, * order_by_expr, asc_expr, nulls_first_expr] ;
2527+ // next, aggregate built-ins
2528+ let fun = aggregates:: AggregateFunction :: PercentileCont ;
2529+
2530+ Ok ( Expr :: AggregateFunction {
2531+ fun,
2532+ distinct : false ,
2533+ args,
2534+ } )
2535+ }
2536+
24942537 fn function_args_to_expr (
24952538 & self ,
24962539 args : Vec < FunctionArg > ,
@@ -4130,6 +4173,15 @@ mod tests {
41304173 quick_test ( sql, expected) ;
41314174 }
41324175
4176+ #[ test]
4177+ fn select_percentile_cont ( ) {
4178+ let sql = "SELECT percentile_cont(0.5) WITHIN GROUP (ORDER BY age) FROM person" ;
4179+ let expected = "Projection: #PERCENTILECONT(Float64(0.5),person.age,Boolean(true),Boolean(false))\
4180+ \n Aggregate: groupBy=[[]], aggr=[[PERCENTILECONT(Float64(0.5), #person.age, Boolean(true), Boolean(false))]]\
4181+ \n TableScan: person projection=None";
4182+ quick_test ( sql, expected) ;
4183+ }
4184+
41334185 #[ test]
41344186 fn select_scalar_func ( ) {
41354187 let sql = "SELECT sqrt(age) FROM person" ;
0 commit comments