88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.70 2001/01/24 19:42:57 momjian Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.71 2001/02/03 21:17:52 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -101,8 +101,6 @@ set_base_rel_pathlists(Query *root)
101101if (rel -> issubquery )
102102{
103103/* Subquery --- generate a separate plan for it */
104- List * upperrestrictlist ;
105- List * lst ;
106104
107105/*
108106 * If there are any restriction clauses that have been attached
@@ -118,48 +116,60 @@ set_base_rel_pathlists(Query *root)
118116 * Currently, we do not push down clauses that contain subselects,
119117 * mainly because I'm not sure it will work correctly (the
120118 * subplan hasn't yet transformed sublinks to subselects).
119+ * Also, if the subquery contains set ops (UNION/INTERSECT/EXCEPT)
120+ * we do not push down any qual clauses, since the planner doesn't
121+ * support quals at the top level of a setop. (With suitable
122+ * analysis we could try to push the quals down into the component
123+ * queries of the setop, but getting it right is not trivial.)
121124 * Non-pushed-down clauses will get evaluated as qpquals of
122125 * the SubqueryScan node.
123126 *
124127 * XXX Are there any cases where we want to make a policy
125128 * decision not to push down, because it'd result in a worse
126129 * plan?
127130 */
128- upperrestrictlist = NIL ;
129- foreach (lst ,rel -> baserestrictinfo )
131+ if (rte -> subquery -> setOperations == NULL )
130132{
131- RestrictInfo * rinfo = (RestrictInfo * )lfirst (lst );
132- Node * clause = (Node * )rinfo -> clause ;
133+ /* OK to consider pushing down individual quals */
134+ List * upperrestrictlist = NIL ;
135+ List * lst ;
133136
134- if ( contain_subplans ( clause ) )
137+ foreach ( lst , rel -> baserestrictinfo )
135138{
136- /* Keep it in the upper query */
137- upperrestrictlist = lappend (upperrestrictlist ,rinfo );
138- }
139- else
140- {
141- /*
142- * We need to replace Vars in the clause (which must
143- * refer to outputs of the subquery) with copies of the
144- * subquery's targetlist expressions. Note that at this
145- * point, any uplevel Vars in the clause should have been
146- * replaced with Params, so they need no work.
147- */
148- clause = ResolveNew (clause ,rti ,0 ,
149- rte -> subquery -> targetList ,
150- CMD_SELECT ,0 );
151- rte -> subquery -> havingQual =
152- make_and_qual (rte -> subquery -> havingQual ,
153- clause );
154- /*
155- * We need not change the subquery's hasAggs or
156- * hasSublinks flags, since we can't be pushing down
157- * any aggregates that weren't there before, and we
158- * don't push down subselects at all.
159- */
139+ RestrictInfo * rinfo = (RestrictInfo * )lfirst (lst );
140+ Node * clause = (Node * )rinfo -> clause ;
141+
142+ if (contain_subplans (clause ))
143+ {
144+ /* Keep it in the upper query */
145+ upperrestrictlist = lappend (upperrestrictlist ,rinfo );
146+ }
147+ else
148+ {
149+ /*
150+ * We need to replace Vars in the clause (which must
151+ * refer to outputs of the subquery) with copies of
152+ * the subquery's targetlist expressions. Note that
153+ * at this point, any uplevel Vars in the clause
154+ * should have been replaced with Params, so they
155+ * need no work.
156+ */
157+ clause = ResolveNew (clause ,rti ,0 ,
158+ rte -> subquery -> targetList ,
159+ CMD_SELECT ,0 );
160+ rte -> subquery -> havingQual =
161+ make_and_qual (rte -> subquery -> havingQual ,
162+ clause );
163+ /*
164+ * We need not change the subquery's hasAggs or
165+ * hasSublinks flags, since we can't be pushing down
166+ * any aggregates that weren't there before, and we
167+ * don't push down subselects at all.
168+ */
169+ }
160170}
171+ rel -> baserestrictinfo = upperrestrictlist ;
161172}
162- rel -> baserestrictinfo = upperrestrictlist ;
163173
164174/* Generate the plan for the subquery */
165175rel -> subplan = subquery_planner (rte -> subquery ,