diff options
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r-- | src/backend/optimizer/path/equivclass.c | 15 | ||||
-rw-r--r-- | src/backend/optimizer/util/relnode.c | 25 |
2 files changed, 33 insertions, 7 deletions
diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c index e54da55924e..94387fdaca8 100644 --- a/src/backend/optimizer/path/equivclass.c +++ b/src/backend/optimizer/path/equivclass.c @@ -1465,6 +1465,21 @@ create_join_clause(PlannerInfo *root, rightem->em_nullable_relids), ec->ec_min_security); + /* + * If either EM is a child, force the clause's clause_relids to include + * the relid(s) of the child rel. In normal cases it would already, but + * not if we are considering appendrel child relations with pseudoconstant + * translated variables (i.e., UNION ALL sub-selects with constant output + * items). We must do this so that join_clause_is_movable_into() will + * think that the clause should be evaluated at the correct place. + */ + if (leftem->em_is_child) + rinfo->clause_relids = bms_add_members(rinfo->clause_relids, + leftem->em_relids); + if (rightem->em_is_child) + rinfo->clause_relids = bms_add_members(rinfo->clause_relids, + rightem->em_relids); + /* Mark the clause as redundant, or not */ rinfo->parent_ec = parent_ec; diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index 7758a49fa4c..380ce9fc9a4 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -1264,6 +1264,7 @@ get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel, ParamPathInfo *ppi; Relids joinrelids; List *pclauses; + List *eqclauses; double rows; ListCell *lc; @@ -1297,14 +1298,24 @@ get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel, } /* - * Add in joinclauses generated by EquivalenceClasses, too. (These - * necessarily satisfy join_clause_is_movable_into.) + * Add in joinclauses generated by EquivalenceClasses, too. In principle + * these should always satisfy join_clause_is_movable_into; but if we are + * below an outer join the clauses might contain Vars that should only be + * evaluated above the join, so we have to check. */ - pclauses = list_concat(pclauses, - generate_join_implied_equalities(root, - joinrelids, - required_outer, - baserel)); + eqclauses = generate_join_implied_equalities(root, + joinrelids, + required_outer, + baserel); + foreach(lc, eqclauses) + { + RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); + + if (join_clause_is_movable_into(rinfo, + baserel->relids, + joinrelids)) + pclauses = lappend(pclauses, rinfo); + } /* Estimate the number of rows returned by the parameterized scan */ rows = get_parameterized_baserel_size(root, baserel, pclauses); |