Header And Logo

PostgreSQL
| The world's most advanced open source database.

Functions

placeholder.h File Reference

#include "nodes/relation.h"
Include dependency graph for placeholder.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

PlaceHolderVarmake_placeholder_expr (PlannerInfo *root, Expr *expr, Relids phrels)
PlaceHolderInfofind_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)

Function Documentation

void add_placeholders_to_base_rels ( PlannerInfo root  ) 
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().

{
    /* We need do nothing if the query contains no PlaceHolderVars */
    if (root->glob->lastPHId != 0)
    {
        /* Start recursion at top of jointree */
        Assert(root->parse->jointree != NULL &&
               IsA(root->parse->jointree, FromExpr));
        (void) find_placeholders_recurse(root, (Node *) root->parse->jointree);
    }
}

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 
)
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;
    }
}