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

📄 createplan.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 5 页
字号:
	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(Query *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->targetlist, 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(Query *root, UniquePath *best_path){	Plan	   *plan;	Plan	   *subplan;	List	   *uniq_exprs;	int			numGroupCols;	AttrNumber *groupColIdx;	int			groupColPos;	List	   *newtlist;	int			nextresno;	bool		newitems;	List	   *my_tlist;	List	   *l;	subplan = create_plan(root, best_path->subpath);	/*	 * 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.  We then build	 * control information showing which subplan output columns are to be	 * examined by the grouping step.  (Since we do not remove any	 * existing subplan outputs, not all the output columns may be used	 * for grouping.)	 *	 * Note: the reason we don't remove any subplan outputs is that there are	 * scenarios where a Var is needed at higher levels even though it is	 * not one of the nominal outputs of an IN clause.	Consider WHERE x	 * IN (SELECT y FROM t1,t2 WHERE y = z) Implied equality deduction	 * will generate an "x = z" clause, which may get used instead of "x =	 * y" in the upper join step.  Therefore the sub-select had better	 * deliver both y and z in its targetlist.	It is sufficient to	 * unique-ify on y, however.	 *	 * 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 == NIL)				/* fell out of loop? */		elog(ERROR, "could not find UniquePath in in_info_list");	/* set up to record positions of unique columns */	numGroupCols = length(uniq_exprs);	groupColIdx = (AttrNumber *) palloc(numGroupCols * sizeof(AttrNumber));	groupColPos = 0;	/* not sure if tlist might be shared with other nodes, so copy */	newtlist = copyObject(subplan->targetlist);	nextresno = length(newtlist) + 1;	newitems = false;	foreach(l, uniq_exprs)	{		Node	   *uniqexpr = lfirst(l);		TargetEntry *tle;		tle = tlistentry_member(uniqexpr, newtlist);		if (!tle)		{			tle = makeTargetEntry(makeResdom(nextresno,											 exprType(uniqexpr),											 exprTypmod(uniqexpr),											 NULL,											 false),								  (Expr *) uniqexpr);			newtlist = lappend(newtlist, tle);			nextresno++;			newitems = true;		}		groupColIdx[groupColPos++] = tle->resdom->resno;	}	if (newitems)	{		/*		 * If the top plan node can't do projections, we need to add a		 * Result node to help it along.		 *		 * Currently, the only non-projection-capable plan type we can see		 * here is Append.		 */		if (IsA(subplan, Append))			subplan = (Plan *) make_result(newtlist, NULL, subplan);		else			subplan->targetlist = newtlist;	}	/* Copy tlist again to make one we can put sorting labels on */	my_tlist = copyObject(subplan->targetlist);	if (best_path->use_hash)	{		long		numGroups;		numGroups = (long) Min(best_path->rows, (double) LONG_MAX);		plan = (Plan *) make_agg(root,								 my_tlist,								 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(my_tlist, groupColIdx[groupColPos]);			Assert(tle != NULL);			sortList = addTargetToSortList(NULL, tle,										   sortList, my_tlist,										   SORTBY_ASC, NIL, false);		}		plan = (Plan *) make_sort_from_sortclauses(root, my_tlist,												   subplan, sortList);		plan = (Plan *) make_unique(my_tlist, plan, sortList);	}	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(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);	scan_plan = make_seqscan(tlist,							 scan_clauses,							 scan_relid);	copy_path_costsize(&scan_plan->plan, best_path);	return scan_plan;}/* * create_indexscan_plan *	  Returns a indexscan plan for the base relation scanned by 'best_path' *	  with restriction clauses 'scan_clauses' and targetlist 'tlist'. * * The indexqual of the path contains a sublist of implicitly-ANDed qual * conditions for each scan of the index(es); if there is more than one * scan then the retrieved tuple sets are ORed together.  The indexqual * and indexinfo lists must have the same length, ie, the number of scans * that will occur.  Note it is possible for a qual condition sublist * to be empty --- then no index restrictions will be applied during that * scan. */static IndexScan *create_indexscan_plan(Query *root,					  IndexPath *best_path,					  List *tlist,					  List *scan_clauses){	List	   *indxqual = best_path->indexqual;	Index		baserelid = best_path->path.parent->relid;	List	   *qpqual;	Expr	   *indxqual_or_expr = NULL;	List	   *fixed_indxqual;	List	   *recheck_indxqual;	FastList	indexids;	List	   *ixinfo;	IndexScan  *scan_plan;	/* it should be a base rel... */	Assert(baserelid > 0);	Assert(best_path->path.parent->rtekind == RTE_RELATION);	/*	 * Build list of index OIDs.	 */	FastListInit(&indexids);	foreach(ixinfo, best_path->indexinfo)	{		IndexOptInfo *index = (IndexOptInfo *) lfirst(ixinfo);		FastAppendo(&indexids, index->indexoid);	}	/*	 * The qpqual list must contain all restrictions not automatically	 * handled by the index.  Normally the predicates in the indxqual are	 * checked fully by the index, but if the index is "lossy" for a	 * particular operator (as signaled by the amopreqcheck flag in	 * pg_amop), then we need to double-check that predicate in qpqual,	 * because the index may return more tuples than match the predicate.	 *	 * Since the indexquals were generated from the restriction clauses given	 * by scan_clauses, there will normally be some duplications between	 * the lists.  We get rid of the duplicates, then add back if lossy.	 */	if (length(indxqual) > 1)	{		/*		 * Build an expression representation of the indexqual, expanding		 * the implicit OR and AND semantics of the first- and		 * second-level lists.		 */		FastList	orclauses;		List	   *orclause;		FastListInit(&orclauses);		foreach(orclause, indxqual)			FastAppend(&orclauses, make_ands_explicit(lfirst(orclause)));		indxqual_or_expr = make_orclause(FastListValue(&orclauses));		qpqual = set_difference(scan_clauses, makeList1(indxqual_or_expr));	}	else if (indxqual != NIL)	{		/*		 * Here, we can simply treat the first sublist as an independent		 * set of qual expressions, since there is no top-level OR		 * behavior.		 */		qpqual = set_difference(scan_clauses, lfirst(indxqual));	}	else		qpqual = scan_clauses;	/*	 * 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 looks for "lossy" operators.	 */	fix_indxqual_references(indxqual, best_path,							&fixed_indxqual, &recheck_indxqual);	/*	 * If there were any "lossy" operators, need to add back the	 * appropriate qual clauses to the qpqual.	When there is just one	 * indexscan being performed (ie, we have simple AND semantics), we	 * can just add the lossy clauses themselves to qpqual.  If we have	 * OR-of-ANDs, we'd better add the entire original indexqual to make	 * sure that the semantics are correct.	 */	if (recheck_indxqual != NIL)	{		if (indxqual_or_expr)		{			/* Better do a deep copy of the original scanclauses */			qpqual = lappend(qpqual, copyObject(indxqual_or_expr));		}		else		{			/* Subroutine already copied quals, so just append to list */			Assert(length(recheck_indxqual) == 1);			qpqual = nconc(qpqual, (List *) lfirst(recheck_indxqual));		}	}	/* Finally ready to build the plan node */	scan_plan = make_indexscan(tlist,							   qpqual,							   baserelid,							   FastListValue(&indexids),							   fixed_indxqual,							   indxqual,							   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_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(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);	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(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);	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(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);	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(Query *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		 * --- but only if there's just one indexscan in the inner path		 * (otherwise, several different sets of clauses are being ORed		 * together).		 *		 * 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.		 *		 * This would be a waste of time if the indexpath was an ordinary		 * indexpath and not a special innerjoin path.	We will skip it in		 * that case since indexjoinclauses is NIL in an ordinary		 * indexpath.		 */		IndexPath  *innerpath = (IndexPath *) best_path->innerjoinpath;		List	   *indexjoinclauses = innerpath->indexjoinclauses;		if (length(indexjoinclauses) == 1)		/* single indexscan? */		{			joinrestrictclauses =				select_nonredundant_join_clauses(root,												 joinrestrictclauses,												 lfirst(indexjoinclauses),												 best_path->jointype);

⌨️ 快捷键说明

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