对get_baserel_parampathinfo函数的学习

/*

 * get_baserel_parampathinfo

 *        Get the ParamPathInfo for a parameterized path for a base relation,

 *        constructing one if we don't have one already.

 *

 * This centralizes estimating the rowcounts for parameterized paths.

 * We need to cache those to be sure we use the same rowcount for all paths

 * of the same parameterization for a given rel.  This is also a convenient

 * place to determine which movable join clauses the parameterized path will

 * be responsible for evaluating.

 */

ParamPathInfo *

get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel,

                          Relids required_outer)

{

    ParamPathInfo *ppi;

    Relids        joinrelids;

    List       *pclauses;

    double        rows;

    ListCell   *lc;



    /* Unparameterized paths have no ParamPathInfo */

    if (bms_is_empty(required_outer))

        return NULL;



    Assert(!bms_overlap(baserel->relids, required_outer));



    /* If we already have a PPI for this parameterization, just return it */

    foreach(lc, baserel->ppilist)

    {

        ppi = (ParamPathInfo *) lfirst(lc);

        if (bms_equal(ppi->ppi_req_outer, required_outer))

            return ppi;

    }



    /*

     * Identify all joinclauses that are movable to this base rel given this

     * parameterization.

     */

    joinrelids = bms_union(baserel->relids, required_outer);

    pclauses = NIL;

    foreach(lc, baserel->joininfo)

    {

        RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);



        if (join_clause_is_movable_into(rinfo,

                                        baserel->relids,

                                        joinrelids))

            pclauses = lappend(pclauses, rinfo);

    }



    /*

     * Add in joinclauses generated by EquivalenceClasses, too.  (These

     * necessarily satisfy join_clause_is_movable_into.)

     */

    pclauses = list_concat(pclauses,

                           generate_join_implied_equalities(root,

                                                            joinrelids,

                                                            required_outer,

                                                            baserel));



    /* Estimate the number of rows returned by the parameterized scan */

    rows = get_parameterized_baserel_size(root, baserel, pclauses);



    /* And now we can build the ParamPathInfo */

    ppi = makeNode(ParamPathInfo);

    ppi->ppi_req_outer = required_outer;

    ppi->ppi_rows = rows;

    ppi->ppi_clauses = pclauses;

    baserel->ppilist = lappend(baserel->ppilist, ppi);



    return ppi;

}

 上溯来看:

/*

 * set_plain_rel_pathlist

 *      Build access paths for a plain relation (no subquery, no inheritance)

 */

static void

set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)

{

/* Consider sequential scan */

    add_path(rel, create_seqscan_path(root, rel, NULL));



    /* Consider index scans */

    create_index_paths(root, rel);



    /* Consider TID scans */

    create_tidscan_paths(root, rel);



    /* Now find the cheapest of the paths for this rel */

    set_cheapest(rel);

}

只要进入了 set_plain_rel_pathlist 函数,进行 

add_path(rel, create_seqscan_path(root, rel, NULL))调用是,给予 create_seqscan_path 的第三个参数是NULL

再看 create_seqscan_path:

/*

 * create_seqscan_path

 *      Creates a path corresponding to a sequential scan, returning the

 *      pathnode.

 */

Path *

create_seqscan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer)

{

    Path       *pathnode = makeNode(Path);



    pathnode->pathtype = T_SeqScan;

    pathnode->parent = rel;

    pathnode->param_info = get_baserel_parampathinfo(root, rel,

                                                     required_outer);



    pathnode->pathkeys = NIL;    /* seqscan has unordered result */



    cost_seqscan(pathnode, root, rel, pathnode->param_info);



    return pathnode;

}

看这句话:pathnode->param_info = get_baserel_parampathinfo(root, rel, required_outer);

由于传递的required_outer是NULL,所以就是 get_baserel_parampathinfo(root, rel, NULL);                                         

那么:

/*

 * get_baserel_parampathinfo

 *        Get the ParamPathInfo for a parameterized path for a base relation,

 *        constructing one if we don't have one already.

 *

 * This centralizes estimating the rowcounts for parameterized paths.

 * We need to cache those to be sure we use the same rowcount for all paths

 * of the same parameterization for a given rel.  This is also a convenient

 * place to determine which movable join clauses the parameterized path will

 * be responsible for evaluating.

 */

ParamPathInfo *

get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel,

                          Relids required_outer)

{

    ParamPathInfo *ppi;

    Relids        joinrelids;

    List       *pclauses;

    double        rows;

    ListCell   *lc;



    /* Unparameterized paths have no ParamPathInfo */

    if (bms_is_empty(required_outer))

        return NULL;



    Assert(!bms_overlap(baserel->relids, required_outer));



    /* If we already have a PPI for this parameterization, just return it */

    foreach(lc, baserel->ppilist)

    {

        ppi = (ParamPathInfo *) lfirst(lc);

        if (bms_equal(ppi->ppi_req_outer, required_outer))

            return ppi;

    }



    /*

     * Identify all joinclauses that are movable to this base rel given this

     * parameterization.

     */

    joinrelids = bms_union(baserel->relids, required_outer);

    pclauses = NIL;

    foreach(lc, baserel->joininfo)

    {

        RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);



        if (join_clause_is_movable_into(rinfo,

                                        baserel->relids,

                                        joinrelids))

            pclauses = lappend(pclauses, rinfo);

    }



    /*

     * Add in joinclauses generated by EquivalenceClasses, too.  (These

     * necessarily satisfy join_clause_is_movable_into.)

     */

    pclauses = list_concat(pclauses,

                           generate_join_implied_equalities(root,

                                                            joinrelids,

                                                            required_outer,

                                                            baserel));



    /* Estimate the number of rows returned by the parameterized scan */

    rows = get_parameterized_baserel_size(root, baserel, pclauses);



    /* And now we can build the ParamPathInfo */

    ppi = makeNode(ParamPathInfo);

    ppi->ppi_req_outer = required_outer;

    ppi->ppi_rows = rows;

    ppi->ppi_clauses = pclauses;

    baserel->ppilist = lappend(baserel->ppilist, ppi);



    return ppi;

}

看这一小段:

    /* Unparameterized paths have no ParamPathInfo */

    if (bms_is_empty(required_outer))

        return NULL;

看看 bms_is_empty:

/*

 * bms_is_empty - is a set empty?

 *

 * This is even faster than bms_membership().

 */

bool

bms_is_empty(const Bitmapset *a)

{

    int            nwords;

    int            wordnum;



    if (a == NULL) return true;     

    nwords = a->nwords;

    for (wordnum = 0; wordnum < nwords; wordnum++)

    {

        bitmapword    w = a->words[wordnum];



        if (w != 0)

            return false;

    }

    return true;

}

 

你可能感兴趣的:(param)