diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c index 64605be31781f9e841f02ea005e9220a721e45aa..c78f32e850bb2bf884a63971898de2c6a88675ea 100644 --- a/src/backend/optimizer/plan/planagg.c +++ b/src/backend/optimizer/plan/planagg.c @@ -125,16 +125,24 @@ preprocess_minmax_aggregates(PlannerInfo *root) return; jtnode = linitial(jtnode->fromlist); } - if (!IsA(jtnode, RangeTblRef)) + if (IsA(jtnode, JoinExpr) && jtnode->fromlist == NIL && root->join_info_list == NIL && IsA(jtnode->quals, RangeTblRef)) + rtr = (RangeTblRef *) (jtnode->quals); + else if (IsA(jtnode, RangeTblRef)) + { + rtr = (RangeTblRef *) jtnode; + } + else + return; + + if(root->simple_rel_array[rtr->rtindex] == NULL) return; - rtr = (RangeTblRef *) jtnode; + rte = planner_rt_fetch(rtr->rtindex, root); + if (rte->rtekind == RTE_RELATION) - /* ordinary relation, ok */ ; + /* ordinary relation, ok */ ; else if (rte->rtekind == RTE_SUBQUERY && rte->inh) - /* flattened UNION ALL subquery, ok */ ; - else - return; + /* flattened UNION ALL subquery, ok */ ; /* * Examine all the aggregates and verify all are MIN/MAX aggregates. Stop @@ -345,6 +353,7 @@ build_minmax_path(PlannerInfo *root, MinMaxAggInfo *mminfo, subroot->init_plans = NIL; subroot->agginfos = NIL; subroot->aggtransinfos = NIL; + subroot->eq_classes = NIL; subroot->parse = parse = copyObject(root->parse); IncrementVarSublevelsUp((Node *) parse, 1, 1); diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c index ade23fd9d56d2a96ff62ceeeea67869aa96e368a..563e689dfc0c3f2e8aad2dea367a928e0467598a 100644 --- a/src/backend/optimizer/plan/planmain.c +++ b/src/backend/optimizer/plan/planmain.c @@ -78,6 +78,7 @@ query_planner(PlannerInfo *root, root->placeholder_array_size = 0; root->fkey_list = NIL; root->initial_rels = NIL; + root->placeholdersFrozen = false; /* * Set up arrays for accessing base relations and AppendRelInfos. diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 8a474a50be73c2a73607ee2c775758ac95999b79..9627ea2aed196b3bcb46ff82f2a9d6535473a1d0 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -1535,15 +1535,6 @@ grouping_planner(PlannerInfo *root, double tuple_fraction, parse->hasWindowFuncs = false; } - /* - * Preprocess MIN/MAX aggregates, if any. Note: be careful about - * adding logic between here and the query_planner() call. Anything - * that is needed in MIN/MAX-optimizable cases will have to be - * duplicated in planagg.c. - */ - if (parse->hasAggs) - preprocess_minmax_aggregates(root); - /* * Figure out whether there's a hard limit on the number of rows that * query_planner's result subplan needs to return. Even if we know a @@ -1612,6 +1603,15 @@ grouping_planner(PlannerInfo *root, double tuple_fraction, sort_input_target_parallel_safe = final_target_parallel_safe; } + /* + * Preprocess MIN/MAX aggregates, if any. Note: be careful about + * adding logic between here and the query_planner() call. Anything + * that is needed in MIN/MAX-optimizable cases will have to be + * duplicated in planagg.c. + */ + if (parse->hasAggs) + preprocess_minmax_aggregates(root); + /* * If we have window functions to deal with, the output from any * grouping step needs to be what the window functions want; diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out index f2fb66388cc91934bf90faeaea7bc06751b14670..4cab1539cffd075f870d04b2639a33a33cbb8f2d 100644 --- a/src/test/regress/expected/aggregates.out +++ b/src/test/regress/expected/aggregates.out @@ -1329,6 +1329,24 @@ from int4_tbl t0; (5 rows) rollback; +--Check min/max optimization for join expressions +create unique index tenk1_unique1_idx on tenk1(unique1); +create index tenk1_unique2_idx on tenk1(unique2); +create unique index INT4_TBL_f1_idx on INT4_TBL(f1); +explain (COSTS OFF) +select min(t1.unique2) from tenk1 t1 left join INT4_TBL t2 on t1.unique1 = t2.f1; + QUERY PLAN +-------------------------------------------------------------- + Result + InitPlan 1 + -> Limit + -> Index Scan using tenk1_unique2_idx on tenk1 t1 + Index Cond: (unique2 IS NOT NULL) +(5 rows) + +DROP INDEX tenk1_unique1_idx; +DROP INDEX tenk1_unique2_idx; +DROP INDEX INT4_TBL_f1_idx; -- check for correct detection of nested-aggregate errors select max(min(unique1)) from tenk1; ERROR: aggregate function calls cannot be nested diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql index 77168bcc7447c5d8dec11cd133c9355f82b33235..9b01b01e928af84f98484b17fd8c66134fa33a77 100644 --- a/src/test/regress/sql/aggregates.sql +++ b/src/test/regress/sql/aggregates.sql @@ -452,6 +452,16 @@ select f1, (select distinct min(t1.f1) from int4_tbl t1 where t1.f1 = t0.f1) from int4_tbl t0; rollback; +--Check min/max optimization for join expressions +create unique index tenk1_unique1_idx on tenk1(unique1); +create index tenk1_unique2_idx on tenk1(unique2); +create unique index INT4_TBL_f1_idx on INT4_TBL(f1); +explain (COSTS OFF) +select min(t1.unique2) from tenk1 t1 left join INT4_TBL t2 on t1.unique1 = t2.f1; +DROP INDEX tenk1_unique1_idx; +DROP INDEX tenk1_unique2_idx; +DROP INDEX INT4_TBL_f1_idx; + -- check for correct detection of nested-aggregate errors select max(min(unique1)) from tenk1; select (select max(min(unique1)) from int8_tbl) from tenk1;