min_max.diff.no-cfbot
text/plain
Filename: min_max.diff.no-cfbot
Type: text/plain
Part: 0
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;