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

📄 restrictinfo.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
	restrictinfo->eval_cost.startup = -1;	restrictinfo->this_selec = -1;	restrictinfo->mergejoinoperator = InvalidOid;	restrictinfo->left_sortop = InvalidOid;	restrictinfo->right_sortop = InvalidOid;	restrictinfo->left_pathkey = NIL;	restrictinfo->right_pathkey = NIL;	restrictinfo->left_mergescansel = -1;	restrictinfo->right_mergescansel = -1;	restrictinfo->hashjoinoperator = InvalidOid;	restrictinfo->left_bucketsize = -1;	restrictinfo->right_bucketsize = -1;	return restrictinfo;}/* * Recursively insert sub-RestrictInfo nodes into a boolean expression. * * We put RestrictInfos above simple (non-AND/OR) clauses and above * sub-OR clauses, but not above sub-AND clauses, because there's no need. * This may seem odd but it is closely related to the fact that we use * implicit-AND lists at top level of RestrictInfo lists.  Only ORs and * simple clauses are valid RestrictInfos. * * The given required_relids are attached to our top-level output, * but any OR-clause constituents are allowed to default to just the * contained rels. */static Expr *make_sub_restrictinfos(Expr *clause,					   bool is_pushed_down, bool outerjoin_delayed,					   Relids required_relids){	if (or_clause((Node *) clause))	{		List	   *orlist = NIL;		ListCell   *temp;		foreach(temp, ((BoolExpr *) clause)->args)			orlist = lappend(orlist,							 make_sub_restrictinfos(lfirst(temp),													is_pushed_down,													outerjoin_delayed,													NULL));		return (Expr *) make_restrictinfo_internal(clause,												   make_orclause(orlist),												   is_pushed_down,												   outerjoin_delayed,												   required_relids);	}	else if (and_clause((Node *) clause))	{		List	   *andlist = NIL;		ListCell   *temp;		foreach(temp, ((BoolExpr *) clause)->args)			andlist = lappend(andlist,							  make_sub_restrictinfos(lfirst(temp),													 is_pushed_down,													 outerjoin_delayed,													 required_relids));		return make_andclause(andlist);	}	else		return (Expr *) make_restrictinfo_internal(clause,												   NULL,												   is_pushed_down,												   outerjoin_delayed,												   required_relids);}/* * restriction_is_or_clause * * Returns t iff the restrictinfo node contains an 'or' clause. */boolrestriction_is_or_clause(RestrictInfo *restrictinfo){	if (restrictinfo->orclause != NULL)		return true;	else		return false;}/* * get_actual_clauses * * Returns a list containing the bare clauses from 'restrictinfo_list'. */List *get_actual_clauses(List *restrictinfo_list){	List	   *result = NIL;	ListCell   *temp;	foreach(temp, restrictinfo_list)	{		RestrictInfo *rinfo = (RestrictInfo *) lfirst(temp);		Assert(IsA(rinfo, RestrictInfo));		result = lappend(result, rinfo->clause);	}	return result;}/* * get_actual_join_clauses * * Extract clauses from 'restrictinfo_list', separating those that * syntactically match the join level from those that were pushed down. */voidget_actual_join_clauses(List *restrictinfo_list,						List **joinquals, List **otherquals){	ListCell   *temp;	*joinquals = NIL;	*otherquals = NIL;	foreach(temp, restrictinfo_list)	{		RestrictInfo *clause = (RestrictInfo *) lfirst(temp);		if (clause->is_pushed_down)			*otherquals = lappend(*otherquals, clause->clause);		else			*joinquals = lappend(*joinquals, clause->clause);	}}/* * remove_redundant_join_clauses * * Given a list of RestrictInfo clauses that are to be applied in a join, * remove any duplicate or redundant clauses. * * We must eliminate duplicates when forming the restrictlist for a joinrel, * 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. * * The result is a fresh List, but it points to the same member nodes * as were in the input. */List *remove_redundant_join_clauses(PlannerInfo *root, List *restrictinfo_list,							  bool isouterjoin){	List	   *result = NIL;	ListCell   *item;	QualCost	cost;	/*	 * If there are any redundant clauses, we want to eliminate the ones that	 * are more expensive in favor of the ones that are less so. Run	 * cost_qual_eval() to ensure the eval_cost fields are set up.	 */	cost_qual_eval(&cost, restrictinfo_list);	/*	 * We don't have enough knowledge yet to be able to estimate the number of	 * times a clause might be evaluated, so it's hard to weight the startup	 * and per-tuple costs appropriately.  For now just weight 'em the same.	 */#define CLAUSECOST(r)  ((r)->eval_cost.startup + (r)->eval_cost.per_tuple)	foreach(item, restrictinfo_list)	{		RestrictInfo *rinfo = (RestrictInfo *) lfirst(item);		RestrictInfo *prevrinfo;		/* is it redundant with any prior clause? */		prevrinfo = join_clause_is_redundant(root, rinfo, result, isouterjoin);		if (prevrinfo == NULL)		{			/* no, so add it to result list */			result = lappend(result, rinfo);		}		else if (CLAUSECOST(rinfo) < CLAUSECOST(prevrinfo))		{			/* keep this one, drop the previous one */			result = list_delete_ptr(result, prevrinfo);			result = lappend(result, rinfo);		}		/* else, drop this one */	}	return result;}/* * select_nonredundant_join_clauses * * Given a list of RestrictInfo clauses that are to be applied in a join, * select the ones that are not redundant with any clause in the * reference_list. * * This is similar to remove_redundant_join_clauses, but we are looking for * redundancies with a separate list of clauses (i.e., clauses that have * already been applied below the join itself). * * Note that we assume the given restrictinfo_list has already been checked * for local redundancies, so we don't check again. */List *select_nonredundant_join_clauses(PlannerInfo *root,								 List *restrictinfo_list,								 List *reference_list,								 bool isouterjoin){	List	   *result = NIL;	ListCell   *item;	foreach(item, restrictinfo_list)	{		RestrictInfo *rinfo = (RestrictInfo *) lfirst(item);		/* drop it if redundant with any reference clause */		if (join_clause_is_redundant(root, rinfo, reference_list, isouterjoin) != NULL)			continue;		/* otherwise, add it to result list */		result = lappend(result, rinfo);	}	return result;}/* * join_clause_is_redundant *		If rinfo is redundant with any clause in reference_list, *		return one such clause; otherwise return NULL. * * This is the guts of both remove_redundant_join_clauses and * select_nonredundant_join_clauses.  See the docs above for motivation. * * We can detect redundant mergejoinable clauses very cheaply by using their * left and right pathkeys, which uniquely identify the sets of equijoined * variables in question.  All the members of a pathkey set that are in the * left relation have already been forced to be equal; likewise for those in * the right relation.	So, we need to have only one clause that checks * equality between any set member on the left and any member on the right; * by transitivity, all the rest are then equal. * * However, clauses that are of the form "var expr = const expr" cannot be * eliminated as redundant.  This is because when there are const expressions * in a pathkey set, generate_implied_equalities() suppresses "var = var" * clauses in favor of "var = const" clauses.  We cannot afford to drop any * of the latter, even though they might seem redundant by the pathkey * membership test. * * Weird special case: if we have two clauses that seem redundant * except one is pushed down into an outer join and the other isn't, * then they're not really redundant, because one constrains the * joined rows after addition of null fill rows, and the other doesn't. */static RestrictInfo *join_clause_is_redundant(PlannerInfo *root,						 RestrictInfo *rinfo,						 List *reference_list,						 bool isouterjoin){	ListCell   *refitem;	/* always consider exact duplicates redundant */	foreach(refitem, reference_list)	{		RestrictInfo *refrinfo = (RestrictInfo *) lfirst(refitem);		if (equal(rinfo, refrinfo))			return refrinfo;	}	/* check for redundant merge clauses */	if (rinfo->mergejoinoperator != InvalidOid)	{		/* do the cheap test first: is it a "var = const" clause? */		if (bms_is_empty(rinfo->left_relids) ||			bms_is_empty(rinfo->right_relids))			return NULL;		/* var = const, so not redundant */		cache_mergeclause_pathkeys(root, rinfo);		foreach(refitem, reference_list)		{			RestrictInfo *refrinfo = (RestrictInfo *) lfirst(refitem);			if (refrinfo->mergejoinoperator != InvalidOid)			{				cache_mergeclause_pathkeys(root, refrinfo);				if (rinfo->left_pathkey == refrinfo->left_pathkey &&					rinfo->right_pathkey == refrinfo->right_pathkey &&					(rinfo->is_pushed_down == refrinfo->is_pushed_down ||					 !isouterjoin))				{					/* Yup, it's redundant */					return refrinfo;				}			}		}	}	/* otherwise, not redundant */	return NULL;}

⌨️ 快捷键说明

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