1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-03 20:02:46 +03:00

Fix planner problems with LATERAL references in PlaceHolderVars.

The planner largely failed to consider the possibility that a
PlaceHolderVar's expression might contain a lateral reference to a Var
coming from somewhere outside the PHV's syntactic scope.  We had a previous
report of a problem in this area, which I tried to fix in a quick-hack way
in commit 4da6439bd8, but Antonin Houska
pointed out that there were still some problems, and investigation turned
up other issues.  This patch largely reverts that commit in favor of a more
thoroughly thought-through solution.  The new theory is that a PHV's
ph_eval_at level cannot be higher than its original syntactic level.  If it
contains lateral references, those don't change the ph_eval_at level, but
rather they create a lateral-reference requirement for the ph_eval_at join
relation.  The code in joinpath.c needs to handle that.

Another issue is that createplan.c wasn't handling nested PlaceHolderVars
properly.

In passing, push knowledge of lateral-reference checks for join clauses
into join_clause_is_movable_to.  This is mainly so that FDWs don't need
to deal with it.

This patch doesn't fix the original join-qual-placement problem reported by
Jeremy Evans (and indeed, one of the new regression test cases shows the
wrong answer because of that).  But the PlaceHolderVar problems need to be
fixed before that issue can be addressed, so committing this separately
seems reasonable.
This commit is contained in:
Tom Lane
2013-08-17 20:22:37 -04:00
parent 175ec8de47
commit 9e7e29c75a
25 changed files with 840 additions and 311 deletions

View File

@ -386,8 +386,7 @@ set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
/*
* We don't support pushing join clauses into the quals of a seqscan, but
* it could still have required parameterization due to LATERAL refs in
* its tlist. (That can only happen if the seqscan is on a relation
* pulled up out of a UNION ALL appendrel.)
* its tlist.
*/
required_outer = rel->lateral_relids;
@ -550,8 +549,8 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
* Note: the resulting childrel->reltargetlist may contain arbitrary
* expressions, which otherwise would not occur in a reltargetlist.
* Code that might be looking at an appendrel child must cope with
* such. Note in particular that "arbitrary expression" can include
* "Var belonging to another relation", due to LATERAL references.
* such. (Normally, a reltargetlist would only include Vars and
* PlaceHolderVars.)
*/
childrel->joininfo = (List *)
adjust_appendrel_attrs(root,
@ -1355,8 +1354,7 @@ set_cte_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
/*
* We don't support pushing join clauses into the quals of a CTE scan, but
* it could still have required parameterization due to LATERAL refs in
* its tlist. (That can only happen if the CTE scan is on a relation
* pulled up out of a UNION ALL appendrel.)
* its tlist.
*/
required_outer = rel->lateral_relids;
@ -1408,10 +1406,8 @@ set_worktable_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
/*
* We don't support pushing join clauses into the quals of a worktable
* scan, but it could still have required parameterization due to LATERAL
* refs in its tlist. (That can only happen if the worktable scan is on a
* relation pulled up out of a UNION ALL appendrel. I'm not sure this is
* actually possible given the restrictions on recursive references, but
* it's easy enough to support.)
* refs in its tlist. (I'm not sure this is actually possible given the
* restrictions on recursive references, but it's easy enough to support.)
*/
required_outer = rel->lateral_relids;