diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c index ef0c20f8f1..b85f48d6ff 100644 --- a/src/backend/optimizer/plan/planagg.c +++ b/src/backend/optimizer/plan/planagg.c @@ -39,6 +39,7 @@ #include "optimizer/planmain.h" #include "optimizer/planner.h" #include "optimizer/subselect.h" +#include "optimizer/tlist.h" #include "parser/parsetree.h" #include "parser/parse_clause.h" #include "utils/lsyscache.h" @@ -545,7 +546,27 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *mminfo) */ plan = create_plan(subroot, mminfo->path); - plan->targetlist = subparse->targetList; + /* + * If the top-level plan node is one that cannot do expression evaluation + * and its existing target list isn't already what we need, we must insert + * a Result node to project the desired tlist. + */ + if (!is_projection_capable_plan(plan) && + !tlist_same_exprs(subparse->targetList, plan->targetlist)) + { + plan = (Plan *) make_result(subroot, + subparse->targetList, + NULL, + plan); + } + else + { + /* + * Otherwise, just replace the subplan's flat tlist with the desired + * tlist. + */ + plan->targetlist = subparse->targetList; + } plan = (Plan *) make_limit(plan, subparse->limitOffset, diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out index a2ef7ef7cd..bfe67337b7 100644 --- a/src/test/regress/expected/inherit.out +++ b/src/test/regress/expected/inherit.out @@ -1207,6 +1207,28 @@ select * from matest0 order by 1-id; 1 | Test 1 (6 rows) +explain (verbose, costs off) select min(1-id) from matest0; + QUERY PLAN +---------------------------------------- + Aggregate + Output: min((1 - matest0.id)) + -> Append + -> Seq Scan on public.matest0 + Output: matest0.id + -> Seq Scan on public.matest1 + Output: matest1.id + -> Seq Scan on public.matest2 + Output: matest2.id + -> Seq Scan on public.matest3 + Output: matest3.id +(11 rows) + +select min(1-id) from matest0; + min +----- + -5 +(1 row) + reset enable_indexscan; set enable_seqscan = off; -- plan with fewest seqscans should be merge explain (verbose, costs off) select * from matest0 order by 1-id; @@ -1238,6 +1260,42 @@ select * from matest0 order by 1-id; 1 | Test 1 (6 rows) +explain (verbose, costs off) select min(1-id) from matest0; + QUERY PLAN +-------------------------------------------------------------------------- + Result + Output: $0 + InitPlan 1 (returns $0) + -> Limit + Output: ((1 - matest0.id)) + -> Result + Output: ((1 - matest0.id)) + -> Merge Append + Sort Key: ((1 - matest0.id)) + -> Index Scan using matest0i on public.matest0 + Output: matest0.id, (1 - matest0.id) + Index Cond: ((1 - matest0.id) IS NOT NULL) + -> Index Scan using matest1i on public.matest1 + Output: matest1.id, (1 - matest1.id) + Index Cond: ((1 - matest1.id) IS NOT NULL) + -> Sort + Output: matest2.id, ((1 - matest2.id)) + Sort Key: ((1 - matest2.id)) + -> Bitmap Heap Scan on public.matest2 + Output: matest2.id, (1 - matest2.id) + Filter: ((1 - matest2.id) IS NOT NULL) + -> Bitmap Index Scan on matest2_pkey + -> Index Scan using matest3i on public.matest3 + Output: matest3.id, (1 - matest3.id) + Index Cond: ((1 - matest3.id) IS NOT NULL) +(25 rows) + +select min(1-id) from matest0; + min +----- + -5 +(1 row) + reset enable_seqscan; drop table matest0 cascade; NOTICE: drop cascades to 3 other objects diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql index 86376554b0..747aa88666 100644 --- a/src/test/regress/sql/inherit.sql +++ b/src/test/regress/sql/inherit.sql @@ -382,11 +382,15 @@ insert into matest3 (name) values ('Test 6'); set enable_indexscan = off; -- force use of seqscan/sort, so no merge explain (verbose, costs off) select * from matest0 order by 1-id; select * from matest0 order by 1-id; +explain (verbose, costs off) select min(1-id) from matest0; +select min(1-id) from matest0; reset enable_indexscan; set enable_seqscan = off; -- plan with fewest seqscans should be merge explain (verbose, costs off) select * from matest0 order by 1-id; select * from matest0 order by 1-id; +explain (verbose, costs off) select min(1-id) from matest0; +select min(1-id) from matest0; reset enable_seqscan; drop table matest0 cascade;