v3-0001-Fix-assertion-failure-in-generate_orderedappend_p.patch
application/octet-stream
Filename: v3-0001-Fix-assertion-failure-in-generate_orderedappend_p.patch
Type: application/octet-stream
Part: 0
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 v3-0001
Subject: Fix assertion failure in generate_orderedappend_paths()
| File | + | − |
|---|---|---|
| src/backend/optimizer/path/allpaths.c | 2 | 14 |
| src/backend/optimizer/path/pathkeys.c | 7 | 2 |
| src/backend/optimizer/plan/planagg.c | 1 | 1 |
| src/include/optimizer/paths.h | 1 | 1 |
| src/test/regress/expected/partition_aggregate.out | 31 | 0 |
| src/test/regress/sql/partition_aggregate.sql | 5 | 0 |
From c10fa47d30783412edb5d26e6f9f77d994755ed9 Mon Sep 17 00:00:00 2001
From: Alexander Korotkov <akorotkov@postgresql.org>
Date: Wed, 5 Nov 2025 01:40:03 +0200
Subject: [PATCH v3] Fix assertion failure in generate_orderedappend_paths()
Reported-by:
Bug:
Discussion:
Author:
Co-authored-by:
Reviewed-by:
Tested-by:
Backpatch-through:
---
src/backend/optimizer/path/allpaths.c | 16 ++--------
src/backend/optimizer/path/pathkeys.c | 9 ++++--
src/backend/optimizer/plan/planagg.c | 2 +-
src/include/optimizer/paths.h | 2 +-
.../regress/expected/partition_aggregate.out | 31 +++++++++++++++++++
src/test/regress/sql/partition_aggregate.sql | 5 +++
6 files changed, 47 insertions(+), 18 deletions(-)
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 9c6436eb72f..b93e00f6cb3 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -1974,23 +1974,11 @@ generate_orderedappend_paths(PlannerInfo *root, RelOptInfo *rel,
*/
if (root->tuple_fraction > 0)
{
- 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;
-
cheapest_fractional =
- get_cheapest_fractional_path_for_pathkeys(childrel->pathlist,
+ get_cheapest_fractional_path_for_pathkeys(childrel,
pathkeys,
NULL,
- path_fraction);
+ root->tuple_fraction);
/*
* If we found no path with matching pathkeys, use the
diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c
index 139fa1f875a..630aa598747 100644
--- a/src/backend/optimizer/path/pathkeys.c
+++ b/src/backend/optimizer/path/pathkeys.c
@@ -663,15 +663,20 @@ get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
* 'fraction' is the fraction of the total tuples expected to be retrieved
*/
Path *
-get_cheapest_fractional_path_for_pathkeys(List *paths,
+get_cheapest_fractional_path_for_pathkeys(RelOptInfo *rel,
List *pathkeys,
Relids required_outer,
double fraction)
{
+ Path *best_path = rel->cheapest_total_path;
Path *matched_path = NULL;
ListCell *l;
- foreach(l, paths)
+ /* Convert absolute # of tuples to a fraction; no need to clamp to 0..1 */
+ if (fraction >= 1.0 && best_path->rows > 0)
+ fraction /= best_path->rows;
+
+ foreach(l, rel->pathlist)
{
Path *path = (Path *) lfirst(l);
diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c
index a2ac58d246e..0fa91cd6b5f 100644
--- a/src/backend/optimizer/plan/planagg.c
+++ b/src/backend/optimizer/plan/planagg.c
@@ -443,7 +443,7 @@ build_minmax_path(PlannerInfo *root, MinMaxAggInfo *mminfo,
path_fraction = 1.0;
sorted_path =
- get_cheapest_fractional_path_for_pathkeys(final_rel->pathlist,
+ get_cheapest_fractional_path_for_pathkeys(final_rel,
subroot->query_pathkeys,
NULL,
path_fraction);
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index f6a62df0b43..23f65176eb4 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -223,7 +223,7 @@ extern Path *get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
Relids required_outer,
CostSelector cost_criterion,
bool require_parallel_safe);
-extern Path *get_cheapest_fractional_path_for_pathkeys(List *paths,
+extern Path *get_cheapest_fractional_path_for_pathkeys(RelOptInfo *rel,
List *pathkeys,
Relids required_outer,
double fraction);
diff --git a/src/test/regress/expected/partition_aggregate.out b/src/test/regress/expected/partition_aggregate.out
index fc84929a002..c30304b99c7 100644
--- a/src/test/regress/expected/partition_aggregate.out
+++ b/src/test/regress/expected/partition_aggregate.out
@@ -339,6 +339,37 @@ SELECT a FROM pagg_tab WHERE a < 3 GROUP BY a ORDER BY 1;
2
(3 rows)
+-- Test partitionwise aggregation with ordered append path built from fractional paths
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM pagg_tab GROUP BY c ORDER BY c LIMIT 1;
+ QUERY PLAN
+------------------------------------------------------------
+ Limit
+ -> Merge Append
+ Sort Key: pagg_tab.c
+ -> GroupAggregate
+ Group Key: pagg_tab.c
+ -> Sort
+ Sort Key: pagg_tab.c
+ -> Seq Scan on pagg_tab_p1 pagg_tab
+ -> GroupAggregate
+ Group Key: pagg_tab_1.c
+ -> Sort
+ Sort Key: pagg_tab_1.c
+ -> Seq Scan on pagg_tab_p2 pagg_tab_1
+ -> GroupAggregate
+ Group Key: pagg_tab_2.c
+ -> Sort
+ Sort Key: pagg_tab_2.c
+ -> Seq Scan on pagg_tab_p3 pagg_tab_2
+(18 rows)
+
+SELECT count(*) FROM pagg_tab GROUP BY c ORDER BY c LIMIT 1;
+ count
+-------
+ 250
+(1 row)
+
RESET enable_hashagg;
-- ROLLUP, partitionwise aggregation does not apply
EXPLAIN (COSTS OFF)
diff --git a/src/test/regress/sql/partition_aggregate.sql b/src/test/regress/sql/partition_aggregate.sql
index 124cc260461..7c725e2663a 100644
--- a/src/test/regress/sql/partition_aggregate.sql
+++ b/src/test/regress/sql/partition_aggregate.sql
@@ -76,6 +76,11 @@ EXPLAIN (COSTS OFF)
SELECT a FROM pagg_tab WHERE a < 3 GROUP BY a ORDER BY 1;
SELECT a FROM pagg_tab WHERE a < 3 GROUP BY a ORDER BY 1;
+-- Test partitionwise aggregation with ordered append path built from fractional paths
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM pagg_tab GROUP BY c ORDER BY c LIMIT 1;
+SELECT count(*) FROM pagg_tab GROUP BY c ORDER BY c LIMIT 1;
+
RESET enable_hashagg;
-- ROLLUP, partitionwise aggregation does not apply
--
2.39.5 (Apple Git-154)