From a95abdf8564e36b7c9de62423fcbe039fcc20efa Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 6 Feb 2007 06:50:33 +0000 Subject: [PATCH] Fix a performance regression in 8.2: optimization of MIN/MAX into indexscans had stopped working for tables buried inside views or sub-selects. This is because I had gotten rid of the simplify_jointree() preprocessing step, and optimize_minmax_aggregates() wasn't smart enough to deal with a non-canonical FromExpr. Per gripe from Bill Howe. --- src/backend/optimizer/plan/planagg.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c index e64340ed21..1b929caa65 100644 --- a/src/backend/optimizer/plan/planagg.c +++ b/src/backend/optimizer/plan/planagg.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.22 2006/10/04 00:29:54 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.22.2.1 2007/02/06 06:50:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -69,6 +69,7 @@ Plan * optimize_minmax_aggregates(PlannerInfo *root, List *tlist, Path *best_path) { Query *parse = root->parse; + FromExpr *jtnode; RangeTblRef *rtr; RangeTblEntry *rte; RelOptInfo *rel; @@ -101,14 +102,19 @@ optimize_minmax_aggregates(PlannerInfo *root, List *tlist, Path *best_path) * We also restrict the query to reference exactly one table, since join * conditions can't be handled reasonably. (We could perhaps handle a * query containing cartesian-product joins, but it hardly seems worth the - * trouble.) + * trouble.) However, the single real table could be buried in several + * levels of FromExpr. */ - Assert(parse->jointree != NULL && IsA(parse->jointree, FromExpr)); - if (list_length(parse->jointree->fromlist) != 1) - return NULL; - rtr = (RangeTblRef *) linitial(parse->jointree->fromlist); - if (!IsA(rtr, RangeTblRef)) + jtnode = parse->jointree; + while (IsA(jtnode, FromExpr)) + { + if (list_length(jtnode->fromlist) != 1) + return NULL; + jtnode = linitial(jtnode->fromlist); + } + if (!IsA(jtnode, RangeTblRef)) return NULL; + rtr = (RangeTblRef *) jtnode; rte = rt_fetch(rtr->rtindex, parse->rtable); if (rte->rtekind != RTE_RELATION || rte->inh) return NULL;