0001-Remove-incorrect-assertion-for-childrel-rows-in-orde.patch

application/octet-stream

Filename: 0001-Remove-incorrect-assertion-for-childrel-rows-in-orde.patch
Type: application/octet-stream
Part: 0
Message: Re: BUG #19102: Assertion failure in generate_orderedappend_paths with aggregate pushdown

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch 0001
Subject: Remove incorrect assertion for childrel rows in ordered append paths
File+
src/backend/optimizer/path/allpaths.c 1 7
src/test/regress/expected/partition_aggregate.out 16 0
src/test/regress/sql/partition_aggregate.sql 9 0
From bb8ecc7e7bac169d0cdc5e4b2bb8a18665b4b936 Mon Sep 17 00:00:00 2001
From: Kuntal Ghosh <kuntalgh@amazon.com>
Date: Mon, 3 Nov 2025 04:45:01 +0000
Subject: [PATCH] Remove incorrect assertion for childrel rows in ordered
 append paths

iThe assertion that childrel->rows > 0 is incorrect when aggregates are
pushed down below merge append, as childrel may be an upperrel in such
cases. Use clamp_row_est() to safely handle zero or near-zero row
estimates when calculating path fractions.
---
 src/backend/optimizer/path/allpaths.c            |  8 +-------
 .../regress/expected/partition_aggregate.out     | 16 ++++++++++++++++
 src/test/regress/sql/partition_aggregate.sql     |  9 +++++++++
 3 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 9c6436eb72f..f9eff4d45c6 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -1976,15 +1976,9 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel,
 			{
 				double		path_fraction = root->tuple_fraction;
 
-				/*
-				 * Merge Append considers only live children relations.  Dummy
-				 * relations must be filtered out before.
-				 */
-				Assert(childrel->rows > 0);
-
 				/* Convert absolute limit to a path fraction */
 				if (path_fraction >= 1.0)
-					path_fraction /= childrel->rows;
+					path_fraction /= clamp_row_est(childrel->rows);
 
 				cheapest_fractional =
 					get_cheapest_fractional_path_for_pathkeys(childrel->pathlist,
diff --git a/src/test/regress/expected/partition_aggregate.out b/src/test/regress/expected/partition_aggregate.out
index fc84929a002..992d016407f 100644
--- a/src/test/regress/expected/partition_aggregate.out
+++ b/src/test/regress/expected/partition_aggregate.out
@@ -930,6 +930,22 @@ SELECT a, c, sum(b), avg(c), count(*) FROM pagg_tab_m GROUP BY (a+b)/2, 2, 1 HAV
  20 | 40 |  50 | 40.0000000000000000 |     5
 (6 rows)
 
+-- Test with relation having interesting order
+CREATE TABLE pagg_tab3 (id BIGINT, PRIMARY KEY (id)) PARTITION BY RANGE (id);
+CREATE TABLE pagg_tab3_0 PARTITION OF pagg_tab3 FOR VALUES FROM ('0') TO ('1000');
+CREATE TABLE pagg_tab3_1 PARTITION OF pagg_tab3 FOR VALUES FROM ('1000') TO ('2000');
+SET enable_partitionwise_aggregate = true;
+EXPLAIN (COSTS OFF)  SELECT count(*)  FROM pagg_tab3 x  GROUP BY x.id  ORDER BY x.id DESC  LIMIT 2;
+                                      QUERY PLAN                                      
+--------------------------------------------------------------------------------------
+ Limit
+   ->  GroupAggregate
+         Group Key: x.id
+         ->  Append
+               ->  Index Only Scan Backward using pagg_tab3_1_pkey on pagg_tab3_1 x_2
+               ->  Index Only Scan Backward using pagg_tab3_0_pkey on pagg_tab3_0 x_1
+(6 rows)
+
 -- Test with multi-level partitioning scheme
 CREATE TABLE pagg_tab_ml (a int, b int, c text) PARTITION BY RANGE(a);
 CREATE TABLE pagg_tab_ml_p1 PARTITION OF pagg_tab_ml FOR VALUES FROM (0) TO (12);
diff --git a/src/test/regress/sql/partition_aggregate.sql b/src/test/regress/sql/partition_aggregate.sql
index 124cc260461..31030c9b76f 100644
--- a/src/test/regress/sql/partition_aggregate.sql
+++ b/src/test/regress/sql/partition_aggregate.sql
@@ -202,6 +202,15 @@ EXPLAIN (COSTS OFF)
 SELECT a, c, sum(b), avg(c), count(*) FROM pagg_tab_m GROUP BY (a+b)/2, 2, 1 HAVING sum(b) = 50 AND avg(c) > 25 ORDER BY 1, 2, 3;
 SELECT a, c, sum(b), avg(c), count(*) FROM pagg_tab_m GROUP BY (a+b)/2, 2, 1 HAVING sum(b) = 50 AND avg(c) > 25 ORDER BY 1, 2, 3;
 
+-- Test with relation having interesting order
+CREATE TABLE pagg_tab3 (id BIGINT, PRIMARY KEY (id)) PARTITION BY RANGE (id);
+CREATE TABLE pagg_tab3_0 PARTITION OF pagg_tab3 FOR VALUES FROM ('0') TO ('1000');
+CREATE TABLE pagg_tab3_1 PARTITION OF pagg_tab3 FOR VALUES FROM ('1000') TO ('2000');
+
+SET enable_partitionwise_aggregate = true;
+
+EXPLAIN (COSTS OFF)  SELECT count(*)  FROM pagg_tab3 x  GROUP BY x.id  ORDER BY x.id DESC  LIMIT 2;
+
 
 -- Test with multi-level partitioning scheme
 
-- 
2.47.3