Search code examples
postgresqlpostgresql-9.3

How to get table names or ID from RelOptInfo in PostgreSQL?


As I need to do some experimental changes to the planner of PostgreSQL, for example, in the cost function, I want to add different parameters for various tables, but how can I know the which table I'm operation?

I'm pretty sure that the FOR loop below is to evaluate each FROM table, but How can I get the table OID or name from PlannerInfo *root?

/*
* set_base_rel_sizes
*     Set the size estimates (rows and widths) for each base-relation entry.
*
* We do this in a separate pass over the base rels so that rowcount
* estimates are available for parameterized path generation.
*/
static void
 set_base_rel_sizes(PlannerInfo *root)
 {
    Index       rti;
    for (rti = 1; rti < root->simple_rel_array_size; rti++)
   {
    RelOptInfo *rel = root->simple_rel_array[rti];
    /* there may be empty slots corresponding to non-baserel RTEs */
    if (rel == NULL)
        continue;

    Assert(rel->relid == rti);      /* sanity check on array */

    /* ignore RTEs that are "other rels" */
    if (rel->reloptkind != RELOPT_BASEREL)
        continue;

    set_rel_size(root, rel, rti, root->simple_rte_array[rti]);
}
}

and

/*----------
* PlannerInfo
*       Per-query information for planning/optimization
*
* This struct is conventionally called "root" in all the planner routines.
* It holds links to all of the planner's working state, in addition to the
* original Query.   Note that at present the planner extensively modifies
* the passed-in Query data structure; someday that should stop.
*----------
*/
typedef struct PlannerInfo
{
 NodeTag        type;

Query      *parse;          /* the Query being planned */

PlannerGlobal *glob;        /* global info for current planner run */

Index       query_level;    /* 1 at the outermost Query */

struct PlannerInfo *parent_root;    /* NULL at outermost Query */

List       *plan_params;    /* list of PlannerParamItems, see below */

/*
 * simple_rel_array holds pointers to "base rels" and "other rels" (see
 * comments for RelOptInfo for more info).  It is indexed by rangetable
 * index (so entry 0 is always wasted).  Entries can be NULL when an RTE
 * does not correspond to a base relation, such as a join RTE or an
 * unreferenced view RTE; or if the RelOptInfo hasn't been made yet.
 */
struct RelOptInfo **simple_rel_array;       /* All 1-rel RelOptInfos */
int         simple_rel_array_size;  /* allocated size of array */

/*
 * simple_rte_array is the same length as simple_rel_array and holds
 * pointers to the associated rangetable entries.  This lets us avoid
 * rt_fetch(), which can be a bit slow once large inheritance sets have
 * been expanded.
 */
RangeTblEntry **simple_rte_array;   /* rangetable as an array */

/*
 * all_baserels is a Relids set of all base relids (but not "other"
 * relids) in the query; that is, the Relids identifier of the final join
 * we need to form.  This is computed in make_one_rel, just before we
 * start making Paths.
 */
Relids      all_baserels;

/*
 * join_rel_list is a list of all join-relation RelOptInfos we have
 * considered in this planning run.  For small problems we just scan the
 * list to do lookups, but when there are many join relations we build a
 * hash table for faster lookups.  The hash table is present and valid
 * when join_rel_hash is not NULL.  Note that we still maintain the list
 * even when using the hash table for lookups; this simplifies life for
 * GEQO.
 */
List       *join_rel_list;  /* list of join-relation RelOptInfos */
struct HTAB *join_rel_hash; /* optional hashtable for join relations */

/*
 * When doing a dynamic-programming-style join search, join_rel_level[k]
 * is a list of all join-relation RelOptInfos of level k, and
 * join_cur_level is the current level.  New join-relation RelOptInfos are
 * automatically added to the join_rel_level[join_cur_level] list.
 * join_rel_level is NULL if not in use.
 */
List      **join_rel_level; /* lists of join-relation RelOptInfos */
int         join_cur_level; /* index of list being extended */

List       *init_plans;     /* init SubPlans for query */

List       *cte_plan_ids;   /* per-CTE-item list of subplan IDs */

List       *eq_classes;     /* list of active EquivalenceClasses */

List       *canon_pathkeys; /* list of "canonical" PathKeys */

List       *left_join_clauses;      /* list of RestrictInfos for
                                     * mergejoinable outer join clauses
                                     * w/nonnullable var on left */

List       *right_join_clauses;     /* list of RestrictInfos for
                                     * mergejoinable outer join clauses
                                     * w/nonnullable var on right */

List       *full_join_clauses;      /* list of RestrictInfos for
                                     * mergejoinable full join clauses */

List       *join_info_list; /* list of SpecialJoinInfos */

List       *lateral_info_list;      /* list of LateralJoinInfos */

List       *append_rel_list;    /* list of AppendRelInfos */

List       *rowMarks;       /* list of PlanRowMarks */

List       *placeholder_list;       /* list of PlaceHolderInfos */

List       *query_pathkeys; /* desired pathkeys for query_planner(), and
                             * actual pathkeys after planning */

List       *group_pathkeys; /* groupClause pathkeys, if any */
List       *window_pathkeys;    /* pathkeys of bottom window, if any */
List       *distinct_pathkeys;      /* distinctClause pathkeys, if any */
List       *sort_pathkeys;  /* sortClause pathkeys, if any */

List       *minmax_aggs;    /* List of MinMaxAggInfos */

List       *initial_rels;   /* RelOptInfos we are now trying to join */

MemoryContext planner_cxt;  /* context holding PlannerInfo */

double      total_table_pages;      /* # of pages in all tables of query */

double      tuple_fraction; /* tuple_fraction passed to query_planner */
double      limit_tuples;   /* limit_tuples passed to query_planner */

bool        hasInheritedTarget;     /* true if parse->resultRelation is an
                                     * inheritance child rel */
bool        hasJoinRTEs;    /* true if any RTEs are RTE_JOIN kind */
bool        hasLateralRTEs; /* true if any RTEs are marked LATERAL */
bool        hasHavingQual;  /* true if havingQual was non-null */
bool        hasPseudoConstantQuals; /* true if any RestrictInfo has
                                     * pseudoconstant = true */
bool        hasRecursion;   /* true if planning a recursive WITH item */

/* These fields are used only when hasRecursion is true: */
int         wt_param_id;    /* PARAM_EXEC ID for the work table */
struct Plan *non_recursive_plan;    /* plan for non-recursive term */

/* These fields are workspace for createplan.c */
Relids      curOuterRels;   /* outer rels above current node */
List       *curOuterParams; /* not-yet-assigned NestLoopParams */

/* optional private data for join_search_hook, e.g., GEQO */
void       *join_search_private;

/* This will be in a saner place in 9.4: */
Relids      nullable_baserels;
} PlannerInfo;

typedef struct RelOptInfo
{
NodeTag     type;

RelOptKind  reloptkind;

/* all relations included in this RelOptInfo */
Relids      relids;         /* set of base relids (rangetable indexes) */

/* size estimates generated by planner */
double      rows;           /* estimated number of result tuples */
int         width;          /* estimated avg width of result tuples */

/* per-relation planner control flags */
bool        consider_startup;       /* keep cheap-startup-cost paths? */

/* materialization information */
List       *reltargetlist;  /* Vars to be output by scan of relation */
List       *pathlist;       /* Path structures */
List       *ppilist;        /* ParamPathInfos used in pathlist */
struct Path *cheapest_startup_path;
struct Path *cheapest_total_path;
struct Path *cheapest_unique_path;
List       *cheapest_parameterized_paths;

/* information about a base rel (not set for join rels!) */
Index       relid;
Oid         reltablespace;  /* containing tablespace */
RTEKind     rtekind;        /* RELATION, SUBQUERY, or FUNCTION */
AttrNumber  min_attr;       /* smallest attrno of rel (often <0) */
AttrNumber  max_attr;       /* largest attrno of rel */
Relids     *attr_needed;    /* array indexed [min_attr .. max_attr] */
int32      *attr_widths;    /* array indexed [min_attr .. max_attr] */
List       *lateral_vars;   /* LATERAL Vars and PHVs referenced by rel */
Relids      lateral_relids; /* minimum parameterization of rel */
Relids      lateral_referencers;    /* rels that reference me laterally */
List       *indexlist;      /* list of IndexOptInfo */
BlockNumber pages;          /* size estimates derived from pg_class */
double      tuples;
double      allvisfrac;
/* use "struct Plan" to avoid including plannodes.h here */
struct Plan *subplan;       /* if subquery */
PlannerInfo *subroot;       /* if subquery */
List       *subplan_params; /* if subquery */
/* use "struct FdwRoutine" to avoid including fdwapi.h here */
struct FdwRoutine *fdwroutine;      /* if foreign table */
void       *fdw_private;    /* if foreign table */

/* used by various scans and joins: */
List       *baserestrictinfo;       /* RestrictInfo structures (if base
                                     * rel) */
QualCost    baserestrictcost;       /* cost of evaluating the above */
List       *joininfo;       /* RestrictInfo structures for join clauses
                             * involving this rel */
bool        has_eclass_joins;       /* T means joininfo is incomplete */
} RelOptInfo;

Solution

  • You can get the table OID from root->simple_rte_array[rti]->relid which related to root->simple_rel_array[rti]