diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2009-07-06 18:26:30 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2009-07-06 18:26:30 +0000 |
| commit | 9b27eab71c47f4f21d0e487b1d7ad277a85735e0 (patch) | |
| tree | beda036b38bbdce77fa13464927e1ddbc20def71 /src/backend/optimizer/path/allpaths.c | |
| parent | bf6570abef3df08c7cd4d318d61217b2f95ccbb2 (diff) | |
Fix set_append_rel_pathlist() to deal intelligently with cases where
substituting a child rel's output expressions into the appendrel's restriction
clauses yields a pseudoconstant restriction. We might be able to skip scanning
that child rel entirely (if we get constant FALSE), or generate a one-time
filter. 8.3 more or less accidentally generated plans that weren't completely
stupid in these cases, but that was only because an extra recursive level of
subquery_planner() always occurred and allowed const-simplification to happen.
8.4's ability to pull up appendrel members with non-Var outputs exposes the
fact that we need to work harder here. Per gripe from Sergey Burladyan.
Diffstat (limited to 'src/backend/optimizer/path/allpaths.c')
| -rw-r--r-- | src/backend/optimizer/path/allpaths.c | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 4a0a1012c0a..e8e5b2ecb2d 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.183 2009/06/11 14:48:58 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.184 2009/07/06 18:26:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,6 +29,7 @@ #include "optimizer/plancat.h" #include "optimizer/planner.h" #include "optimizer/prep.h" +#include "optimizer/restrictinfo.h" #include "optimizer/var.h" #include "parser/parse_clause.h" #include "parser/parsetree.h" @@ -318,6 +319,8 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, int childRTindex; RangeTblEntry *childRTE; RelOptInfo *childrel; + List *childquals; + Node *childqual; Path *childpath; ListCell *parentvars; ListCell *childvars; @@ -342,10 +345,34 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, * baserestrictinfo quals are needed before we can check for * constraint exclusion; so do that first and then check to see if we * can disregard this child. + * + * As of 8.4, the child rel's targetlist might contain non-Var + * expressions, which means that substitution into the quals + * could produce opportunities for const-simplification, and perhaps + * even pseudoconstant quals. To deal with this, we strip the + * RestrictInfo nodes, do the substitution, do const-simplification, + * and then reconstitute the RestrictInfo layer. */ - childrel->baserestrictinfo = (List *) - adjust_appendrel_attrs((Node *) rel->baserestrictinfo, - appinfo); + childquals = get_all_actual_clauses(rel->baserestrictinfo); + childquals = (List *) adjust_appendrel_attrs((Node *) childquals, + appinfo); + childqual = eval_const_expressions(root, (Node *) + make_ands_explicit(childquals)); + if (childqual && IsA(childqual, Const) && + (((Const *) childqual)->constisnull || + !DatumGetBool(((Const *) childqual)->constvalue))) + { + /* + * Restriction reduces to constant FALSE or constant NULL after + * substitution, so this child need not be scanned. + */ + set_dummy_rel_pathlist(childrel); + continue; + } + childquals = make_ands_implicit((Expr *) childqual); + childquals = make_restrictinfos_from_actual_clauses(root, + childquals); + childrel->baserestrictinfo = childquals; if (relation_excluded_by_constraints(root, childrel, childRTE)) { |
