Fix inappropriate attempt to push down qual clauses into a view that
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 3 Feb 2001 21:17:52 +0000 (21:17 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 3 Feb 2001 21:17:52 +0000 (21:17 +0000)
has UNION/INTERSECT/EXCEPT operations.  Per bug report from Ferrier.

src/backend/optimizer/path/allpaths.c

index fa4e1dfd90ad81e329dd5d15b925066524168a7e..7d44c4dcfa070b5dbf48d39ae48f313062e2986d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.70 2001/01/24 19:42:57 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.71 2001/02/03 21:17:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -101,8 +101,6 @@ set_base_rel_pathlists(Query *root)
        if (rel->issubquery)
        {
            /* Subquery --- generate a separate plan for it */
-           List       *upperrestrictlist;
-           List       *lst;
 
            /*
             * If there are any restriction clauses that have been attached
@@ -118,6 +116,11 @@ set_base_rel_pathlists(Query *root)
             * Currently, we do not push down clauses that contain subselects,
             * mainly because I'm not sure it will work correctly (the
             * subplan hasn't yet transformed sublinks to subselects).
+            * Also, if the subquery contains set ops (UNION/INTERSECT/EXCEPT)
+            * we do not push down any qual clauses, since the planner doesn't
+            * support quals at the top level of a setop.  (With suitable
+            * analysis we could try to push the quals down into the component
+            * queries of the setop, but getting it right is not trivial.)
             * Non-pushed-down clauses will get evaluated as qpquals of
             * the SubqueryScan node.
             *
@@ -125,41 +128,48 @@ set_base_rel_pathlists(Query *root)
             * decision not to push down, because it'd result in a worse
             * plan?
             */
-           upperrestrictlist = NIL;
-           foreach(lst, rel->baserestrictinfo)
+           if (rte->subquery->setOperations == NULL)
            {
-               RestrictInfo   *rinfo = (RestrictInfo *) lfirst(lst);
-               Node           *clause = (Node *) rinfo->clause;
+               /* OK to consider pushing down individual quals */
+               List       *upperrestrictlist = NIL;
+               List       *lst;
 
-               if (contain_subplans(clause))
+               foreach(lst, rel->baserestrictinfo)
                {
-                   /* Keep it in the upper query */
-                   upperrestrictlist = lappend(upperrestrictlist, rinfo);
-               }
-               else
-               {
-                   /*
-                    * We need to replace Vars in the clause (which must
-                    * refer to outputs of the subquery) with copies of the
-                    * subquery's targetlist expressions.  Note that at this
-                    * point, any uplevel Vars in the clause should have been
-                    * replaced with Params, so they need no work.
-                    */
-                   clause = ResolveNew(clause, rti, 0,
-                                       rte->subquery->targetList,
-                                       CMD_SELECT, 0);
-                   rte->subquery->havingQual =
-                       make_and_qual(rte->subquery->havingQual,
-                                     clause);
-                   /*
-                    * We need not change the subquery's hasAggs or
-                    * hasSublinks flags, since we can't be pushing down
-                    * any aggregates that weren't there before, and we
-                    * don't push down subselects at all.
-                    */
+                   RestrictInfo   *rinfo = (RestrictInfo *) lfirst(lst);
+                   Node           *clause = (Node *) rinfo->clause;
+
+                   if (contain_subplans(clause))
+                   {
+                       /* Keep it in the upper query */
+                       upperrestrictlist = lappend(upperrestrictlist, rinfo);
+                   }
+                   else
+                   {
+                       /*
+                        * We need to replace Vars in the clause (which must
+                        * refer to outputs of the subquery) with copies of
+                        * the subquery's targetlist expressions.  Note that
+                        * at this point, any uplevel Vars in the clause
+                        * should have been replaced with Params, so they
+                        * need no work.
+                        */
+                       clause = ResolveNew(clause, rti, 0,
+                                           rte->subquery->targetList,
+                                           CMD_SELECT, 0);
+                       rte->subquery->havingQual =
+                           make_and_qual(rte->subquery->havingQual,
+                                         clause);
+                       /*
+                        * We need not change the subquery's hasAggs or
+                        * hasSublinks flags, since we can't be pushing down
+                        * any aggregates that weren't there before, and we
+                        * don't push down subselects at all.
+                        */
+                   }
                }
+               rel->baserestrictinfo = upperrestrictlist;
            }
-           rel->baserestrictinfo = upperrestrictlist;
 
            /* Generate the plan for the subquery */
            rel->subplan = subquery_planner(rte->subquery,