#include "nodes/relation.h"
Go to the source code of this file.
Functions | |
PlaceHolderVar * | make_placeholder_expr (PlannerInfo *root, Expr *expr, Relids phrels) |
PlaceHolderInfo * | find_placeholder_info (PlannerInfo *root, PlaceHolderVar *phv, bool create_new_ph) |
void | find_placeholders_in_jointree (PlannerInfo *root) |
void | mark_placeholder_maybe_needed (PlannerInfo *root, PlaceHolderInfo *phinfo, Relids relids) |
void | update_placeholder_eval_levels (PlannerInfo *root, SpecialJoinInfo *new_sjinfo) |
void | fix_placeholder_input_needed_levels (PlannerInfo *root) |
void | add_placeholders_to_base_rels (PlannerInfo *root) |
void | add_placeholders_to_joinrel (PlannerInfo *root, RelOptInfo *joinrel) |
void add_placeholders_to_base_rels | ( | PlannerInfo * | root | ) |
Definition at line 415 of file placeholder.c.
References bms_membership(), bms_nonempty_difference(), BMS_SINGLETON, bms_singleton_member(), copyObject(), find_base_rel(), lappend(), lfirst, PlaceHolderInfo::ph_eval_at, PlaceHolderInfo::ph_needed, PlaceHolderInfo::ph_var, PlannerInfo::placeholder_list, and RelOptInfo::reltargetlist.
Referenced by query_planner().
{ ListCell *lc; foreach(lc, root->placeholder_list) { PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc); Relids eval_at = phinfo->ph_eval_at; if (bms_membership(eval_at) == BMS_SINGLETON && bms_nonempty_difference(phinfo->ph_needed, eval_at)) { int varno = bms_singleton_member(eval_at); RelOptInfo *rel = find_base_rel(root, varno); rel->reltargetlist = lappend(rel->reltargetlist, copyObject(phinfo->ph_var)); } } }
void add_placeholders_to_joinrel | ( | PlannerInfo * | root, | |
RelOptInfo * | joinrel | |||
) |
Definition at line 446 of file placeholder.c.
References bms_is_subset(), bms_nonempty_difference(), lappend(), lfirst, PlaceHolderInfo::ph_eval_at, PlaceHolderInfo::ph_needed, PlaceHolderInfo::ph_var, PlaceHolderInfo::ph_width, PlannerInfo::placeholder_list, RelOptInfo::relids, RelOptInfo::reltargetlist, and RelOptInfo::width.
Referenced by build_join_rel().
{ Relids relids = joinrel->relids; ListCell *lc; foreach(lc, root->placeholder_list) { PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc); /* Is it still needed above this joinrel? */ if (bms_nonempty_difference(phinfo->ph_needed, relids)) { /* Is it computable here? */ if (bms_is_subset(phinfo->ph_eval_at, relids)) { /* Yup, add it to the output */ joinrel->reltargetlist = lappend(joinrel->reltargetlist, phinfo->ph_var); joinrel->width += phinfo->ph_width; } } } }
PlaceHolderInfo* find_placeholder_info | ( | PlannerInfo * | root, | |
PlaceHolderVar * | phv, | |||
bool | create_new_ph | |||
) |
Definition at line 69 of file placeholder.c.
References Assert, copyObject(), elog, ERROR, exprType(), exprTypmod(), get_typavgwidth(), lappend(), lfirst, makeNode, PlaceHolderInfo::ph_eval_at, PlaceHolderInfo::ph_may_need, PlaceHolderInfo::ph_needed, PlaceHolderInfo::ph_var, PlaceHolderInfo::ph_width, PlaceHolderVar::phid, PlaceHolderInfo::phid, PlaceHolderVar::phlevelsup, PlannerInfo::placeholder_list, and pull_varnos().
Referenced by add_vars_to_targetlist(), create_lateral_join_info(), create_nestloop_plan(), mark_placeholders_in_expr(), process_subquery_nestloop_params(), replace_nestloop_params_mutator(), and set_rel_width().
{ PlaceHolderInfo *phinfo; ListCell *lc; /* if this ever isn't true, we'd need to be able to look in parent lists */ Assert(phv->phlevelsup == 0); foreach(lc, root->placeholder_list) { phinfo = (PlaceHolderInfo *) lfirst(lc); if (phinfo->phid == phv->phid) return phinfo; } /* Not found, so create it */ if (!create_new_ph) elog(ERROR, "too late to create a new PlaceHolderInfo"); 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 update_placeholder_eval_levels */ phinfo->ph_needed = NULL; /* initially it's unused */ phinfo->ph_may_need = NULL; /* 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; }
void find_placeholders_in_jointree | ( | PlannerInfo * | root | ) |
Definition at line 114 of file placeholder.c.
References Assert, find_placeholders_recurse(), PlannerInfo::glob, IsA, Query::jointree, PlannerGlobal::lastPHId, NULL, and PlannerInfo::parse.
Referenced by query_planner().
void fix_placeholder_input_needed_levels | ( | PlannerInfo * | root | ) |
Definition at line 381 of file placeholder.c.
References add_vars_to_targetlist(), bms_membership(), lfirst, list_free(), PlaceHolderInfo::ph_eval_at, PlaceHolderInfo::ph_var, PlaceHolderVar::phexpr, PlannerInfo::placeholder_list, pull_var_clause(), PVC_INCLUDE_PLACEHOLDERS, and PVC_RECURSE_AGGREGATES.
Referenced by query_planner().
{ ListCell *lc; foreach(lc, root->placeholder_list) { PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc); Relids eval_at = phinfo->ph_eval_at; /* No work unless it'll be evaluated above baserel level */ if (bms_membership(eval_at) == BMS_MULTIPLE) { List *vars = pull_var_clause((Node *) phinfo->ph_var->phexpr, PVC_RECURSE_AGGREGATES, PVC_INCLUDE_PLACEHOLDERS); add_vars_to_targetlist(root, vars, eval_at, false); list_free(vars); } } }
PlaceHolderVar* make_placeholder_expr | ( | PlannerInfo * | root, | |
Expr * | expr, | |||
Relids | phrels | |||
) |
Definition at line 39 of file placeholder.c.
References PlannerInfo::glob, PlannerGlobal::lastPHId, makeNode, PlaceHolderVar::phexpr, PlaceHolderVar::phid, PlaceHolderVar::phlevelsup, and PlaceHolderVar::phrels.
Referenced by pullup_replace_vars_callback().
{ PlaceHolderVar *phv = makeNode(PlaceHolderVar); phv->phexpr = expr; phv->phrels = phrels; phv->phid = ++(root->glob->lastPHId); phv->phlevelsup = 0; return phv; }
void mark_placeholder_maybe_needed | ( | PlannerInfo * | root, | |
PlaceHolderInfo * | phinfo, | |||
Relids | relids | |||
) |
Definition at line 250 of file placeholder.c.
References bms_add_members(), bms_free(), bms_union(), mark_placeholders_in_expr(), PlaceHolderInfo::ph_eval_at, PlaceHolderInfo::ph_may_need, PlaceHolderInfo::ph_var, PlaceHolderVar::phexpr, and PlaceHolderVar::phrels.
Referenced by add_vars_to_targetlist(), and mark_placeholders_in_expr().
{ Relids est_eval_level; /* Mark the PHV as possibly needed at the given syntactic level */ phinfo->ph_may_need = bms_add_members(phinfo->ph_may_need, relids); /* * This is a bit tricky: the PHV's contained expression may contain other, * lower-level PHVs. We need to get those into the PlaceHolderInfo list, * but they aren't going to be needed where the outer PHV is referenced. * Rather, they'll be needed where the outer PHV is evaluated. We can * estimate that conservatively as the syntactic location of the PHV's * expression, but not less than the level of any Vars it contains. * (Normally the Vars would come from below the syntactic location anyway, * but this might not be true if the PHV contains any LATERAL references.) */ est_eval_level = bms_union(phinfo->ph_var->phrels, phinfo->ph_eval_at); /* Now recurse to take care of any such PHVs */ mark_placeholders_in_expr(root, (Node *) phinfo->ph_var->phexpr, est_eval_level); bms_free(est_eval_level); }
void update_placeholder_eval_levels | ( | PlannerInfo * | root, | |
SpecialJoinInfo * | new_sjinfo | |||
) |
Definition at line 302 of file placeholder.c.
References bms_add_members(), bms_is_subset(), bms_overlap(), JOIN_FULL, PlannerInfo::join_info_list, SpecialJoinInfo::jointype, lfirst, SpecialJoinInfo::min_lefthand, SpecialJoinInfo::min_righthand, PlaceHolderInfo::ph_eval_at, PlaceHolderInfo::ph_var, PlaceHolderVar::phrels, PlannerInfo::placeholder_list, SpecialJoinInfo::syn_lefthand, and SpecialJoinInfo::syn_righthand.
Referenced by deconstruct_recurse().
{ ListCell *lc1; foreach(lc1, root->placeholder_list) { PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc1); Relids syn_level = phinfo->ph_var->phrels; Relids eval_at; bool found_some; ListCell *lc2; /* * We don't need to do any work on this placeholder unless the * newly-added outer join is syntactically beneath its location. */ if (!bms_is_subset(new_sjinfo->syn_lefthand, syn_level) || !bms_is_subset(new_sjinfo->syn_righthand, syn_level)) continue; /* * 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 * have anything to do with the delay_upper_joins flags; delay of * upper outer joins will be handled later, based on the eval_at * values we compute now. */ eval_at = phinfo->ph_eval_at; do { found_some = false; foreach(lc2, root->join_info_list) { SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc2); /* disregard joins not within the PHV's sub-select */ if (!bms_is_subset(sjinfo->syn_lefthand, syn_level) || !bms_is_subset(sjinfo->syn_righthand, syn_level)) continue; /* do we reference any nullable rels of this OJ? */ if (bms_overlap(eval_at, sjinfo->min_righthand) || (sjinfo->jointype == JOIN_FULL && bms_overlap(eval_at, sjinfo->min_lefthand))) { /* yes; have we included all its rels in eval_at? */ if (!bms_is_subset(sjinfo->min_lefthand, eval_at) || !bms_is_subset(sjinfo->min_righthand, eval_at)) { /* no, so add them in */ eval_at = bms_add_members(eval_at, sjinfo->min_lefthand); eval_at = bms_add_members(eval_at, sjinfo->min_righthand); /* we'll need another iteration */ found_some = true; } } } } while (found_some); phinfo->ph_eval_at = eval_at; } }