⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 relnode.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
 */RelOptInfo *build_join_rel(PlannerInfo *root,			   Relids joinrelids,			   RelOptInfo *outer_rel,			   RelOptInfo *inner_rel,			   JoinType jointype,			   List **restrictlist_ptr){	RelOptInfo *joinrel;	List	   *restrictlist;	/*	 * See if we already have a joinrel for this set of base rels.	 */	joinrel = find_join_rel(root, joinrelids);	if (joinrel)	{		/*		 * Yes, so we only need to figure the restrictlist for this particular		 * pair of component relations.		 */		if (restrictlist_ptr)			*restrictlist_ptr = build_joinrel_restrictlist(root,														   joinrel,														   outer_rel,														   inner_rel,														   jointype);		return joinrel;	}	/*	 * Nope, so make one.	 */	joinrel = makeNode(RelOptInfo);	joinrel->reloptkind = RELOPT_JOINREL;	joinrel->relids = bms_copy(joinrelids);	joinrel->rows = 0;	joinrel->width = 0;	joinrel->reltargetlist = NIL;	joinrel->pathlist = NIL;	joinrel->cheapest_startup_path = NULL;	joinrel->cheapest_total_path = NULL;	joinrel->cheapest_unique_path = NULL;	joinrel->relid = 0;			/* indicates not a baserel */	joinrel->rtekind = RTE_JOIN;	joinrel->min_attr = 0;	joinrel->max_attr = 0;	joinrel->attr_needed = NULL;	joinrel->attr_widths = NULL;	joinrel->indexlist = NIL;	joinrel->pages = 0;	joinrel->tuples = 0;	joinrel->subplan = NULL;	joinrel->baserestrictinfo = NIL;	joinrel->baserestrictcost.startup = 0;	joinrel->baserestrictcost.per_tuple = 0;	joinrel->outerjoinset = NULL;	joinrel->joininfo = NIL;	joinrel->index_outer_relids = NULL;	joinrel->index_inner_paths = NIL;	/*	 * Create a new tlist containing just the vars that need to be output from	 * this join (ie, are needed for higher joinclauses or final output).	 *	 * NOTE: the tlist order for a join rel will depend on which pair of outer	 * and inner rels we first try to build it from.  But the contents should	 * be the same regardless.	 */	build_joinrel_tlist(root, joinrel, outer_rel);	build_joinrel_tlist(root, joinrel, inner_rel);	/*	 * Construct restrict and join clause lists for the new joinrel. (The	 * caller might or might not need the restrictlist, but I need it anyway	 * for set_joinrel_size_estimates().)	 */	restrictlist = build_joinrel_restrictlist(root,											  joinrel,											  outer_rel,											  inner_rel,											  jointype);	if (restrictlist_ptr)		*restrictlist_ptr = restrictlist;	build_joinrel_joinlist(joinrel, outer_rel, inner_rel);	/*	 * Set estimates of the joinrel's size.	 */	set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,							   jointype, restrictlist);	/*	 * Add the joinrel to the query's joinrel list, and store it into the	 * auxiliary hashtable if there is one.  NB: GEQO requires us to append	 * the new joinrel to the end of the list!	 */	root->join_rel_list = lappend(root->join_rel_list, joinrel);	if (root->join_rel_hash)	{		JoinHashEntry *hentry;		bool		found;		hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,											   &(joinrel->relids),											   HASH_ENTER,											   &found);		Assert(!found);		hentry->join_rel = joinrel;	}	return joinrel;}/* * build_joinrel_tlist *	  Builds a join relation's target list. * * The join's targetlist includes all Vars of its member relations that * will still be needed above the join.  This subroutine adds all such * Vars from the specified input rel's tlist to the join rel's tlist. * * We also compute the expected width of the join's output, making use * of data that was cached at the baserel level by set_rel_width(). */static voidbuild_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,					RelOptInfo *input_rel){	Relids		relids = joinrel->relids;	ListCell   *vars;	foreach(vars, input_rel->reltargetlist)	{		Var		   *var = (Var *) lfirst(vars);		RelOptInfo *baserel;		int			ndx;		/* We can't run into any child RowExprs here */		Assert(IsA(var, Var));		/* Get the Var's original base rel */		baserel = find_base_rel(root, var->varno);		/* Is it still needed above this joinrel? */		ndx = var->varattno - baserel->min_attr;		if (bms_nonempty_difference(baserel->attr_needed[ndx], relids))		{			/* Yup, add it to the output */			joinrel->reltargetlist = lappend(joinrel->reltargetlist, var);			Assert(baserel->attr_widths[ndx] > 0);			joinrel->width += baserel->attr_widths[ndx];		}	}}/* * build_joinrel_restrictlist * build_joinrel_joinlist *	  These routines build lists of restriction and join clauses for a *	  join relation from the joininfo lists of the relations it joins. * *	  These routines are separate because the restriction list must be *	  built afresh for each pair of input sub-relations we consider, whereas *	  the join list need only be computed once for any join RelOptInfo. *	  The join list is fully determined by the set of rels making up the *	  joinrel, so we should get the same results (up to ordering) from any *	  candidate pair of sub-relations.	But the restriction list is whatever *	  is not handled in the sub-relations, so it depends on which *	  sub-relations are considered. * *	  If a join clause from an input relation refers to base rels still not *	  present in the joinrel, then it is still a join clause for the joinrel; *	  we put it into the joininfo list for the joinrel.  Otherwise, *	  the clause is now a restrict clause for the joined relation, and we *	  return it to the caller of build_joinrel_restrictlist() to be stored in *	  join paths made from this pair of sub-relations.	(It will not need to *	  be considered further up the join tree.) * *	  When building a restriction list, we eliminate redundant clauses. *	  We don't try to do that for join clause lists, since the join clauses *	  aren't really doing anything, just waiting to become part of higher *	  levels' restriction lists. * * 'joinrel' is a join relation node * 'outer_rel' and 'inner_rel' are a pair of relations that can be joined *		to form joinrel. * 'jointype' is the type of join used. * * build_joinrel_restrictlist() returns a list of relevant restrictinfos, * whereas build_joinrel_joinlist() stores its results in the joinrel's * joininfo list.  One or the other must accept each given clause! * * NB: Formerly, we made deep(!) copies of each input RestrictInfo to pass * up to the join relation.  I believe this is no longer necessary, because * RestrictInfo nodes are no longer context-dependent.	Instead, just include * the original nodes in the lists made for the join relation. */static List *build_joinrel_restrictlist(PlannerInfo *root,						   RelOptInfo *joinrel,						   RelOptInfo *outer_rel,						   RelOptInfo *inner_rel,						   JoinType jointype){	List	   *result;	List	   *rlist;	/*	 * Collect all the clauses that syntactically belong at this level.	 */	rlist = list_concat(subbuild_joinrel_restrictlist(joinrel,													  outer_rel->joininfo),						subbuild_joinrel_restrictlist(joinrel,													  inner_rel->joininfo));	/*	 * Eliminate duplicate and redundant clauses.	 *	 * We must eliminate duplicates, since we will see many of the same	 * clauses arriving from both input relations.	Also, if a clause is a	 * mergejoinable clause, it's possible that it is redundant with previous	 * clauses (see optimizer/README for discussion).  We detect that case and	 * omit the redundant clause from the result list.	 */	result = remove_redundant_join_clauses(root, rlist,										   IS_OUTER_JOIN(jointype));	list_free(rlist);	return result;}static voidbuild_joinrel_joinlist(RelOptInfo *joinrel,					   RelOptInfo *outer_rel,					   RelOptInfo *inner_rel){	subbuild_joinrel_joinlist(joinrel, outer_rel->joininfo);	subbuild_joinrel_joinlist(joinrel, inner_rel->joininfo);}static List *subbuild_joinrel_restrictlist(RelOptInfo *joinrel,							  List *joininfo_list){	List	   *restrictlist = NIL;	ListCell   *l;	foreach(l, joininfo_list)	{		RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);		if (bms_is_subset(rinfo->required_relids, joinrel->relids))		{			/*			 * This clause becomes a restriction clause for the joinrel, since			 * it refers to no outside rels.  We don't bother to check for			 * duplicates here --- build_joinrel_restrictlist will do that.			 */			restrictlist = lappend(restrictlist, rinfo);		}		else		{			/*			 * This clause is still a join clause at this level, so we ignore			 * it in this routine.			 */		}	}	return restrictlist;}static voidsubbuild_joinrel_joinlist(RelOptInfo *joinrel,						  List *joininfo_list){	ListCell   *l;	foreach(l, joininfo_list)	{		RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);		if (bms_is_subset(rinfo->required_relids, joinrel->relids))		{			/*			 * This clause becomes a restriction clause for the joinrel, since			 * it refers to no outside rels.  So we can ignore it in this			 * routine.			 */		}		else		{			/*			 * This clause is still a join clause at this level, so add it to			 * the joininfo list for the joinrel, being careful to eliminate			 * duplicates.	(Since RestrictInfo nodes are normally			 * multiply-linked rather than copied, pointer equality should be			 * a sufficient test.  If two equal() nodes should happen to sneak			 * in, no great harm is done --- they'll be detected by			 * redundant-clause testing when they reach a restriction list.)			 */			joinrel->joininfo = list_append_unique_ptr(joinrel->joininfo,													   rinfo);		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -