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

📄 prepjointree.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
				reduce_outer_joins_pass2(j->rarg, right_state, root,										 pass_nonnullable);			}			bms_free(local_nonnullable);		}	}	else		elog(ERROR, "unrecognized node type: %d",			 (int) nodeTag(jtnode));}/* * find_nonnullable_rels *		Determine which base rels are forced nonnullable by given quals * * We don't use expression_tree_walker here because we don't want to * descend through very many kinds of nodes; only the ones we can be sure * are strict.	We can descend through the top level of implicit AND'ing, * but not through any explicit ANDs (or ORs) below that, since those are not * strict constructs.  The List case handles the top-level implicit AND list * as well as lists of arguments to strict operators/functions. */static Relidsfind_nonnullable_rels(Node *node, bool top_level){	Relids		result = NULL;	if (node == NULL)		return NULL;	if (IsA(node, Var))	{		Var		   *var = (Var *) node;		if (var->varlevelsup == 0)			result = bms_make_singleton(var->varno);	}	else if (IsA(node, List))	{		ListCell   *l;		foreach(l, (List *) node)		{			result = bms_join(result, find_nonnullable_rels(lfirst(l),															top_level));		}	}	else if (IsA(node, FuncExpr))	{		FuncExpr   *expr = (FuncExpr *) node;		if (func_strict(expr->funcid))			result = find_nonnullable_rels((Node *) expr->args, false);	}	else if (IsA(node, OpExpr))	{		OpExpr	   *expr = (OpExpr *) node;		if (op_strict(expr->opno))			result = find_nonnullable_rels((Node *) expr->args, false);	}	else if (IsA(node, BoolExpr))	{		BoolExpr   *expr = (BoolExpr *) node;		/* NOT is strict, others are not */		if (expr->boolop == NOT_EXPR)			result = find_nonnullable_rels((Node *) expr->args, false);	}	else if (IsA(node, RelabelType))	{		RelabelType *expr = (RelabelType *) node;		result = find_nonnullable_rels((Node *) expr->arg, top_level);	}	else if (IsA(node, ConvertRowtypeExpr))	{		/* not clear this is useful, but it can't hurt */		ConvertRowtypeExpr *expr = (ConvertRowtypeExpr *) node;		result = find_nonnullable_rels((Node *) expr->arg, top_level);	}	else if (IsA(node, NullTest))	{		NullTest   *expr = (NullTest *) node;		/*		 * IS NOT NULL can be considered strict, but only at top level; else		 * we might have something like NOT (x IS NOT NULL).		 */		if (top_level && expr->nulltesttype == IS_NOT_NULL)			result = find_nonnullable_rels((Node *) expr->arg, false);	}	else if (IsA(node, BooleanTest))	{		BooleanTest *expr = (BooleanTest *) node;		/*		 * Appropriate boolean tests are strict at top level.		 */		if (top_level &&			(expr->booltesttype == IS_TRUE ||			 expr->booltesttype == IS_FALSE ||			 expr->booltesttype == IS_NOT_UNKNOWN))			result = find_nonnullable_rels((Node *) expr->arg, false);	}	return result;}/* * simplify_jointree *		Attempt to simplify a query's jointree. * * If we succeed in pulling up a subquery then we might form a jointree * in which a FromExpr is a direct child of another FromExpr.  In that * case we can consider collapsing the two FromExprs into one.	This is * an optional conversion, since the planner will work correctly either * way.  But we may find a better plan (at the cost of more planning time) * if we merge the two nodes, creating a single join search space out of * two.  To allow the user to trade off planning time against plan quality, * we provide a control parameter from_collapse_limit that limits the size * of the join search space that can be created this way. * * We also consider flattening explicit inner JOINs into FromExprs (which * will in turn allow them to be merged into parent FromExprs).  The tradeoffs * here are the same as for flattening FromExprs, but we use a different * control parameter so that the user can use explicit JOINs to control the * join order even when they are inner JOINs. * * NOTE: don't try to do this in the same jointree scan that does subquery * pullup!	Since we're changing the jointree structure here, that wouldn't * work reliably --- see comments for pull_up_subqueries(). */Node *simplify_jointree(PlannerInfo *root, Node *jtnode){	if (jtnode == NULL)		return NULL;	if (IsA(jtnode, RangeTblRef))	{		/* nothing to do here... */	}	else if (IsA(jtnode, FromExpr))	{		FromExpr   *f = (FromExpr *) jtnode;		List	   *newlist = NIL;		int			children_remaining;		ListCell   *l;		children_remaining = list_length(f->fromlist);		foreach(l, f->fromlist)		{			Node	   *child = (Node *) lfirst(l);			children_remaining--;			/* Recursively simplify this child... */			child = simplify_jointree(root, child);			/* Now, is it a FromExpr? */			if (child && IsA(child, FromExpr))			{				/*				 * Yes, so do we want to merge it into parent?	Always do so				 * if child has just one element (since that doesn't make the				 * parent's list any longer).  Otherwise merge if the				 * resulting join list would be no longer than				 * from_collapse_limit.				 */				FromExpr   *subf = (FromExpr *) child;				int			childlen = list_length(subf->fromlist);				int			myothers = list_length(newlist) + children_remaining;				if (childlen <= 1 ||					(childlen + myothers) <= from_collapse_limit)				{					newlist = list_concat(newlist, subf->fromlist);					/*					 * By now, the quals have been converted to implicit-AND					 * lists, so we just need to join the lists.  NOTE: we put					 * the pulled-up quals first.					 */					f->quals = (Node *) list_concat((List *) subf->quals,													(List *) f->quals);				}				else					newlist = lappend(newlist, child);			}			else				newlist = lappend(newlist, child);		}		f->fromlist = newlist;	}	else if (IsA(jtnode, JoinExpr))	{		JoinExpr   *j = (JoinExpr *) jtnode;		/* Recursively simplify the children... */		j->larg = simplify_jointree(root, j->larg);		j->rarg = simplify_jointree(root, j->rarg);		/*		 * If it is an outer join, we must not flatten it.	An inner join is		 * semantically equivalent to a FromExpr; we convert it to one,		 * allowing it to be flattened into its parent, if the resulting		 * FromExpr would have no more than join_collapse_limit members.		 */		if (j->jointype == JOIN_INNER && join_collapse_limit > 1)		{			int			leftlen,						rightlen;			if (j->larg && IsA(j->larg, FromExpr))				leftlen = list_length(((FromExpr *) j->larg)->fromlist);			else				leftlen = 1;			if (j->rarg && IsA(j->rarg, FromExpr))				rightlen = list_length(((FromExpr *) j->rarg)->fromlist);			else				rightlen = 1;			if ((leftlen + rightlen) <= join_collapse_limit)			{				FromExpr   *f = makeNode(FromExpr);				f->fromlist = NIL;				f->quals = NULL;				if (j->larg && IsA(j->larg, FromExpr))				{					FromExpr   *subf = (FromExpr *) j->larg;					f->fromlist = subf->fromlist;					f->quals = subf->quals;				}				else					f->fromlist = list_make1(j->larg);				if (j->rarg && IsA(j->rarg, FromExpr))				{					FromExpr   *subf = (FromExpr *) j->rarg;					f->fromlist = list_concat(f->fromlist,											  subf->fromlist);					f->quals = (Node *) list_concat((List *) f->quals,													(List *) subf->quals);				}				else					f->fromlist = lappend(f->fromlist, j->rarg);				/* pulled-up quals first */				f->quals = (Node *) list_concat((List *) f->quals,												(List *) j->quals);				return (Node *) f;			}		}	}	else		elog(ERROR, "unrecognized node type: %d",			 (int) nodeTag(jtnode));	return jtnode;}/* * fix_in_clause_relids: update RT-index sets of InClauseInfo nodes * * When we pull up a subquery, any InClauseInfo references to the subquery's * RT index have to be replaced by the set of substituted relids. * * We assume we may modify the InClauseInfo nodes in-place. */static voidfix_in_clause_relids(List *in_info_list, int varno, Relids subrelids){	ListCell   *l;	foreach(l, in_info_list)	{		InClauseInfo *ininfo = (InClauseInfo *) lfirst(l);		if (bms_is_member(varno, ininfo->lefthand))		{			ininfo->lefthand = bms_del_member(ininfo->lefthand, varno);			ininfo->lefthand = bms_add_members(ininfo->lefthand, subrelids);		}		if (bms_is_member(varno, ininfo->righthand))		{			ininfo->righthand = bms_del_member(ininfo->righthand, varno);			ininfo->righthand = bms_add_members(ininfo->righthand, subrelids);		}	}}/* * get_relids_in_jointree: get set of base RT indexes present in a jointree */Relidsget_relids_in_jointree(Node *jtnode){	Relids		result = NULL;	if (jtnode == NULL)		return result;	if (IsA(jtnode, RangeTblRef))	{		int			varno = ((RangeTblRef *) jtnode)->rtindex;		result = bms_make_singleton(varno);	}	else if (IsA(jtnode, FromExpr))	{		FromExpr   *f = (FromExpr *) jtnode;		ListCell   *l;		foreach(l, f->fromlist)		{			result = bms_join(result,							  get_relids_in_jointree(lfirst(l)));		}	}	else if (IsA(jtnode, JoinExpr))	{		JoinExpr   *j = (JoinExpr *) jtnode;		/* join's own RT index is not wanted in result */		result = get_relids_in_jointree(j->larg);		result = bms_join(result, get_relids_in_jointree(j->rarg));	}	else		elog(ERROR, "unrecognized node type: %d",			 (int) nodeTag(jtnode));	return result;}/* * get_relids_for_join: get set of base RT indexes making up a join * * NB: this will not work reliably after simplify_jointree() is run, * since that may eliminate join nodes from the jointree. */Relidsget_relids_for_join(PlannerInfo *root, int joinrelid){	Node	   *jtnode;	jtnode = find_jointree_node_for_rel((Node *) root->parse->jointree,										joinrelid);	if (!jtnode)		elog(ERROR, "could not find join node %d", joinrelid);	return get_relids_in_jointree(jtnode);}/* * find_jointree_node_for_rel: locate jointree node for a base or join RT index * * Returns NULL if not found */static Node *find_jointree_node_for_rel(Node *jtnode, int relid){	if (jtnode == NULL)		return NULL;	if (IsA(jtnode, RangeTblRef))	{		int			varno = ((RangeTblRef *) jtnode)->rtindex;		if (relid == varno)			return jtnode;	}	else if (IsA(jtnode, FromExpr))	{		FromExpr   *f = (FromExpr *) jtnode;		ListCell   *l;		foreach(l, f->fromlist)		{			jtnode = find_jointree_node_for_rel(lfirst(l), relid);			if (jtnode)				return jtnode;		}	}	else if (IsA(jtnode, JoinExpr))	{		JoinExpr   *j = (JoinExpr *) jtnode;		if (relid == j->rtindex)			return jtnode;		jtnode = find_jointree_node_for_rel(j->larg, relid);		if (jtnode)			return jtnode;		jtnode = find_jointree_node_for_rel(j->rarg, relid);		if (jtnode)			return jtnode;	}	else		elog(ERROR, "unrecognized node type: %d",			 (int) nodeTag(jtnode));	return NULL;}

⌨️ 快捷键说明

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