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

📄 restrictinfo.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * restrictinfo.c *	  RestrictInfo node manipulation routines. * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.41.2.4 2006/04/07 17:05:47 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "optimizer/clauses.h"#include "optimizer/cost.h"#include "optimizer/paths.h"#include "optimizer/predtest.h"#include "optimizer/restrictinfo.h"#include "optimizer/var.h"static RestrictInfo *make_restrictinfo_internal(Expr *clause,						   Expr *orclause,						   bool is_pushed_down,						   bool outerjoin_delayed,						   Relids required_relids);static Expr *make_sub_restrictinfos(Expr *clause,					   bool is_pushed_down,					   bool outerjoin_delayed,					   Relids required_relids);static RestrictInfo *join_clause_is_redundant(PlannerInfo *root,						 RestrictInfo *rinfo,						 List *reference_list,						 bool isouterjoin);/* * make_restrictinfo * * Build a RestrictInfo node containing the given subexpression. * * The is_pushed_down and outerjoin_delayed flags must be supplied by the * caller.	required_relids can be NULL, in which case it defaults to the * actual clause contents (i.e., clause_relids). * * We initialize fields that depend only on the given subexpression, leaving * others that depend on context (or may never be needed at all) to be filled * later. */RestrictInfo *make_restrictinfo(Expr *clause,				  bool is_pushed_down,				  bool outerjoin_delayed,				  Relids required_relids){	/*	 * If it's an OR clause, build a modified copy with RestrictInfos inserted	 * above each subclause of the top-level AND/OR structure.	 */	if (or_clause((Node *) clause))		return (RestrictInfo *) make_sub_restrictinfos(clause,													   is_pushed_down,													   outerjoin_delayed,													   required_relids);	/* Shouldn't be an AND clause, else AND/OR flattening messed up */	Assert(!and_clause((Node *) clause));	return make_restrictinfo_internal(clause, NULL,									  is_pushed_down, outerjoin_delayed,									  required_relids);}/* * make_restrictinfo_from_bitmapqual * * Given the bitmapqual Path structure for a bitmap indexscan, generate * RestrictInfo node(s) equivalent to the condition represented by the * indexclauses of the Path structure. * * The result is a List (effectively, implicit-AND representation) of * RestrictInfos. * * The caller must pass is_pushed_down, but we assume outerjoin_delayed * is false (no such qual should ever get into a bitmapqual). * * If include_predicates is true, we add any partial index predicates to * the explicit index quals.  When this is not true, we return a condition * that might be weaker than the actual scan represents. * * To do this through the normal make_restrictinfo() API, callers would have * to strip off the RestrictInfo nodes present in the indexclauses lists, and * then make_restrictinfo() would have to build new ones.  It's better to have * a specialized routine to allow sharing of RestrictInfos. * * The qual manipulations here are much the same as in create_bitmap_subplan; * keep the two routines in sync! */List *make_restrictinfo_from_bitmapqual(Path *bitmapqual,								  bool is_pushed_down,								  bool include_predicates){	List	   *result;	ListCell   *l;	if (IsA(bitmapqual, BitmapAndPath))	{		BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;		/*		 * There may well be redundant quals among the subplans, since a		 * top-level WHERE qual might have gotten used to form several		 * different index quals.  We don't try exceedingly hard to eliminate		 * redundancies, but we do eliminate obvious duplicates by using		 * list_concat_unique.		 */		result = NIL;		foreach(l, apath->bitmapquals)		{			List	   *sublist;			sublist = make_restrictinfo_from_bitmapqual((Path *) lfirst(l),														is_pushed_down,														include_predicates);			result = list_concat_unique(result, sublist);		}	}	else if (IsA(bitmapqual, BitmapOrPath))	{		BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;		List	   *withris = NIL;		List	   *withoutris = NIL;		/*		 * Here, we only detect qual-free subplans.  A qual-free subplan would		 * cause us to generate "... OR true ..."  which we may as well reduce		 * to just "true".	We do not try to eliminate redundant subclauses		 * because (a) it's not as likely as in the AND case, and (b) we might		 * well be working with hundreds or even thousands of OR conditions,		 * perhaps from a long IN list.  The performance of list_append_unique		 * would be unacceptable.		 */		foreach(l, opath->bitmapquals)		{			List	   *sublist;			sublist = make_restrictinfo_from_bitmapqual((Path *) lfirst(l),														is_pushed_down,														include_predicates);			if (sublist == NIL)			{				/*				 * If we find a qual-less subscan, it represents a constant				 * TRUE, and hence the OR result is also constant TRUE, so we				 * can stop here.				 */				return NIL;			}			/*			 * If the sublist contains multiple RestrictInfos, we create an			 * AND subclause.  If there's just one, we have to check if it's			 * an OR clause, and if so flatten it to preserve AND/OR flatness			 * of our output.			 *			 * We construct lists with and without sub-RestrictInfos, so			 * as not to have to regenerate duplicate RestrictInfos below.			 */			if (list_length(sublist) > 1)			{				withris = lappend(withris, make_andclause(sublist));				sublist = get_actual_clauses(sublist);				withoutris = lappend(withoutris, make_andclause(sublist));			}			else			{				RestrictInfo   *subri = (RestrictInfo *) linitial(sublist);				Assert(IsA(subri, RestrictInfo));				if (restriction_is_or_clause(subri))				{					BoolExpr   *subor = (BoolExpr *) subri->orclause;					Assert(or_clause((Node *) subor));					withris = list_concat(withris,										  list_copy(subor->args));					subor = (BoolExpr *) subri->clause;					Assert(or_clause((Node *) subor));					withoutris = list_concat(withoutris,											 list_copy(subor->args));				}				else				{					withris = lappend(withris, subri);					withoutris = lappend(withoutris, subri->clause);				}			}		}		/*		 * Avoid generating one-element ORs, which could happen due to		 * redundancy elimination.		 */		if (list_length(withris) <= 1)			result = withris;		else		{			/* Here's the magic part not available to outside callers */			result =				list_make1(make_restrictinfo_internal(make_orclause(withoutris),													  make_orclause(withris),													  is_pushed_down,													  false,													  NULL));		}	}	else if (IsA(bitmapqual, IndexPath))	{		IndexPath  *ipath = (IndexPath *) bitmapqual;		result = list_copy(ipath->indexclauses);		if (include_predicates && ipath->indexinfo->indpred != NIL)		{			foreach(l, ipath->indexinfo->indpred)			{				Expr	   *pred = (Expr *) lfirst(l);				/*				 * We know that the index predicate must have been implied by				 * the query condition as a whole, but it may or may not be				 * implied by the conditions that got pushed into the				 * bitmapqual.	Avoid generating redundant conditions.				 */				if (!predicate_implied_by(list_make1(pred), result))					result = lappend(result,									 make_restrictinfo(pred,													   is_pushed_down,													   false,													   NULL));			}		}	}	else	{		elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));		result = NIL;			/* keep compiler quiet */	}	return result;}/* * make_restrictinfo_internal * * Common code for the main entry points and the recursive cases. */static RestrictInfo *make_restrictinfo_internal(Expr *clause, Expr *orclause,						   bool is_pushed_down, bool outerjoin_delayed,						   Relids required_relids){	RestrictInfo *restrictinfo = makeNode(RestrictInfo);	restrictinfo->clause = clause;	restrictinfo->orclause = orclause;	restrictinfo->is_pushed_down = is_pushed_down;	restrictinfo->outerjoin_delayed = outerjoin_delayed;	restrictinfo->can_join = false;		/* may get set below */	/*	 * If it's a binary opclause, set up left/right relids info. In any case	 * set up the total clause relids info.	 */	if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)	{		restrictinfo->left_relids = pull_varnos(get_leftop(clause));		restrictinfo->right_relids = pull_varnos(get_rightop(clause));		restrictinfo->clause_relids = bms_union(restrictinfo->left_relids,												restrictinfo->right_relids);		/*		 * Does it look like a normal join clause, i.e., a binary operator		 * relating expressions that come from distinct relations? If so we		 * might be able to use it in a join algorithm.  Note that this is a		 * purely syntactic test that is made regardless of context.		 */		if (!bms_is_empty(restrictinfo->left_relids) &&			!bms_is_empty(restrictinfo->right_relids) &&			!bms_overlap(restrictinfo->left_relids,						 restrictinfo->right_relids))			restrictinfo->can_join = true;	}	else	{		/* Not a binary opclause, so mark left/right relid sets as empty */		restrictinfo->left_relids = NULL;		restrictinfo->right_relids = NULL;		/* and get the total relid set the hard way */		restrictinfo->clause_relids = pull_varnos((Node *) clause);	}	/* required_relids defaults to clause_relids */	if (required_relids != NULL)		restrictinfo->required_relids = required_relids;	else		restrictinfo->required_relids = restrictinfo->clause_relids;	/*	 * Fill in all the cacheable fields with "not yet set" markers. None of	 * these will be computed until/unless needed.	Note in particular that we	 * don't mark a binary opclause as mergejoinable or hashjoinable here;	 * that happens only if it appears in the right context (top level of a	 * joinclause list).	 */

⌨️ 快捷键说明

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