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

📄 createplan.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* Process the bitmapqual tree into a Plan tree and qual lists */	bitmapqualplan = create_bitmap_subplan(root, best_path->bitmapqual,										   &bitmapqualorig, &indexquals);	/* Reduce RestrictInfo list to bare expressions */	scan_clauses = get_actual_clauses(scan_clauses);	/*	 * If this is a innerjoin scan, the indexclauses will contain join clauses	 * that are not present in scan_clauses (since the passed-in value is just	 * the rel's baserestrictinfo list).  We must add these clauses to	 * scan_clauses to ensure they get checked.  In most cases we will remove	 * the join clauses again below, but if a join clause contains a special	 * operator, we need to make sure it gets into the scan_clauses.	 */	if (best_path->isjoininner)	{		scan_clauses = list_concat_unique(scan_clauses, bitmapqualorig);	}	/*	 * The qpqual list must contain all restrictions not automatically handled	 * by the index.  All the predicates in the indexquals will be checked	 * (either by the index itself, or by nodeBitmapHeapscan.c), but if there	 * are any "special" or lossy operators involved then they must be added	 * to qpqual.  The upshot is that qpqual must contain scan_clauses minus	 * whatever appears in indexquals.	 *	 * In normal cases simple equal() checks will be enough to spot duplicate	 * clauses, so we try that first.  In some situations (particularly with	 * OR'd index conditions) we may have scan_clauses that are not equal to,	 * but are logically implied by, the index quals; so we also try a	 * predicate_implied_by() check to see if we can discard quals that way.	 * (predicate_implied_by assumes its first input contains only immutable	 * functions, so we have to check that.)	 *	 * Unlike create_indexscan_plan(), we need take no special thought here	 * for partial index predicates; this is because the predicate conditions	 * are already listed in bitmapqualorig and indexquals.  Bitmap scans	 * have to do it that way because predicate conditions need to be rechecked	 * if the scan becomes lossy.	 */	qpqual = NIL;	foreach(l, scan_clauses)	{		Node	   *clause = (Node *) lfirst(l);		if (list_member(indexquals, clause))			continue;		if (!contain_mutable_functions(clause))		{			List	   *clausel = list_make1(clause);			if (predicate_implied_by(clausel, indexquals))				continue;		}		qpqual = lappend(qpqual, clause);	}	/* Sort clauses into best execution order */	qpqual = order_qual_clauses(root, qpqual);	/*	 * When dealing with special or lossy operators, we will at this point	 * have duplicate clauses in qpqual and bitmapqualorig.  We may as well	 * drop 'em from bitmapqualorig, since there's no point in making the	 * tests twice.	 */	bitmapqualorig = list_difference_ptr(bitmapqualorig, qpqual);	/*	 * Copy the finished bitmapqualorig to make sure we have an independent	 * copy --- needed in case there are subplans in the index quals	 */	bitmapqualorig = copyObject(bitmapqualorig);	/* Finally ready to build the plan node */	scan_plan = make_bitmap_heapscan(tlist,									 qpqual,									 bitmapqualplan,									 bitmapqualorig,									 baserelid);	copy_path_costsize(&scan_plan->scan.plan, &best_path->path);	/* use the indexscan-specific rows estimate, not the parent rel's */	scan_plan->scan.plan.plan_rows = best_path->rows;	return scan_plan;}/* * Given a bitmapqual tree, generate the Plan tree that implements it * * As byproducts, we also return in *qual and *indexqual the qual lists * (in implicit-AND form, without RestrictInfos) describing the original index * conditions and the generated indexqual conditions.  The latter is made to * exclude lossy index operators.  Both lists include partial-index predicates, * because we have to recheck predicates as well as index conditions if the * bitmap scan becomes lossy. * * Note: if you find yourself changing this, you probably need to change * make_restrictinfo_from_bitmapqual too. */static Plan *create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,					  List **qual, List **indexqual){	Plan	   *plan;	if (IsA(bitmapqual, BitmapAndPath))	{		BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;		List	   *subplans = NIL;		List	   *subquals = NIL;		List	   *subindexquals = NIL;		ListCell   *l;		/*		 * 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.		 */		foreach(l, apath->bitmapquals)		{			Plan	   *subplan;			List	   *subqual;			List	   *subindexqual;			subplan = create_bitmap_subplan(root, (Path *) lfirst(l),											&subqual, &subindexqual);			subplans = lappend(subplans, subplan);			subquals = list_concat_unique(subquals, subqual);			subindexquals = list_concat_unique(subindexquals, subindexqual);		}		plan = (Plan *) make_bitmap_and(subplans);		plan->startup_cost = apath->path.startup_cost;		plan->total_cost = apath->path.total_cost;		plan->plan_rows =			clamp_row_est(apath->bitmapselectivity * apath->path.parent->tuples);		plan->plan_width = 0;	/* meaningless */		*qual = subquals;		*indexqual = subindexquals;	}	else if (IsA(bitmapqual, BitmapOrPath))	{		BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;		List	   *subplans = NIL;		List	   *subquals = NIL;		List	   *subindexquals = NIL;		bool		const_true_subqual = false;		bool		const_true_subindexqual = false;		ListCell   *l;		/*		 * 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)		{			Plan	   *subplan;			List	   *subqual;			List	   *subindexqual;			subplan = create_bitmap_subplan(root, (Path *) lfirst(l),											&subqual, &subindexqual);			subplans = lappend(subplans, subplan);			if (subqual == NIL)				const_true_subqual = true;			else if (!const_true_subqual)				subquals = lappend(subquals,								   make_ands_explicit(subqual));			if (subindexqual == NIL)				const_true_subindexqual = true;			else if (!const_true_subindexqual)				subindexquals = lappend(subindexquals,										make_ands_explicit(subindexqual));		}		plan = (Plan *) make_bitmap_or(subplans);		plan->startup_cost = opath->path.startup_cost;		plan->total_cost = opath->path.total_cost;		plan->plan_rows =			clamp_row_est(opath->bitmapselectivity * opath->path.parent->tuples);		plan->plan_width = 0;	/* meaningless */		/*		 * If there were constant-TRUE subquals, the OR reduces to constant		 * TRUE.  Also, avoid generating one-element ORs, which could happen		 * due to redundancy elimination.		 */		if (const_true_subqual)			*qual = NIL;		else if (list_length(subquals) <= 1)			*qual = subquals;		else			*qual = list_make1(make_orclause(subquals));		if (const_true_subindexqual)			*indexqual = NIL;		else if (list_length(subindexquals) <= 1)			*indexqual = subindexquals;		else			*indexqual = list_make1(make_orclause(subindexquals));	}	else if (IsA(bitmapqual, IndexPath))	{		IndexPath  *ipath = (IndexPath *) bitmapqual;		IndexScan  *iscan;		List	   *nonlossy_clauses;		ListCell   *l;		/* Use the regular indexscan plan build machinery... */		iscan = create_indexscan_plan(root, ipath, NIL, NIL,									  &nonlossy_clauses);		/* then convert to a bitmap indexscan */		plan = (Plan *) make_bitmap_indexscan(iscan->scan.scanrelid,											  iscan->indexid,											  iscan->indexqual,											  iscan->indexqualorig,											  iscan->indexstrategy,											  iscan->indexsubtype);		plan->startup_cost = 0.0;		plan->total_cost = ipath->indextotalcost;		plan->plan_rows =			clamp_row_est(ipath->indexselectivity * ipath->path.parent->tuples);		plan->plan_width = 0;	/* meaningless */		*qual = get_actual_clauses(ipath->indexclauses);		*indexqual = get_actual_clauses(nonlossy_clauses);		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), ipath->indexclauses))			{				*qual = lappend(*qual, pred);				*indexqual = lappend(*indexqual, pred);			}		}	}	else	{		elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));		plan = NULL;			/* keep compiler quiet */	}	return plan;}/* * create_tidscan_plan *	 Returns a tidscan plan for the base relation scanned by 'best_path' *	 with restriction clauses 'scan_clauses' and targetlist 'tlist'. */static TidScan *create_tidscan_plan(PlannerInfo *root, TidPath *best_path,					List *tlist, List *scan_clauses){	TidScan    *scan_plan;	Index		scan_relid = best_path->path.parent->relid;	/* it should be a base rel... */	Assert(scan_relid > 0);	Assert(best_path->path.parent->rtekind == RTE_RELATION);	/* Reduce RestrictInfo list to bare expressions */	scan_clauses = get_actual_clauses(scan_clauses);	/* Sort clauses into best execution order */	scan_clauses = order_qual_clauses(root, scan_clauses);	scan_plan = make_tidscan(tlist,							 scan_clauses,							 scan_relid,							 best_path->tideval);	copy_path_costsize(&scan_plan->scan.plan, &best_path->path);	return scan_plan;}/* * create_subqueryscan_plan *	 Returns a subqueryscan plan for the base relation scanned by 'best_path' *	 with restriction clauses 'scan_clauses' and targetlist 'tlist'. */static SubqueryScan *create_subqueryscan_plan(PlannerInfo *root, Path *best_path,						 List *tlist, List *scan_clauses){	SubqueryScan *scan_plan;	Index		scan_relid = best_path->parent->relid;	/* it should be a subquery base rel... */	Assert(scan_relid > 0);	Assert(best_path->parent->rtekind == RTE_SUBQUERY);	/* Reduce RestrictInfo list to bare expressions */	scan_clauses = get_actual_clauses(scan_clauses);	/* Sort clauses into best execution order */	scan_clauses = order_qual_clauses(root, scan_clauses);	scan_plan = make_subqueryscan(tlist,								  scan_clauses,								  scan_relid,								  best_path->parent->subplan);	copy_path_costsize(&scan_plan->scan.plan, best_path);	return scan_plan;}/* * create_functionscan_plan *	 Returns a functionscan plan for the base relation scanned by 'best_path' *	 with restriction clauses 'scan_clauses' and targetlist 'tlist'. */static FunctionScan *create_functionscan_plan(PlannerInfo *root, Path *best_path,						 List *tlist, List *scan_clauses){	FunctionScan *scan_plan;	Index		scan_relid = best_path->parent->relid;	/* it should be a function base rel... */	Assert(scan_relid > 0);	Assert(best_path->parent->rtekind == RTE_FUNCTION);	/* Reduce RestrictInfo list to bare expressions */	scan_clauses = get_actual_clauses(scan_clauses);	/* Sort clauses into best execution order */	scan_clauses = order_qual_clauses(root, scan_clauses);	scan_plan = make_functionscan(tlist, scan_clauses, scan_relid);	copy_path_costsize(&scan_plan->scan.plan, best_path);	return scan_plan;}/***************************************************************************** * *	JOIN METHODS * *****************************************************************************/static NestLoop *create_nestloop_plan(PlannerInfo *root,					 NestPath *best_path,					 Plan *outer_plan,					 Plan *inner_plan){	List	   *tlist = build_relation_tlist(best_path->path.parent);	List	   *joinrestrictclauses = best_path->joinrestrictinfo;	List	   *joinclauses;	List	   *otherclauses;	NestLoop   *join_plan;	if (IsA(best_path->innerjoinpath, IndexPath))	{		/*		 * An index is being used to reduce the number of tuples scanned in		 * the inner relation.	If there are join clauses being used with the		 * index, we may remove those join clauses from the list of clauses		 * that have to be checked as qpquals at the join node.		 *		 * We can also remove any join clauses that are redundant with those		 * being used in the index scan; prior redundancy checks will not have		 * caught this case because the join clauses would never have been put		 * in the same joininfo list.		 *		 * We can skip this if the index path is an ordinary indexpath and not		 * a special innerjoin path.		 */		IndexPath  *innerpath = (IndexPath *) best_path->innerjoinpath;		if (innerpath->isjoininner)		{			joinrestrictclauses =				select_nonredundant_join_clauses(root,												 joinrestrictclauses,												 innerpath->indexclauses,										 IS_OUTER_JOIN(best_path->jointype));		}	}	else if (IsA(best_path->innerjoinpath, BitmapHeapPath))	{		/*		 * Same deal for bitmapped index scans.		 *		 * Note: both here and above, we ignore any implicit index		 * restrictions associated with the use of partial indexes.  This is		 * OK because we're only trying to prove we can dispense with some		 * join quals; failing to prove that doesn't result in an incorrect		 * plan.  It is the right way to proceed because adding more quals to		 * the stuff we got from the original query would just make it harder		 * to detect duplication.  (Also, to change this we'd have to be		 * wary of UPDATE/DELETE/SELECT FOR UPDATE target relations; see		 * notes above about EvalPlanQual.)		 */		BitmapHeapPath *innerpath = (BitmapHeapPath *) best_path->innerjoinpath;		if (innerpath->isjoininner)		{			List	   *bitmapclauses;			bitmapclauses =				make_restrictinfo_from_bitmapqual(innerpath->bitmapqual,												  true,												  false);			joinrestrictclauses =				select_nonredundant_join_clauses(root,												 joinrestrictclauses,												 bitmapclauses,										 IS_OUTER_JOIN(best_path->jointype));		}	}	/* Get the join qual clauses (in plain expression form) */	if (IS_OUTER_JOIN(best_path->jointype))	{		get_actual_join_clauses(joinrestrictclauses,								&joinclauses, &otherclauses);	}	else	{		/* We can treat all clauses alike for an inner join */		joinclauses = get_actual_clauses(joinrestrictclauses);		otherclauses = NIL;	}	/* Sort clauses into best execution order */	joinclauses = order_qual_clauses(root, joinclauses);	otherclauses = order_qual_clauses(root, otherclauses);	join_plan = make_nestloop(tlist,							  joinclauses,

⌨️ 快捷键说明

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