Describe the bug
With datafusion.optimizer.enable_window_topn = true, a query whose filter is rn < 1 (or the flipped 1 > rn) over a partitioned ROW_NUMBER()/RANK() panics:
thread '...' panicked at datafusion/physical-plan/src/topk/mod.rs:1294:
PartitionedTopK requires k > 0
ROW_NUMBER()/RANK() are always >= 1, so rn < 1 matches no rows and the correct result is an empty relation — it should not panic. With the optimization disabled the same query correctly returns no rows.
To Reproduce
SET datafusion.optimizer.enable_window_topn = true;
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY pk ORDER BY val) AS rn
FROM t
) WHERE rn < 1; -- panics; also `WHERE 1 > rn`
Root cause
The WindowTopN rule's extract_window_limit maps rn < K to a fetch of K - 1 (and the flipped K > rn likewise). For K = 1 the fetch is 0, which is passed to PartitionedTopKExec::try_new, whose assert!(k > 0) panics.
Expected behavior
rn < 1 / 1 > rn should return an empty result without panicking (matching the enable_window_topn = false behavior).
Additional context
The fix is to skip the rewrite when the computed fetch is 0 and let the regular FilterExec produce the empty result.
Describe the bug
With
datafusion.optimizer.enable_window_topn = true, a query whose filter isrn < 1(or the flipped1 > rn) over a partitionedROW_NUMBER()/RANK()panics:ROW_NUMBER()/RANK()are always>= 1, sorn < 1matches no rows and the correct result is an empty relation — it should not panic. With the optimization disabled the same query correctly returns no rows.To Reproduce
Root cause
The
WindowTopNrule'sextract_window_limitmapsrn < Kto a fetch ofK - 1(and the flippedK > rnlikewise). ForK = 1the fetch is0, which is passed toPartitionedTopKExec::try_new, whoseassert!(k > 0)panics.Expected behavior
rn < 1/1 > rnshould return an empty result without panicking (matching theenable_window_topn = falsebehavior).Additional context
The fix is to skip the rewrite when the computed fetch is
0and let the regularFilterExecproduce the empty result.