summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/relnode.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2012-08-26 22:48:55 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2012-08-26 22:50:23 -0400
commit9ff79b9d4e71822a875c0f5e38f5ec86c7fb079f (patch)
tree54ca663a626498195754d48a9b4d2c545210381d /src/backend/optimizer/util/relnode.c
parentde87d4704432e98a327dbf42dbc4711fa2628a9c (diff)
Fix up planner infrastructure to support LATERAL properly.
This patch takes care of a number of problems having to do with failure to choose valid join orders and incorrect handling of lateral references pulled up from subqueries. Notable changes: * Add a LateralJoinInfo data structure similar to SpecialJoinInfo, to represent join ordering constraints created by lateral references. (I first considered extending the SpecialJoinInfo structure, but the semantics are different enough that a separate data structure seems better.) Extend join_is_legal() and related functions to prevent trying to form unworkable joins, and to ensure that we will consider joins that satisfy lateral references even if the joins would be clauseless. * Fill in the infrastructure needed for the last few types of relation scan paths to support parameterization. We'd have wanted this eventually anyway, but it is necessary now because a relation that gets pulled up out of a UNION ALL subquery may acquire a reltargetlist containing lateral references, meaning that its paths *have* to be parameterized whether or not we have any code that can push join quals down into the scan. * Compute data about lateral references early in query_planner(), and save in RelOptInfo nodes, to avoid repetitive calculations later. * Assorted corner-case bug fixes. There's probably still some bugs left, but this is a lot closer to being real than it was before.
Diffstat (limited to 'src/backend/optimizer/util/relnode.c')
-rw-r--r--src/backend/optimizer/util/relnode.c28
1 files changed, 13 insertions, 15 deletions
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 8d4ab03d20e..680184c0e9f 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -109,6 +109,8 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
rel->relid = relid;
rel->rtekind = rte->rtekind;
/* min_attr, max_attr, attr_needed, attr_widths are set below */
+ rel->lateral_vars = NIL;
+ rel->lateral_relids = NULL;
rel->indexlist = NIL;
rel->pages = 0;
rel->tuples = 0;
@@ -365,6 +367,8 @@ build_join_rel(PlannerInfo *root,
joinrel->max_attr = 0;
joinrel->attr_needed = NULL;
joinrel->attr_widths = NULL;
+ joinrel->lateral_vars = NIL;
+ joinrel->lateral_relids = NULL;
joinrel->indexlist = NIL;
joinrel->pages = 0;
joinrel->tuples = 0;
@@ -472,8 +476,7 @@ build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
foreach(vars, input_rel->reltargetlist)
{
- Node *origvar = (Node *) lfirst(vars);
- Var *var;
+ Var *var = (Var *) lfirst(vars);
RelOptInfo *baserel;
int ndx;
@@ -481,22 +484,17 @@ build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
* Ignore PlaceHolderVars in the input tlists; we'll make our own
* decisions about whether to copy them.
*/
- if (IsA(origvar, PlaceHolderVar))
+ if (IsA(var, PlaceHolderVar))
continue;
/*
- * We can't run into any child RowExprs here, but we could find a
- * whole-row Var with a ConvertRowtypeExpr atop it.
+ * Otherwise, anything in a baserel or joinrel targetlist ought to be
+ * a Var. (More general cases can only appear in appendrel child
+ * rels, which will never be seen here.)
*/
- var = (Var *) origvar;
- while (!IsA(var, Var))
- {
- if (IsA(var, ConvertRowtypeExpr))
- var = (Var *) ((ConvertRowtypeExpr *) var)->arg;
- else
- elog(ERROR, "unexpected node type in reltargetlist: %d",
- (int) nodeTag(var));
- }
+ if (!IsA(var, Var))
+ elog(ERROR, "unexpected node type in reltargetlist: %d",
+ (int) nodeTag(var));
/* Get the Var's original base rel */
baserel = find_base_rel(root, var->varno);
@@ -506,7 +504,7 @@ build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
if (bms_nonempty_difference(baserel->attr_needed[ndx], relids))
{
/* Yup, add it to the output */
- joinrel->reltargetlist = lappend(joinrel->reltargetlist, origvar);
+ joinrel->reltargetlist = lappend(joinrel->reltargetlist, var);
joinrel->width += baserel->attr_widths[ndx];
}
}