You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
WITH ... AS MATERIALIZED returns wrong rows under ORDER BY ... LIMIT: top-k aggregation limits the shared CTE body #27219
ORDER BY x LIMIT n above a MATERIALIZED CTE whose body groups by x returns wrong rows, often none. The physical optimizer rule TopKAggregation puts the limit on the aggregate inside the CTE body, so the body keeps only n groups, and every reference to the CTE sees only those. With NOT MATERIALIZED the rows are right. The feature (#25580) is on branch-56, so 56.0.0 would ship with this.
To Reproduce
In datafusion-cli (the PostgreSQL dialect is needed to parse MATERIALIZED):
SETdatafusion.sql_parser.dialect ='PostgreSQL';
CREATETABLEtASSELECT value AS x FROM generate_series(1, 200);
-- Query 1SELECT*FROM (
WITH c AS MATERIALIZED (SELECT x FROM t GROUP BY x)
SELECT x FROM c WHERE x >100
) s ORDER BY x LIMIT3;
-- Query 2SELECT*FROM (
WITH c AS MATERIALIZED (SELECT x FROM t GROUP BY x)
SELECTc.x, m.nFROM c CROSS JOIN (SELECTcount(*) AS n FROM c) m
) s ORDER BY x LIMIT3;
Expected behavior
Query
DataFusion returns
Expected
1
no rows
101, 102, 103
2
(1, 3), (2, 3), (3, 3)
(1, 200), (2, 200), (3, 200)
With NOT MATERIALIZED, query 1 returns 101, 102, 103.
Additional context
EXPLAIN of query 1 shows the limit inside the body:
Cause: TopKAggregation::transform_sort walks down with transform_down (datafusion/physical-optimizer/src/topk_aggregation.rs:91) through every node whose cardinality_effect is Equal (:83). MaterializedCteExec reports Equal (datafusion/physical-plan/src/materialized_cte.rs:623) and lists the body as its first child (:534-536). So the walk enters the body, finds GROUP BY x matching the sort column x, and limits it. The body is not the node's output; the continuation is.
Fix direction: the walk should only enter children whose rows reach the node's output (for MaterializedCteExec, the continuation).
I'm not planning to fix this myself, so anyone is welcome to pick it up. Feel free to ping me with questions about the cause or when you'd like a review.
I'd like to work on this. I'll submit a PR that updates TopKAggregation so it does not traverse into the shared CTE body of MaterializedCteExec (only optimizing the continuation), and add regression tests in cte_materialized.slt.
Activity
Hrushikesh-ramilla commentedon Nov 8, 2026
I'd like to work on this. I'll submit a PR that updates
TopKAggregationso it does not traverse into the shared CTE body ofMaterializedCteExec(only optimizing the continuation), and add regression tests incte_materialized.slt.