您的位置:首页 > 数据库

PostgreSQL在何处处理 sql查询之二十六

2013-05-29 09:36 281 查看
接前面,再次上溯一个层次,看代码(planmain.c :query_planner):

void
query_planner(PlannerInfo *root, List *tlist,
double tuple_fraction, double limit_tuples,
Path **cheapest_path, Path **sorted_path,
double *num_groups)
{
...

/*
* Make a flattened version of the rangetable for faster access (this is
* OK because the rangetable won't change any more), and set up an empty
* array for indexing base relations.
*/
setup_simple_rel_arrays(root);

/*
* Construct RelOptInfo nodes for all base relations in query, and
* indirectly for all appendrel member relations ("other rels").  This
* will give us a RelOptInfo for every "simple" (non-join) rel involved in
* the query.
*
* Note: the reason we find the rels by searching the jointree and
* appendrel list, rather than just scanning the rangetable, is that the
* rangetable may contain RTEs for rels not actively part of the query,
* for example views.  We don't want to make RelOptInfos for them.
*/
add_base_rels_to_query(root, (Node *) parse->jointree);
/*
* Examine the targetlist and join tree, adding entries to baserel
* targetlists for all referenced Vars, and generating PlaceHolderInfo
* entries for all referenced PlaceHolderVars.    Restrict and join clauses
* are added to appropriate lists belonging to the mentioned relations. We
* also build EquivalenceClasses for provably equivalent expressions. The
* SpecialJoinInfo list is also built to hold information about join order
* restrictions.  Finally, we form a target joinlist for make_one_rel() to
* work from.
*/
build_base_rel_tlists(root, tlist);

find_placeholders_in_jointree(root);

joinlist = deconstruct_jointree(root);

/*
* Reconsider any postponed outer-join quals now that we have built up
* equivalence classes.  (This could result in further additions or
* mergings of classes.)
*/
reconsider_outer_join_clauses(root);

/*
* If we formed any equivalence classes, generate additional restriction
* clauses as appropriate.    (Implied join clauses are formed on-the-fly
* later.)
*/
generate_base_implied_equalities(root);

/*
* We have completed merging equivalence sets, so it's now possible to
* convert previously generated pathkeys (in particular, the requested
* query_pathkeys) to canonical form.
*/
canonicalize_all_pathkeys(root);

/*
* Examine any "placeholder" expressions generated during subquery pullup.
* Make sure that the Vars they need are marked as needed at the relevant
* join level.    This must be done before join removal because it might
* cause Vars or placeholders to be needed above a join when they weren't
* so marked before.
*/
fix_placeholder_input_needed_levels(root);

/*
* Remove any useless outer joins.    Ideally this would be done during
* jointree preprocessing, but the necessary information isn't available
* until we've built baserel data structures and classified qual clauses.
*/
joinlist = remove_useless_joins(root, joinlist);

/*
* Now distribute "placeholders" to base rels as needed.  This has to be
* done after join removal because removal could change whether a
* placeholder is evaluatable at a base rel.
*/
add_placeholders_to_base_rels(root);
...
}


在此处,setup_simple_rel_arrays 构造了指向指针的数组(其实是指向指针数组的指针),挂在root下。 add_base_rels_to_query 要利用此数组。

看其中的代码(relnode.c):

/*
* setup_simple_rel_arrays
*      Prepare the arrays we use for quickly accessing base relations.
*/
void
setup_simple_rel_arrays(PlannerInfo *root)
{
Index        rti;
ListCell   *lc;

/* Arrays are accessed using RT indexes (1..N) */
root->simple_rel_array_size = list_length(root->parse->rtable) + 1;

/* simple_rel_array is initialized to all NULLs */
root->simple_rel_array = (RelOptInfo **)
palloc0(root->simple_rel_array_size * sizeof(RelOptInfo *));
...

}


add_base_rels_to_query :(initsplan.c)

void
add_base_rels_to_query(PlannerInfo *root, Node *jtnode)
{
if (jtnode == NULL)
return;
if (IsA(jtnode, RangeTblRef))
{
int    varno = ((RangeTblRef *) jtnode)->rtindex;
(void) build_simple_rel(root, varno, RELOPT_BASEREL);
}
else if (IsA(jtnode, FromExpr))
{
FromExpr   *f = (FromExpr *) jtnode;
ListCell   *l;

foreach(l, f->fromlist)
add_base_rels_to_query(root, lfirst(l));
}
else if (IsA(jtnode, JoinExpr))
{
JoinExpr   *j = (JoinExpr *) jtnode;

add_base_rels_to_query(root, j->larg);
add_base_rels_to_query(root, j->rarg);
}
else
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(jtnode));
}


build_simple_rel:

RelOptInfo *
build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
{
RelOptInfo *rel;
RangeTblEntry *rte;

/* Rel should not exist already */
Assert(relid > 0 && relid < root->simple_rel_array_size);
if (root->simple_rel_array[relid] != NULL)
elog(ERROR, "rel %d already exists", relid);
...

/* Check type of rtable entry */
switch (rte->rtekind)
{
case RTE_RELATION:
/* Table --- retrieve statistics from the system catalogs */
get_relation_info(root, rte->relid, rte->inh, rel);
break;
case RTE_SUBQUERY:
case RTE_FUNCTION:
case RTE_VALUES:
case RTE_CTE:

/*
* Subquery, function, or values list --- set up attr range and
* arrays
*
* Note: 0 is included in range to support whole-row Vars
*/
rel->min_attr = 0;
rel->max_attr = list_length(rte->eref->colnames);
rel->attr_needed = (Relids *)
palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));
rel->attr_widths = (int32 *)
palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));
break;
default:
elog(ERROR, "unrecognized RTE kind: %d",
(int) rte->rtekind);
break;
}

/* Save the finished struct in the query's simple_rel_array */
root->simple_rel_array[relid] = rel;

...

return rel;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: