@@ -79,8 +79,7 @@ use datafusion::{
7979 runtime_env:: RuntimeEnv ,
8080 } ,
8181 logical_expr:: {
82- Expr , Extension , LogicalPlan , Sort , UserDefinedLogicalNode ,
83- UserDefinedLogicalNodeCore ,
82+ Expr , Extension , LogicalPlan , UserDefinedLogicalNode , UserDefinedLogicalNodeCore ,
8483 } ,
8584 optimizer:: { OptimizerConfig , OptimizerRule } ,
8685 physical_expr:: EquivalenceProperties ,
@@ -519,30 +518,49 @@ impl OptimizerRule for TopKOptimizerRule {
519518 // Note: this code simply looks for the pattern of a Limit followed by a
520519 // Sort and replaces it by a TopK node. It does not handle many
521520 // edge cases (e.g multiple sort columns, sort ASC / DESC), etc.
522- let LogicalPlan :: Limit ( ref limit) = plan else {
523- return Ok ( Transformed :: no ( plan) ) ;
524- } ;
525- let FetchType :: Literal ( Some ( fetch) ) = limit. get_fetch_type ( ) ? else {
526- return Ok ( Transformed :: no ( plan) ) ;
527- } ;
528-
529- if let LogicalPlan :: Sort ( Sort {
530- ref expr,
531- ref input,
532- ..
533- } ) = limit. input . as_ref ( )
534- {
535- if expr. len ( ) == 1 {
536- // we found a sort with a single sort expr, replace with a a TopK
537- return Ok ( Transformed :: yes ( LogicalPlan :: Extension ( Extension {
538- node : Arc :: new ( TopKPlanNode {
539- k : fetch,
540- input : input. as_ref ( ) . clone ( ) ,
541- expr : expr[ 0 ] . clone ( ) ,
542- invariant_mock : self . invariant_mock . clone ( ) ,
543- } ) ,
544- } ) ) ) ;
521+ //
522+ // Because Limit > Sort can get optimized to Sort, fetch in the first pass, we
523+ // also support bare Sort (as we are running in ApplyOrder::TopDown mode).
524+ let expr: & Vec < SortExpr > ;
525+ let input: & Arc < LogicalPlan > ;
526+ let fetch: usize ;
527+ match plan {
528+ LogicalPlan :: Limit ( ref limit) => {
529+ let FetchType :: Literal ( Some ( limit_fetch) ) = limit. get_fetch_type ( ) ?
530+ else {
531+ return Ok ( Transformed :: no ( plan) ) ;
532+ } ;
533+ let LogicalPlan :: Sort ( ref sort) = limit. input . as_ref ( ) else {
534+ return Ok ( Transformed :: no ( plan) ) ;
535+ } ;
536+ expr = & sort. expr ;
537+ input = & sort. input ;
538+ fetch = limit_fetch;
539+ }
540+ LogicalPlan :: Sort ( ref sort) => {
541+ let Some ( sort_fetch) = sort. fetch else {
542+ return Ok ( Transformed :: no ( plan) ) ;
543+ } ;
544+
545+ expr = & sort. expr ;
546+ input = & sort. input ;
547+ fetch = sort_fetch;
545548 }
549+ _ => {
550+ return Ok ( Transformed :: no ( plan) ) ;
551+ }
552+ }
553+
554+ if expr. len ( ) == 1 {
555+ // we found a sort with a single sort expr, replace with a a TopK
556+ return Ok ( Transformed :: yes ( LogicalPlan :: Extension ( Extension {
557+ node : Arc :: new ( TopKPlanNode {
558+ k : fetch,
559+ input : input. as_ref ( ) . clone ( ) ,
560+ expr : expr[ 0 ] . clone ( ) ,
561+ invariant_mock : self . invariant_mock . clone ( ) ,
562+ } ) ,
563+ } ) ) ) ;
546564 }
547565
548566 Ok ( Transformed :: no ( plan) )
0 commit comments