summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path/allpaths.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/path/allpaths.c')
-rw-r--r--src/backend/optimizer/path/allpaths.c63
1 files changed, 59 insertions, 4 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 4f7a0e570f5..5e461cb3c15 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -8,13 +8,14 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.68 2000/12/14 22:30:43 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.69 2001/01/18 07:12:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/geqo.h"
#include "optimizer/pathnode.h"
@@ -23,6 +24,7 @@
#include "optimizer/planner.h"
#include "optimizer/prep.h"
#include "parser/parsetree.h"
+#include "rewrite/rewriteManip.h"
bool enable_geqo = true;
@@ -99,12 +101,65 @@ set_base_rel_pathlists(Query *root)
if (rel->issubquery)
{
/* Subquery --- generate a separate plan for it */
+ List *upperrestrictlist;
+ List *lst;
/*
- * XXX for now, we just apply any restrict clauses that came
- * from the outer query as qpquals of the SubqueryScan node.
- * Later, think about pushing them down into the subquery itself.
+ * If there are any restriction clauses that have been attached
+ * to the subquery relation, consider pushing them down to become
+ * HAVING quals of the subquery itself. (Not WHERE clauses, since
+ * they may refer to subquery outputs that are aggregate results.
+ * But planner.c will transfer them into the subquery's WHERE if
+ * they do not.) This transformation is useful because it may
+ * allow us to generate a better plan for the subquery than
+ * evaluating all the subquery output rows and then filtering
+ * them.
+ *
+ * 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).
+ * Non-pushed-down clauses will get evaluated as qpquals of
+ * the SubqueryScan node.
+ *
+ * XXX Are there any cases where we want to make a policy
+ * decision not to push down, because it'd result in a worse
+ * plan?
*/
+ upperrestrictlist = NIL;
+ foreach(lst, rel->baserestrictinfo)
+ {
+ 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;
/* Generate the plan for the subquery */
rel->subplan = subquery_planner(rte->subquery,