Fix a performance regression in 8.2: optimization of MIN/MAX into indexscans
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 6 Feb 2007 06:50:26 +0000 (06:50 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 6 Feb 2007 06:50:26 +0000 (06:50 +0000)
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

index bce3b1ac442879f77697f5545d09c5c84ce07b0a..77ad0176db256f448ba06ee4d74fdcedf63d60a1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.25 2007/01/09 02:14:13 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.26 2007/02/06 06:50:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -70,6 +70,7 @@ Plan *
 optimize_minmax_aggregates(PlannerInfo *root, List *tlist, Path *best_path)
 {
    Query      *parse = root->parse;
+   FromExpr   *jtnode;
    RangeTblRef *rtr;
    RangeTblEntry *rte;
    RelOptInfo *rel;
@@ -102,14 +103,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;