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

📄 createplan.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * parent-rel Vars it'll be asked to emit.	 */	if (best_path->subpaths == NIL)	{		/* Generate a Result plan with constant-FALSE gating qual */		return (Plan *) make_result(tlist,									(Node *) list_make1(makeBoolConst(false,																	  false)),									NULL);	}	/* Normal case with multiple subpaths */	foreach(subpaths, best_path->subpaths)	{		Path	   *subpath = (Path *) lfirst(subpaths);		subplans = lappend(subplans, create_plan(root, subpath));	}	plan = make_append(subplans, false, tlist);	return (Plan *) plan;}/* * create_result_plan *	  Create a Result plan for 'best_path' and (recursively) plans *	  for its subpaths. * *	  Returns a Plan node. */static Result *create_result_plan(PlannerInfo *root, ResultPath *best_path){	Result	   *plan;	List	   *tlist;	List	   *constclauses;	Plan	   *subplan;	if (best_path->path.parent)		tlist = build_relation_tlist(best_path->path.parent);	else		tlist = NIL;			/* will be filled in later */	if (best_path->subpath)		subplan = create_plan(root, best_path->subpath);	else		subplan = NULL;	constclauses = order_qual_clauses(root, best_path->constantqual);	plan = make_result(tlist, (Node *) constclauses, subplan);	return plan;}/* * create_material_plan *	  Create a Material plan for 'best_path' and (recursively) plans *	  for its subpaths. * *	  Returns a Plan node. */static Material *create_material_plan(PlannerInfo *root, MaterialPath *best_path){	Material   *plan;	Plan	   *subplan;	subplan = create_plan(root, best_path->subpath);	/* We don't want any excess columns in the materialized tuples */	disuse_physical_tlist(subplan, best_path->subpath);	plan = make_material(subplan);	copy_path_costsize(&plan->plan, (Path *) best_path);	return plan;}/* * create_unique_plan *	  Create a Unique plan for 'best_path' and (recursively) plans *	  for its subpaths. * *	  Returns a Plan node. */static Plan *create_unique_plan(PlannerInfo *root, UniquePath *best_path){	Plan	   *plan;	Plan	   *subplan;	List	   *uniq_exprs;	List	   *newtlist;	int			nextresno;	bool		newitems;	int			numGroupCols;	AttrNumber *groupColIdx;	int			groupColPos;	ListCell   *l;	subplan = create_plan(root, best_path->subpath);	/* Done if we don't need to do any actual unique-ifying */	if (best_path->umethod == UNIQUE_PATH_NOOP)		return subplan;	/*----------	 * As constructed, the subplan has a "flat" tlist containing just the	 * Vars needed here and at upper levels.  The values we are supposed	 * to unique-ify may be expressions in these variables.  We have to	 * add any such expressions to the subplan's tlist.	 *	 * The subplan may have a "physical" tlist if it is a simple scan plan.	 * This should be left as-is if we don't need to add any expressions;	 * but if we do have to add expressions, then a projection step will be	 * needed at runtime anyway, and so we may as well remove unneeded items.	 * Therefore newtlist starts from build_relation_tlist() not just a	 * copy of the subplan's tlist; and we don't install it into the subplan	 * unless stuff has to be added.	 *	 * To find the correct list of values to unique-ify, we look in the	 * information saved for IN expressions.  If this code is ever used in	 * other scenarios, some other way of finding what to unique-ify will	 * be needed.	 *----------	 */	uniq_exprs = NIL;			/* just to keep compiler quiet */	foreach(l, root->in_info_list)	{		InClauseInfo *ininfo = (InClauseInfo *) lfirst(l);		if (bms_equal(ininfo->righthand, best_path->path.parent->relids))		{			uniq_exprs = ininfo->sub_targetlist;			break;		}	}	if (l == NULL)				/* fell out of loop? */		elog(ERROR, "could not find UniquePath in in_info_list");	/* initialize modified subplan tlist as just the "required" vars */	newtlist = build_relation_tlist(best_path->path.parent);	nextresno = list_length(newtlist) + 1;	newitems = false;	foreach(l, uniq_exprs)	{		Node	   *uniqexpr = lfirst(l);		TargetEntry *tle;		tle = tlist_member(uniqexpr, newtlist);		if (!tle)		{			tle = makeTargetEntry((Expr *) uniqexpr,								  nextresno,								  NULL,								  false);			newtlist = lappend(newtlist, tle);			nextresno++;			newitems = true;		}	}	if (newitems)	{		/*		 * If the top plan node can't do projections, we need to add a Result		 * node to help it along.		 */		if (!is_projection_capable_plan(subplan))			subplan = (Plan *) make_result(newtlist, NULL, subplan);		else			subplan->targetlist = newtlist;	}	/*	 * Build control information showing which subplan output columns are to	 * be examined by the grouping step.  Unfortunately we can't merge this	 * with the previous loop, since we didn't then know which version of the	 * subplan tlist we'd end up using.	 */	newtlist = subplan->targetlist;	numGroupCols = list_length(uniq_exprs);	groupColIdx = (AttrNumber *) palloc(numGroupCols * sizeof(AttrNumber));	groupColPos = 0;	foreach(l, uniq_exprs)	{		Node	   *uniqexpr = lfirst(l);		TargetEntry *tle;		tle = tlist_member(uniqexpr, newtlist);		if (!tle)				/* shouldn't happen */			elog(ERROR, "failed to find unique expression in subplan tlist");		groupColIdx[groupColPos++] = tle->resno;	}	if (best_path->umethod == UNIQUE_PATH_HASH)	{		long		numGroups;		numGroups = (long) Min(best_path->rows, (double) LONG_MAX);		/*		 * Since the Agg node is going to project anyway, we can give it the		 * minimum output tlist, without any stuff we might have added to the		 * subplan tlist.		 */		plan = (Plan *) make_agg(root,								 build_relation_tlist(best_path->path.parent),								 NIL,								 AGG_HASHED,								 numGroupCols,								 groupColIdx,								 numGroups,								 0,								 subplan);	}	else	{		List	   *sortList = NIL;		for (groupColPos = 0; groupColPos < numGroupCols; groupColPos++)		{			TargetEntry *tle;			tle = get_tle_by_resno(subplan->targetlist,								   groupColIdx[groupColPos]);			Assert(tle != NULL);			sortList = addTargetToSortList(NULL, tle,										   sortList, subplan->targetlist,										   SORTBY_ASC, NIL, false);		}		plan = (Plan *) make_sort_from_sortclauses(root, sortList, subplan);		plan = (Plan *) make_unique(plan, sortList);	}	/* Adjust output size estimate (other fields should be OK already) */	plan->plan_rows = best_path->rows;	return plan;}/***************************************************************************** * *	BASE-RELATION SCAN METHODS * *****************************************************************************//* * create_seqscan_plan *	 Returns a seqscan plan for the base relation scanned by 'best_path' *	 with restriction clauses 'scan_clauses' and targetlist 'tlist'. */static SeqScan *create_seqscan_plan(PlannerInfo *root, Path *best_path,					List *tlist, List *scan_clauses){	SeqScan    *scan_plan;	Index		scan_relid = best_path->parent->relid;	/* it should be a base rel... */	Assert(scan_relid > 0);	Assert(best_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_seqscan(tlist,							 scan_clauses,							 scan_relid);	copy_path_costsize(&scan_plan->plan, best_path);	return scan_plan;}/* * create_indexscan_plan *	  Returns an indexscan plan for the base relation scanned by 'best_path' *	  with restriction clauses 'scan_clauses' and targetlist 'tlist'. * * The indexquals list of the path contains implicitly-ANDed qual conditions. * The list can be empty --- then no index restrictions will be applied during * the scan. * * If nonlossy_clauses isn't NULL, *nonlossy_clauses receives a list of the * nonlossy indexquals. */static IndexScan *create_indexscan_plan(PlannerInfo *root,					  IndexPath *best_path,					  List *tlist,					  List *scan_clauses,					  List **nonlossy_clauses){	List	   *indexquals = best_path->indexquals;	Index		baserelid = best_path->path.parent->relid;	Oid			indexoid = best_path->indexinfo->indexoid;	List	   *qpqual;	List	   *stripped_indexquals;	List	   *fixed_indexquals;	List	   *nonlossy_indexquals;	List	   *indexstrategy;	List	   *indexsubtype;	ListCell   *l;	IndexScan  *scan_plan;	/* it should be a base rel... */	Assert(baserelid > 0);	Assert(best_path->path.parent->rtekind == RTE_RELATION);	/*	 * Build "stripped" indexquals structure (no RestrictInfos) to pass to	 * executor as indexqualorig	 */	stripped_indexquals = get_actual_clauses(indexquals);	/*	 * The executor needs a copy with the indexkey on the left of each clause	 * and with index attr numbers substituted for table ones. This pass also	 * gets strategy info and looks for "lossy" operators.	 */	fix_indexqual_references(indexquals, best_path,							 &fixed_indexquals,							 &nonlossy_indexquals,							 &indexstrategy,							 &indexsubtype);	/* pass back nonlossy quals if caller wants 'em */	if (nonlossy_clauses)		*nonlossy_clauses = nonlossy_indexquals;	/*	 * If this is an 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.	 *	 * Note: pointer comparison should be enough to determine RestrictInfo	 * matches.	 */	if (best_path->isjoininner)		scan_clauses = list_union_ptr(scan_clauses, best_path->indexclauses);	/*	 * 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 nodeIndexscan.c), but if there are	 * any "special" operators involved then they must be included in qpqual.	 * Also, any lossy index operators must be rechecked in the qpqual.  The	 * upshot is that qpqual must contain scan_clauses minus whatever appears	 * in nonlossy_indexquals.	 *	 * In normal cases simple pointer equality checks will be enough to spot	 * duplicate RestrictInfos, 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.)	 *	 * We can also discard quals that are implied by a partial index's	 * predicate, but only in a plain SELECT; when scanning a target relation	 * of UPDATE/DELETE/SELECT FOR UPDATE, we must leave such quals in the	 * plan so that they'll be properly rechecked by EvalPlanQual testing.	 *	 * While at it, we strip off the RestrictInfos to produce a list of plain	 * expressions.	 */	qpqual = NIL;	foreach(l, scan_clauses)	{		RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);		Assert(IsA(rinfo, RestrictInfo));		if (list_member_ptr(nonlossy_indexquals, rinfo))			continue;		if (!contain_mutable_functions((Node *) rinfo->clause))		{			List	   *clausel = list_make1(rinfo->clause);			if (predicate_implied_by(clausel, nonlossy_indexquals))				continue;			if (best_path->indexinfo->indpred)			{				if (baserelid != root->parse->resultRelation &&					!list_member_int(root->parse->rowMarks, baserelid))					if (predicate_implied_by(clausel,											 best_path->indexinfo->indpred))						continue;			}		}		qpqual = lappend(qpqual, rinfo->clause);	}	/* Sort clauses into best execution order */	qpqual = order_qual_clauses(root, qpqual);	/* Finally ready to build the plan node */	scan_plan = make_indexscan(tlist,							   qpqual,							   baserelid,							   indexoid,							   fixed_indexquals,							   stripped_indexquals,							   indexstrategy,							   indexsubtype,							   best_path->indexscandir);	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;}/* * create_bitmap_scan_plan *	  Returns a bitmap scan plan for the base relation scanned by 'best_path' *	  with restriction clauses 'scan_clauses' and targetlist 'tlist'. */static BitmapHeapScan *create_bitmap_scan_plan(PlannerInfo *root,						BitmapHeapPath *best_path,						List *tlist,						List *scan_clauses){	Index		baserelid = best_path->path.parent->relid;	Plan	   *bitmapqualplan;	List	   *bitmapqualorig;	List	   *indexquals;	List	   *qpqual;	ListCell   *l;	BitmapHeapScan *scan_plan;	/* it should be a base rel... */	Assert(baserelid > 0);	Assert(best_path->path.parent->rtekind == RTE_RELATION);

⌨️ 快捷键说明

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