Commit 31468d05 authored by Tom Lane's avatar Tom Lane

Dept of better ideas: refrain from creating the planner's placeholder_list

until vars are distributed to rels during query_planner() startup.  We don't
really need it before that, and not building it early has some advantages.
First, we don't need to put it through the various preprocessing steps, which
saves some cycles and eliminates the need for a number of routines to support
PlaceHolderInfo nodes at all.  Second, this means one less unused plan for any
sub-SELECT appearing in a placeholder's expression, since we don't build
placeholder_list until after sublink expansion is complete.
parent b9856b67
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.111 2008/10/21 20:42:53 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.112 2008/10/22 20:17:51 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -133,7 +133,7 @@ query_planner(PlannerInfo *root, List *tlist, ...@@ -133,7 +133,7 @@ query_planner(PlannerInfo *root, List *tlist,
* for "simple" rels. * for "simple" rels.
* *
* NOTE: append_rel_list was set up by subquery_planner, so do not touch * NOTE: append_rel_list was set up by subquery_planner, so do not touch
* here; ditto placeholder_list; eq_classes may contain data already, too. * here; eq_classes may contain data already, too.
*/ */
root->simple_rel_array_size = list_length(parse->rtable) + 1; root->simple_rel_array_size = list_length(parse->rtable) + 1;
root->simple_rel_array = (RelOptInfo **) root->simple_rel_array = (RelOptInfo **)
...@@ -145,6 +145,7 @@ query_planner(PlannerInfo *root, List *tlist, ...@@ -145,6 +145,7 @@ query_planner(PlannerInfo *root, List *tlist,
root->right_join_clauses = NIL; root->right_join_clauses = NIL;
root->full_join_clauses = NIL; root->full_join_clauses = NIL;
root->join_info_list = NIL; root->join_info_list = NIL;
root->placeholder_list = NIL;
root->initial_rels = NIL; root->initial_rels = NIL;
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.245 2008/10/21 20:42:53 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.246 2008/10/22 20:17:51 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -55,7 +55,7 @@ planner_hook_type planner_hook = NULL; ...@@ -55,7 +55,7 @@ planner_hook_type planner_hook = NULL;
#define EXPRKIND_RTFUNC 2 #define EXPRKIND_RTFUNC 2
#define EXPRKIND_VALUES 3 #define EXPRKIND_VALUES 3
#define EXPRKIND_LIMIT 4 #define EXPRKIND_LIMIT 4
#define EXPRKIND_AUXINFO 5 #define EXPRKIND_APPINFO 5
static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind); static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind);
...@@ -274,7 +274,6 @@ subquery_planner(PlannerGlobal *glob, Query *parse, ...@@ -274,7 +274,6 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
root->cte_plan_ids = NIL; root->cte_plan_ids = NIL;
root->eq_classes = NIL; root->eq_classes = NIL;
root->append_rel_list = NIL; root->append_rel_list = NIL;
root->placeholder_list = NIL;
root->hasRecursion = hasRecursion; root->hasRecursion = hasRecursion;
if (hasRecursion) if (hasRecursion)
...@@ -380,10 +379,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse, ...@@ -380,10 +379,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
root->append_rel_list = (List *) root->append_rel_list = (List *)
preprocess_expression(root, (Node *) root->append_rel_list, preprocess_expression(root, (Node *) root->append_rel_list,
EXPRKIND_AUXINFO); EXPRKIND_APPINFO);
root->placeholder_list = (List *)
preprocess_expression(root, (Node *) root->placeholder_list,
EXPRKIND_AUXINFO);
/* Also need to preprocess expressions for function and values RTEs */ /* Also need to preprocess expressions for function and values RTEs */
foreach(l, parse->rtable) foreach(l, parse->rtable)
...@@ -664,11 +660,10 @@ inheritance_planner(PlannerInfo *root) ...@@ -664,11 +660,10 @@ inheritance_planner(PlannerInfo *root)
subroot.returningLists = NIL; subroot.returningLists = NIL;
subroot.init_plans = NIL; subroot.init_plans = NIL;
/* We needn't modify the child's append_rel_list */ /* We needn't modify the child's append_rel_list */
subroot.placeholder_list = (List *)
adjust_appendrel_attrs((Node *) root->placeholder_list,
appinfo);
/* There shouldn't be any OJ info to translate, as yet */ /* There shouldn't be any OJ info to translate, as yet */
Assert(subroot.join_info_list == NIL); Assert(subroot.join_info_list == NIL);
/* and we haven't created PlaceHolderInfos, either */
Assert(subroot.placeholder_list == NIL);
/* Generate plan */ /* Generate plan */
subplan = grouping_planner(&subroot, 0.0 /* retrieve all tuples */ ); subplan = grouping_planner(&subroot, 0.0 /* retrieve all tuples */ );
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.57 2008/10/21 20:42:53 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.58 2008/10/22 20:17:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -565,7 +565,6 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte, ...@@ -565,7 +565,6 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
subroot->cte_plan_ids = NIL; subroot->cte_plan_ids = NIL;
subroot->eq_classes = NIL; subroot->eq_classes = NIL;
subroot->append_rel_list = NIL; subroot->append_rel_list = NIL;
subroot->placeholder_list = NIL;
subroot->hasRecursion = false; subroot->hasRecursion = false;
subroot->wt_param_id = -1; subroot->wt_param_id = -1;
subroot->non_recursive_plan = NULL; subroot->non_recursive_plan = NULL;
...@@ -627,12 +626,11 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte, ...@@ -627,12 +626,11 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
/* /*
* Adjust level-0 varnos in subquery so that we can append its rangetable * Adjust level-0 varnos in subquery so that we can append its rangetable
* to upper query's. We have to fix the subquery's append_rel_list * to upper query's. We have to fix the subquery's append_rel_list
* and placeholder_list as well. * as well.
*/ */
rtoffset = list_length(parse->rtable); rtoffset = list_length(parse->rtable);
OffsetVarNodes((Node *) subquery, rtoffset, 0); OffsetVarNodes((Node *) subquery, rtoffset, 0);
OffsetVarNodes((Node *) subroot->append_rel_list, rtoffset, 0); OffsetVarNodes((Node *) subroot->append_rel_list, rtoffset, 0);
OffsetVarNodes((Node *) subroot->placeholder_list, rtoffset, 0);
/* /*
* Upper-level vars in subquery are now one level closer to their parent * Upper-level vars in subquery are now one level closer to their parent
...@@ -640,7 +638,6 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte, ...@@ -640,7 +638,6 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
*/ */
IncrementVarSublevelsUp((Node *) subquery, -1, 1); IncrementVarSublevelsUp((Node *) subquery, -1, 1);
IncrementVarSublevelsUp((Node *) subroot->append_rel_list, -1, 1); IncrementVarSublevelsUp((Node *) subroot->append_rel_list, -1, 1);
IncrementVarSublevelsUp((Node *) subroot->placeholder_list, -1, 1);
/* /*
* The subquery's targetlist items are now in the appropriate form to * The subquery's targetlist items are now in the appropriate form to
...@@ -706,48 +703,42 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte, ...@@ -706,48 +703,42 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
parse->rowMarks = list_concat(parse->rowMarks, subquery->rowMarks); parse->rowMarks = list_concat(parse->rowMarks, subquery->rowMarks);
/* /*
* We also have to fix the relid sets of any FlattenedSubLink, * We also have to fix the relid sets of any FlattenedSubLink and
* PlaceHolderVar, and PlaceHolderInfo nodes in the parent query. * PlaceHolderVar nodes in the parent query. (This could perhaps be done
* (This could perhaps be done by ResolveNew, but it would clutter that * by ResolveNew, but it would clutter that routine's API unreasonably.)
* routine's API unreasonably.) Note in particular that any placeholder * Note in particular that any PlaceHolderVar nodes just created by
* nodes just created by insert_targetlist_placeholders() wiil be adjusted. * insert_targetlist_placeholders() will be adjusted, so having created
* them with the subquery's varno is correct.
* *
* Likewise, relids appearing in AppendRelInfo nodes have to be fixed (but * Likewise, relids appearing in AppendRelInfo nodes have to be fixed (but
* we took care of their translated_vars lists above). We already checked * we took care of their translated_vars lists above). We already checked
* that this won't require introducing multiple subrelids into the * that this won't require introducing multiple subrelids into the
* single-slot AppendRelInfo structs. * single-slot AppendRelInfo structs.
*/ */
if (parse->hasSubLinks || root->placeholder_list || root->append_rel_list) if (parse->hasSubLinks || root->glob->lastPHId != 0 ||
root->append_rel_list)
{ {
Relids subrelids; Relids subrelids;
subrelids = get_relids_in_jointree((Node *) subquery->jointree, false); subrelids = get_relids_in_jointree((Node *) subquery->jointree, false);
substitute_multiple_relids((Node *) parse, substitute_multiple_relids((Node *) parse, varno, subrelids);
varno, subrelids); fix_append_rel_relids(root->append_rel_list, varno, subrelids);
substitute_multiple_relids((Node *) root->placeholder_list,
varno, subrelids);
fix_append_rel_relids(root->append_rel_list,
varno, subrelids);
} }
/* /*
* And now add subquery's AppendRelInfos and PlaceHolderInfos to our lists. * And now add subquery's AppendRelInfos to our list.
* Note that any placeholders pulled up from the subquery will appear
* after any we just created; this preserves the property that placeholders
* can only refer to other placeholders that appear later in the list
* (needed by fix_placeholder_eval_levels).
*/ */
root->append_rel_list = list_concat(root->append_rel_list, root->append_rel_list = list_concat(root->append_rel_list,
subroot->append_rel_list); subroot->append_rel_list);
root->placeholder_list = list_concat(root->placeholder_list,
subroot->placeholder_list);
/* /*
* We don't have to do the equivalent bookkeeping for outer-join info, * We don't have to do the equivalent bookkeeping for outer-join info,
* because that hasn't been set up yet. * because that hasn't been set up yet. placeholder_list likewise.
*/ */
Assert(root->join_info_list == NIL); Assert(root->join_info_list == NIL);
Assert(subroot->join_info_list == NIL); Assert(subroot->join_info_list == NIL);
Assert(root->placeholder_list == NIL);
Assert(subroot->placeholder_list == NIL);
/* /*
* Miscellaneous housekeeping. * Miscellaneous housekeeping.
...@@ -1606,10 +1597,10 @@ reduce_outer_joins_pass2(Node *jtnode, ...@@ -1606,10 +1597,10 @@ reduce_outer_joins_pass2(Node *jtnode,
* substitute_multiple_relids - adjust node relid sets after pulling up * substitute_multiple_relids - adjust node relid sets after pulling up
* a subquery * a subquery
* *
* Find any FlattenedSubLink, PlaceHolderVar, or PlaceHolderInfo nodes in the * Find any FlattenedSubLink or PlaceHolderVar nodes in the given tree that
* given tree that reference the pulled-up relid, and change them to reference * reference the pulled-up relid, and change them to reference the replacement
* the replacement relid(s). We do not need to recurse into subqueries, since * relid(s). We do not need to recurse into subqueries, since no subquery of
* no subquery of the current top query could (yet) contain such a reference. * the current top query could (yet) contain such a reference.
* *
* NOTE: although this has the form of a walker, we cheat and modify the * NOTE: although this has the form of a walker, we cheat and modify the
* nodes in-place. This should be OK since the tree was copied by ResolveNew * nodes in-place. This should be OK since the tree was copied by ResolveNew
...@@ -1662,26 +1653,11 @@ substitute_multiple_relids_walker(Node *node, ...@@ -1662,26 +1653,11 @@ substitute_multiple_relids_walker(Node *node,
} }
/* fall through to examine children */ /* fall through to examine children */
} }
if (IsA(node, PlaceHolderInfo)) /* Shouldn't need to handle planner auxiliary nodes here */
{ Assert(!IsA(node, SpecialJoinInfo));
PlaceHolderInfo *phinfo = (PlaceHolderInfo *) node; Assert(!IsA(node, AppendRelInfo));
Assert(!IsA(node, PlaceHolderInfo));
if (bms_is_member(context->varno, phinfo->ph_eval_at))
{
phinfo->ph_eval_at = bms_union(phinfo->ph_eval_at,
context->subrelids);
phinfo->ph_eval_at = bms_del_member(phinfo->ph_eval_at,
context->varno);
}
if (bms_is_member(context->varno, phinfo->ph_needed))
{
phinfo->ph_needed = bms_union(phinfo->ph_needed,
context->subrelids);
phinfo->ph_needed = bms_del_member(phinfo->ph_needed,
context->varno);
}
/* fall through to examine children */
}
return expression_tree_walker(node, substitute_multiple_relids_walker, return expression_tree_walker(node, substitute_multiple_relids_walker,
(void *) context); (void *) context);
} }
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.159 2008/10/21 20:42:53 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.160 2008/10/22 20:17:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1599,26 +1599,10 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context) ...@@ -1599,26 +1599,10 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context)
context->child_relid); context->child_relid);
return (Node *) phv; return (Node *) phv;
} }
if (IsA(node, PlaceHolderInfo)) /* Shouldn't need to handle planner auxiliary nodes here */
{
/* Copy the PlaceHolderInfo node with correct mutation of subnodes */
PlaceHolderInfo *phinfo;
phinfo = (PlaceHolderInfo *) expression_tree_mutator(node,
adjust_appendrel_attrs_mutator,
(void *) context);
/* now fix PlaceHolderInfo's relid sets */
phinfo->ph_eval_at = adjust_relid_set(phinfo->ph_eval_at,
context->parent_relid,
context->child_relid);
phinfo->ph_needed = adjust_relid_set(phinfo->ph_needed,
context->parent_relid,
context->child_relid);
return (Node *) phinfo;
}
/* Shouldn't need to handle other planner auxiliary nodes here */
Assert(!IsA(node, SpecialJoinInfo)); Assert(!IsA(node, SpecialJoinInfo));
Assert(!IsA(node, AppendRelInfo)); Assert(!IsA(node, AppendRelInfo));
Assert(!IsA(node, PlaceHolderInfo));
/* /*
* We have to process RestrictInfo nodes specially. * We have to process RestrictInfo nodes specially.
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/placeholder.c,v 1.1 2008/10/21 20:42:53 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/util/placeholder.c,v 1.2 2008/10/22 20:17:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -25,8 +25,7 @@ ...@@ -25,8 +25,7 @@
/* /*
* make_placeholder_expr * make_placeholder_expr
* Make a PlaceHolderVar (and corresponding PlaceHolderInfo) * Make a PlaceHolderVar for the given expression.
* for the given expression.
* *
* phrels is the syntactic location (as a set of baserels) to attribute * phrels is the syntactic location (as a set of baserels) to attribute
* to the expression. * to the expression.
...@@ -35,34 +34,25 @@ PlaceHolderVar * ...@@ -35,34 +34,25 @@ PlaceHolderVar *
make_placeholder_expr(PlannerInfo *root, Expr *expr, Relids phrels) make_placeholder_expr(PlannerInfo *root, Expr *expr, Relids phrels)
{ {
PlaceHolderVar *phv = makeNode(PlaceHolderVar); PlaceHolderVar *phv = makeNode(PlaceHolderVar);
PlaceHolderInfo *phinfo = makeNode(PlaceHolderInfo);
phv->phexpr = expr; phv->phexpr = expr;
phv->phrels = phrels; phv->phrels = phrels;
phv->phid = ++(root->glob->lastPHId); phv->phid = ++(root->glob->lastPHId);
phv->phlevelsup = 0; phv->phlevelsup = 0;
phinfo->phid = phv->phid;
phinfo->ph_var = copyObject(phv);
phinfo->ph_eval_at = pull_varnos((Node *) phv);
/* ph_eval_at may change later, see fix_placeholder_eval_levels */
phinfo->ph_needed = NULL; /* initially it's unused */
/* for the moment, estimate width using just the datatype info */
phinfo->ph_width = get_typavgwidth(exprType((Node *) expr),
exprTypmod((Node *) expr));
root->placeholder_list = lappend(root->placeholder_list, phinfo);
return phv; return phv;
} }
/* /*
* find_placeholder_info * find_placeholder_info
* Fetch the PlaceHolderInfo for the given PHV; error if not found * Fetch the PlaceHolderInfo for the given PHV; create it if not found
*
* Note: this should only be called after query_planner() has started.
*/ */
PlaceHolderInfo * PlaceHolderInfo *
find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv) find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv)
{ {
PlaceHolderInfo *phinfo;
ListCell *lc; ListCell *lc;
/* if this ever isn't true, we'd need to be able to look in parent lists */ /* if this ever isn't true, we'd need to be able to look in parent lists */
...@@ -70,20 +60,33 @@ find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv) ...@@ -70,20 +60,33 @@ find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv)
foreach(lc, root->placeholder_list) foreach(lc, root->placeholder_list)
{ {
PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc); phinfo = (PlaceHolderInfo *) lfirst(lc);
if (phinfo->phid == phv->phid) if (phinfo->phid == phv->phid)
return phinfo; return phinfo;
} }
elog(ERROR, "could not find PlaceHolderInfo with id %u", phv->phid);
return NULL; /* keep compiler quiet */ /* Not found, so create it */
phinfo = makeNode(PlaceHolderInfo);
phinfo->phid = phv->phid;
phinfo->ph_var = copyObject(phv);
phinfo->ph_eval_at = pull_varnos((Node *) phv);
/* ph_eval_at may change later, see fix_placeholder_eval_levels */
phinfo->ph_needed = NULL; /* initially it's unused */
/* for the moment, estimate width using just the datatype info */
phinfo->ph_width = get_typavgwidth(exprType((Node *) phv->phexpr),
exprTypmod((Node *) phv->phexpr));
root->placeholder_list = lappend(root->placeholder_list, phinfo);
return phinfo;
} }
/* /*
* fix_placeholder_eval_levels * fix_placeholder_eval_levels
* Adjust the target evaluation levels for placeholders * Adjust the target evaluation levels for placeholders
* *
* The initial eval_at level set by make_placeholder_expr was the set of * The initial eval_at level set by find_placeholder_info was the set of
* rels used in the placeholder's expression (or the whole subselect if * rels used in the placeholder's expression (or the whole subselect if
* the expr is variable-free). If the subselect contains any outer joins * the expr is variable-free). If the subselect contains any outer joins
* that can null any of those rels, we must delay evaluation to above those * that can null any of those rels, we must delay evaluation to above those
...@@ -103,19 +106,9 @@ fix_placeholder_eval_levels(PlannerInfo *root) ...@@ -103,19 +106,9 @@ fix_placeholder_eval_levels(PlannerInfo *root)
PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc1); PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc1);
Relids syn_level = phinfo->ph_var->phrels; Relids syn_level = phinfo->ph_var->phrels;
Relids eval_at = phinfo->ph_eval_at; Relids eval_at = phinfo->ph_eval_at;
BMS_Membership eval_membership;
bool found_some; bool found_some;
ListCell *lc2; ListCell *lc2;
/*
* Ignore unreferenced placeholders. Note: if a placeholder is
* referenced only by some other placeholder's expr, we will do
* the right things because the referencing placeholder must appear
* earlier in the list.
*/
if (bms_is_empty(phinfo->ph_needed))
continue;
/* /*
* Check for delays due to lower outer joins. This is the same logic * Check for delays due to lower outer joins. This is the same logic
* as in check_outerjoin_delay in initsplan.c, except that we don't * as in check_outerjoin_delay in initsplan.c, except that we don't
...@@ -160,11 +153,13 @@ fix_placeholder_eval_levels(PlannerInfo *root) ...@@ -160,11 +153,13 @@ fix_placeholder_eval_levels(PlannerInfo *root)
/* /*
* Now that we know where to evaluate the placeholder, make sure that * Now that we know where to evaluate the placeholder, make sure that
* any vars or placeholders it uses will be available at that join * any vars or placeholders it uses will be available at that join
* level. (Note that this has to be done within this loop to make * level. NOTE: this could cause more PlaceHolderInfos to be added
* sure we don't skip over such placeholders when we get to them.) * to placeholder_list. That is okay because we'll process them
* before falling out of the foreach loop. Also, it could cause
* the ph_needed sets of existing list entries to expand, which
* is also okay because this loop doesn't examine those.
*/ */
eval_membership = bms_membership(eval_at); if (bms_membership(eval_at) == BMS_MULTIPLE)
if (eval_membership == BMS_MULTIPLE)
{ {
List *vars = pull_var_clause((Node *) phinfo->ph_var->phexpr, List *vars = pull_var_clause((Node *) phinfo->ph_var->phexpr,
true); true);
...@@ -172,14 +167,22 @@ fix_placeholder_eval_levels(PlannerInfo *root) ...@@ -172,14 +167,22 @@ fix_placeholder_eval_levels(PlannerInfo *root)
add_vars_to_targetlist(root, vars, eval_at); add_vars_to_targetlist(root, vars, eval_at);
list_free(vars); list_free(vars);
} }
}
/* /*
* Also, if the placeholder can be computed at a base rel and is * Now, if any placeholder can be computed at a base rel and is needed
* needed above it, add it to that rel's targetlist. (This is * above it, add it to that rel's targetlist. (This is essentially the
* essentially the same logic as in add_placeholders_to_joinrel, but * same logic as in add_placeholders_to_joinrel, but we can't do that part
* we can't do that part until joinrels are formed.) * until joinrels are formed.) We have to do this as a separate step
*/ * because the ph_needed values aren't stable until the previous loop
if (eval_membership == BMS_SINGLETON) * finishes.
*/
foreach(lc1, root->placeholder_list)
{
PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc1);
Relids eval_at = phinfo->ph_eval_at;
if (bms_membership(eval_at) == BMS_SINGLETON)
{ {
int varno = bms_singleton_member(eval_at); int varno = bms_singleton_member(eval_at);
RelOptInfo *rel = find_base_rel(root, varno); RelOptInfo *rel = find_base_rel(root, varno);
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.81 2008/10/21 20:42:53 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.82 2008/10/22 20:17:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -800,24 +800,6 @@ flatten_join_alias_vars_mutator(Node *node, ...@@ -800,24 +800,6 @@ flatten_join_alias_vars_mutator(Node *node,
} }
return (Node *) phv; return (Node *) phv;
} }
if (IsA(node, PlaceHolderInfo))
{
/* Copy the PlaceHolderInfo node with correct mutation of subnodes */
PlaceHolderInfo *phinfo;
phinfo = (PlaceHolderInfo *) expression_tree_mutator(node,
flatten_join_alias_vars_mutator,
(void *) context);
/* now fix PlaceHolderInfo's relid sets */
if (context->sublevels_up == 0)
{
phinfo->ph_eval_at = alias_relid_set(context->root,
phinfo->ph_eval_at);
phinfo->ph_needed = alias_relid_set(context->root,
phinfo->ph_needed);
}
return (Node *) phinfo;
}
if (IsA(node, Query)) if (IsA(node, Query))
{ {
...@@ -834,6 +816,9 @@ flatten_join_alias_vars_mutator(Node *node, ...@@ -834,6 +816,9 @@ flatten_join_alias_vars_mutator(Node *node,
} }
/* Already-planned tree not supported */ /* Already-planned tree not supported */
Assert(!IsA(node, SubPlan)); Assert(!IsA(node, SubPlan));
/* Shouldn't need to handle these planner auxiliary nodes here */
Assert(!IsA(node, SpecialJoinInfo));
Assert(!IsA(node, PlaceHolderInfo));
return expression_tree_mutator(node, flatten_join_alias_vars_mutator, return expression_tree_mutator(node, flatten_join_alias_vars_mutator,
(void *) context); (void *) context);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.116 2008/10/21 20:42:53 tgl Exp $ * $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.117 2008/10/22 20:17:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -298,19 +298,10 @@ OffsetVarNodes_walker(Node *node, OffsetVarNodes_context *context) ...@@ -298,19 +298,10 @@ OffsetVarNodes_walker(Node *node, OffsetVarNodes_context *context)
} }
/* fall through to examine children */ /* fall through to examine children */
} }
if (IsA(node, PlaceHolderInfo)) /* Shouldn't need to handle other planner auxiliary nodes here */
{ Assert(!IsA(node, SpecialJoinInfo));
PlaceHolderInfo *phinfo = (PlaceHolderInfo *) node; Assert(!IsA(node, PlaceHolderInfo));
if (context->sublevels_up == 0)
{
phinfo->ph_eval_at = offset_relid_set(phinfo->ph_eval_at,
context->offset);
phinfo->ph_needed = offset_relid_set(phinfo->ph_needed,
context->offset);
}
/* fall through to examine children */
}
if (IsA(node, Query)) if (IsA(node, Query))
{ {
/* Recurse into subselects */ /* Recurse into subselects */
...@@ -489,21 +480,10 @@ ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context) ...@@ -489,21 +480,10 @@ ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context)
} }
/* fall through to examine children */ /* fall through to examine children */
} }
if (IsA(node, PlaceHolderInfo)) /* Shouldn't need to handle other planner auxiliary nodes here */
{ Assert(!IsA(node, SpecialJoinInfo));
PlaceHolderInfo *phinfo = (PlaceHolderInfo *) node; Assert(!IsA(node, PlaceHolderInfo));
if (context->sublevels_up == 0)
{
phinfo->ph_eval_at = adjust_relid_set(phinfo->ph_eval_at,
context->rt_index,
context->new_index);
phinfo->ph_needed = adjust_relid_set(phinfo->ph_needed,
context->rt_index,
context->new_index);
}
/* fall through to examine children */
}
if (IsA(node, Query)) if (IsA(node, Query))
{ {
/* Recurse into subselects */ /* Recurse into subselects */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.162 2008/10/21 20:42:53 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.163 2008/10/22 20:17:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1290,6 +1290,9 @@ typedef struct AppendRelInfo ...@@ -1290,6 +1290,9 @@ typedef struct AppendRelInfo
* The idea is to evaluate the expression at (only) the ph_eval_at join level, * The idea is to evaluate the expression at (only) the ph_eval_at join level,
* then allow it to bubble up like a Var until the ph_needed join level. * then allow it to bubble up like a Var until the ph_needed join level.
* ph_needed has the same definition as attr_needed for a regular Var. * ph_needed has the same definition as attr_needed for a regular Var.
*
* We create a PlaceHolderInfo only after determining that the PlaceHolderVar
* is actually referenced in the plan tree.
*/ */
typedef struct PlaceHolderInfo typedef struct PlaceHolderInfo
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment