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

📄 joinrels.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
	List	   *result = NIL;	ListCell   *i;	for_each_cell(i, other_rels)	{		RelOptInfo *other_rel = (RelOptInfo *) lfirst(i);		if (!bms_overlap(other_rel->relids, old_rel->relids))		{			RelOptInfo *jrel;			jrel = make_join_rel(root, old_rel, other_rel, JOIN_INNER);			/*			 * As long as given other_rels are distinct, don't need to test to			 * see if jrel is already part of output list.			 */			if (jrel)				result = lcons(jrel, result);		}	}	return result;}/* * is_inside_IN *		Detect whether the specified relation is inside an IN (sub-SELECT). * * Note that we are actually only interested in rels that have been pulled up * out of an IN, so the routine name is a slight misnomer. */static boolis_inside_IN(PlannerInfo *root, RelOptInfo *rel){	ListCell   *l;	foreach(l, root->in_info_list)	{		InClauseInfo *ininfo = (InClauseInfo *) lfirst(l);		if (bms_is_subset(rel->relids, ininfo->righthand))			return true;	}	return false;}/* * make_jointree_rel *		Find or build a RelOptInfo join rel representing a specific *		jointree item.	For JoinExprs, we only consider the construction *		path that corresponds exactly to what the user wrote. */RelOptInfo *make_jointree_rel(PlannerInfo *root, Node *jtnode){	if (IsA(jtnode, RangeTblRef))	{		int			varno = ((RangeTblRef *) jtnode)->rtindex;		return find_base_rel(root, varno);	}	else if (IsA(jtnode, FromExpr))	{		FromExpr   *f = (FromExpr *) jtnode;		/* Recurse back to multi-way-join planner */		return make_fromexpr_rel(root, f);	}	else if (IsA(jtnode, JoinExpr))	{		JoinExpr   *j = (JoinExpr *) jtnode;		RelOptInfo *rel,				   *lrel,				   *rrel;		/* Recurse */		lrel = make_jointree_rel(root, j->larg);		rrel = make_jointree_rel(root, j->rarg);		/* Make this join rel */		rel = make_join_rel(root, lrel, rrel, j->jointype);		if (rel == NULL)		/* oops */			elog(ERROR, "invalid join order");		/*		 * Since we are only going to consider this one way to do it, we're		 * done generating Paths for this joinrel and can now select the		 * cheapest.  In fact we *must* do so now, since next level up will		 * need it!		 */		set_cheapest(rel);#ifdef OPTIMIZER_DEBUG		debug_print_rel(root, rel);#endif		return rel;	}	else		elog(ERROR, "unrecognized node type: %d",			 (int) nodeTag(jtnode));	return NULL;				/* keep compiler quiet */}/* * make_join_rel *	   Find or create a join RelOptInfo that represents the join of *	   the two given rels, and add to it path information for paths *	   created with the two rels as outer and inner rel. *	   (The join rel may already contain paths generated from other *	   pairs of rels that add up to the same set of base rels.) * * NB: will return NULL if attempted join is not valid.  This can only * happen when working with IN clauses that have been turned into joins. */RelOptInfo *make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,			  JoinType jointype){	Relids		joinrelids;	RelOptInfo *joinrel;	List	   *restrictlist;	/* We should never try to join two overlapping sets of rels. */	Assert(!bms_overlap(rel1->relids, rel2->relids));	/* Construct Relids set that identifies the joinrel. */	joinrelids = bms_union(rel1->relids, rel2->relids);	/*	 * If we are implementing IN clauses as joins, there are some joins that	 * are illegal.  Check to see if the proposed join is trouble. We can skip	 * the work if looking at an outer join, however, because only top-level	 * joins might be affected.	 */	if (jointype == JOIN_INNER)	{		ListCell   *l;		foreach(l, root->in_info_list)		{			InClauseInfo *ininfo = (InClauseInfo *) lfirst(l);			/*			 * This IN clause is not relevant unless its RHS overlaps the			 * proposed join.  (Check this first as a fast path for dismissing			 * most irrelevant INs quickly.)			 */			if (!bms_overlap(ininfo->righthand, joinrelids))				continue;			/*			 * If we are still building the IN clause's RHS, then this IN			 * clause isn't relevant yet.			 */			if (bms_is_subset(joinrelids, ininfo->righthand))				continue;			/*			 * Cannot join if proposed join contains rels not in the RHS *and*			 * contains only part of the RHS.  We must build the complete RHS			 * (subselect's join) before it can be joined to rels outside the			 * subselect.			 */			if (!bms_is_subset(ininfo->righthand, joinrelids))			{				bms_free(joinrelids);				return NULL;			}			/*			 * At this point we are considering a join of the IN's RHS to some			 * other rel(s).			 *			 * If we already joined IN's RHS to any other rels in either input			 * path, then this join is not constrained (the necessary work was			 * done at the lower level where that join occurred).			 */			if (bms_is_subset(ininfo->righthand, rel1->relids) &&				!bms_equal(ininfo->righthand, rel1->relids))				continue;			if (bms_is_subset(ininfo->righthand, rel2->relids) &&				!bms_equal(ininfo->righthand, rel2->relids))				continue;			/*			 * JOIN_IN technique will work if outerrel includes LHS and			 * innerrel is exactly RHS; conversely JOIN_REVERSE_IN handles			 * RHS/LHS.			 *			 * JOIN_UNIQUE_OUTER will work if outerrel is exactly RHS;			 * conversely JOIN_UNIQUE_INNER will work if innerrel is exactly			 * RHS.			 *			 * But none of these will work if we already found another IN that			 * needs to trigger here.			 */			if (jointype != JOIN_INNER)			{				bms_free(joinrelids);				return NULL;			}			if (bms_is_subset(ininfo->lefthand, rel1->relids) &&				bms_equal(ininfo->righthand, rel2->relids))				jointype = JOIN_IN;			else if (bms_is_subset(ininfo->lefthand, rel2->relids) &&					 bms_equal(ininfo->righthand, rel1->relids))				jointype = JOIN_REVERSE_IN;			else if (bms_equal(ininfo->righthand, rel1->relids))				jointype = JOIN_UNIQUE_OUTER;			else if (bms_equal(ininfo->righthand, rel2->relids))				jointype = JOIN_UNIQUE_INNER;			else			{				/* invalid join path */				bms_free(joinrelids);				return NULL;			}		}	}	/*	 * Find or build the join RelOptInfo, and compute the restrictlist that	 * goes with this particular joining.	 */	joinrel = build_join_rel(root, joinrelids, rel1, rel2, jointype,							 &restrictlist);	/*	 * Consider paths using each rel as both outer and inner.	 */	switch (jointype)	{		case JOIN_INNER:			add_paths_to_joinrel(root, joinrel, rel1, rel2, JOIN_INNER,								 restrictlist);			add_paths_to_joinrel(root, joinrel, rel2, rel1, JOIN_INNER,								 restrictlist);			break;		case JOIN_LEFT:			add_paths_to_joinrel(root, joinrel, rel1, rel2, JOIN_LEFT,								 restrictlist);			add_paths_to_joinrel(root, joinrel, rel2, rel1, JOIN_RIGHT,								 restrictlist);			break;		case JOIN_FULL:			add_paths_to_joinrel(root, joinrel, rel1, rel2, JOIN_FULL,								 restrictlist);			add_paths_to_joinrel(root, joinrel, rel2, rel1, JOIN_FULL,								 restrictlist);			break;		case JOIN_RIGHT:			add_paths_to_joinrel(root, joinrel, rel1, rel2, JOIN_RIGHT,								 restrictlist);			add_paths_to_joinrel(root, joinrel, rel2, rel1, JOIN_LEFT,								 restrictlist);			break;		case JOIN_IN:			add_paths_to_joinrel(root, joinrel, rel1, rel2, JOIN_IN,								 restrictlist);			/* REVERSE_IN isn't supported by joinpath.c */			add_paths_to_joinrel(root, joinrel, rel1, rel2, JOIN_UNIQUE_INNER,								 restrictlist);			add_paths_to_joinrel(root, joinrel, rel2, rel1, JOIN_UNIQUE_OUTER,								 restrictlist);			break;		case JOIN_REVERSE_IN:			/* REVERSE_IN isn't supported by joinpath.c */			add_paths_to_joinrel(root, joinrel, rel2, rel1, JOIN_IN,								 restrictlist);			add_paths_to_joinrel(root, joinrel, rel1, rel2, JOIN_UNIQUE_OUTER,								 restrictlist);			add_paths_to_joinrel(root, joinrel, rel2, rel1, JOIN_UNIQUE_INNER,								 restrictlist);			break;		case JOIN_UNIQUE_OUTER:			add_paths_to_joinrel(root, joinrel, rel1, rel2, JOIN_UNIQUE_OUTER,								 restrictlist);			add_paths_to_joinrel(root, joinrel, rel2, rel1, JOIN_UNIQUE_INNER,								 restrictlist);			break;		case JOIN_UNIQUE_INNER:			add_paths_to_joinrel(root, joinrel, rel1, rel2, JOIN_UNIQUE_INNER,								 restrictlist);			add_paths_to_joinrel(root, joinrel, rel2, rel1, JOIN_UNIQUE_OUTER,								 restrictlist);			break;		default:			elog(ERROR, "unrecognized join type: %d",				 (int) jointype);			break;	}	bms_free(joinrelids);	return joinrel;}

⌨️ 快捷键说明

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