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

📄 createplan.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 5 页
字号:
 *		in at runtime. * * Ideally the order should be driven by a combination of execution cost and * selectivity, but unfortunately we have so little information about * execution cost of operators that it's really hard to do anything smart. * For now, we just move any quals that contain SubPlan references (but not * InitPlan references) to the end of the list. */static List *order_qual_clauses(Query *root, List *clauses){	FastList	nosubplans;	FastList	withsubplans;	List	   *l;	/* No need to work hard if the query is subselect-free */	if (!root->hasSubLinks)		return clauses;	FastListInit(&nosubplans);	FastListInit(&withsubplans);	foreach(l, clauses)	{		Node	   *clause = lfirst(l);		if (contain_subplans(clause))			FastAppend(&withsubplans, clause);		else			FastAppend(&nosubplans, clause);	}	FastConcFast(&nosubplans, &withsubplans);	return FastListValue(&nosubplans);}/* * Copy cost and size info from a Path node to the Plan node created from it. * The executor won't use this info, but it's needed by EXPLAIN. */static voidcopy_path_costsize(Plan *dest, Path *src){	if (src)	{		dest->startup_cost = src->startup_cost;		dest->total_cost = src->total_cost;		dest->plan_rows = src->parent->rows;		dest->plan_width = src->parent->width;	}	else	{		dest->startup_cost = 0;		dest->total_cost = 0;		dest->plan_rows = 0;		dest->plan_width = 0;	}}/* * Copy cost and size info from a lower plan node to an inserted node. * This is not critical, since the decisions have already been made, * but it helps produce more reasonable-looking EXPLAIN output. * (Some callers alter the info after copying it.) */static voidcopy_plan_costsize(Plan *dest, Plan *src){	if (src)	{		dest->startup_cost = src->startup_cost;		dest->total_cost = src->total_cost;		dest->plan_rows = src->plan_rows;		dest->plan_width = src->plan_width;	}	else	{		dest->startup_cost = 0;		dest->total_cost = 0;		dest->plan_rows = 0;		dest->plan_width = 0;	}}/***************************************************************************** * *	PLAN NODE BUILDING ROUTINES * * Some of these are exported because they are called to build plan nodes * in contexts where we're not deriving the plan node from a path node. * *****************************************************************************/static SeqScan *make_seqscan(List *qptlist,			 List *qpqual,			 Index scanrelid){	SeqScan    *node = makeNode(SeqScan);	Plan	   *plan = &node->plan;	/* cost should be inserted by caller */	plan->targetlist = qptlist;	plan->qual = qpqual;	plan->lefttree = NULL;	plan->righttree = NULL;	node->scanrelid = scanrelid;	return node;}static IndexScan *make_indexscan(List *qptlist,			   List *qpqual,			   Index scanrelid,			   List *indxid,			   List *indxqual,			   List *indxqualorig,			   ScanDirection indexscandir){	IndexScan  *node = makeNode(IndexScan);	Plan	   *plan = &node->scan.plan;	/* cost should be inserted by caller */	plan->targetlist = qptlist;	plan->qual = qpqual;	plan->lefttree = NULL;	plan->righttree = NULL;	node->scan.scanrelid = scanrelid;	node->indxid = indxid;	node->indxqual = indxqual;	node->indxqualorig = indxqualorig;	node->indxorderdir = indexscandir;	return node;}static TidScan *make_tidscan(List *qptlist,			 List *qpqual,			 Index scanrelid,			 List *tideval){	TidScan    *node = makeNode(TidScan);	Plan	   *plan = &node->scan.plan;	/* cost should be inserted by caller */	plan->targetlist = qptlist;	plan->qual = qpqual;	plan->lefttree = NULL;	plan->righttree = NULL;	node->scan.scanrelid = scanrelid;	node->tideval = tideval;	return node;}SubqueryScan *make_subqueryscan(List *qptlist,				  List *qpqual,				  Index scanrelid,				  Plan *subplan){	SubqueryScan *node = makeNode(SubqueryScan);	Plan	   *plan = &node->scan.plan;	/*	 * Cost is figured here for the convenience of prepunion.c.  Note this	 * is only correct for the case where qpqual is empty; otherwise	 * caller should overwrite cost with a better estimate.	 */	copy_plan_costsize(plan, subplan);	plan->total_cost += cpu_tuple_cost * subplan->plan_rows;	plan->targetlist = qptlist;	plan->qual = qpqual;	plan->lefttree = NULL;	plan->righttree = NULL;	node->scan.scanrelid = scanrelid;	node->subplan = subplan;	return node;}static FunctionScan *make_functionscan(List *qptlist,				  List *qpqual,				  Index scanrelid){	FunctionScan *node = makeNode(FunctionScan);	Plan	   *plan = &node->scan.plan;	/* cost should be inserted by caller */	plan->targetlist = qptlist;	plan->qual = qpqual;	plan->lefttree = NULL;	plan->righttree = NULL;	node->scan.scanrelid = scanrelid;	return node;}Append *make_append(List *appendplans, bool isTarget, List *tlist){	Append	   *node = makeNode(Append);	Plan	   *plan = &node->plan;	List	   *subnode;	/*	 * Compute cost as sum of subplan costs.  We charge nothing extra for	 * the Append itself, which perhaps is too optimistic, but since it	 * doesn't do any selection or projection, it is a pretty cheap node.	 */	plan->startup_cost = 0;	plan->total_cost = 0;	plan->plan_rows = 0;	plan->plan_width = 0;	foreach(subnode, appendplans)	{		Plan	   *subplan = (Plan *) lfirst(subnode);		if (subnode == appendplans)		/* first node? */			plan->startup_cost = subplan->startup_cost;		plan->total_cost += subplan->total_cost;		plan->plan_rows += subplan->plan_rows;		if (plan->plan_width < subplan->plan_width)			plan->plan_width = subplan->plan_width;	}	plan->targetlist = tlist;	plan->qual = NIL;	plan->lefttree = NULL;	plan->righttree = NULL;	node->appendplans = appendplans;	node->isTarget = isTarget;	return node;}static NestLoop *make_nestloop(List *tlist,			  List *joinclauses,			  List *otherclauses,			  Plan *lefttree,			  Plan *righttree,			  JoinType jointype){	NestLoop   *node = makeNode(NestLoop);	Plan	   *plan = &node->join.plan;	/* cost should be inserted by caller */	plan->targetlist = tlist;	plan->qual = otherclauses;	plan->lefttree = lefttree;	plan->righttree = righttree;	node->join.jointype = jointype;	node->join.joinqual = joinclauses;	return node;}static HashJoin *make_hashjoin(List *tlist,			  List *joinclauses,			  List *otherclauses,			  List *hashclauses,			  Plan *lefttree,			  Plan *righttree,			  JoinType jointype){	HashJoin   *node = makeNode(HashJoin);	Plan	   *plan = &node->join.plan;	/* cost should be inserted by caller */	plan->targetlist = tlist;	plan->qual = otherclauses;	plan->lefttree = lefttree;	plan->righttree = righttree;	node->hashclauses = hashclauses;	node->join.jointype = jointype;	node->join.joinqual = joinclauses;	return node;}static Hash *make_hash(List *tlist, List *hashkeys, Plan *lefttree){	Hash	   *node = makeNode(Hash);	Plan	   *plan = &node->plan;	copy_plan_costsize(plan, lefttree);	/*	 * For plausibility, make startup & total costs equal total cost of	 * input plan; this only affects EXPLAIN display not decisions.	 */	plan->startup_cost = plan->total_cost;	plan->targetlist = tlist;	plan->qual = NIL;	plan->lefttree = lefttree;	plan->righttree = NULL;	node->hashkeys = hashkeys;	return node;}static MergeJoin *make_mergejoin(List *tlist,			   List *joinclauses,			   List *otherclauses,			   List *mergeclauses,			   Plan *lefttree,			   Plan *righttree,			   JoinType jointype){	MergeJoin  *node = makeNode(MergeJoin);	Plan	   *plan = &node->join.plan;	/* cost should be inserted by caller */	plan->targetlist = tlist;	plan->qual = otherclauses;	plan->lefttree = lefttree;	plan->righttree = righttree;	node->mergeclauses = mergeclauses;	node->join.jointype = jointype;	node->join.joinqual = joinclauses;	return node;}/* * make_sort --- basic routine to build a Sort plan node * * Caller must have built the sortColIdx and sortOperators arrays already. */static Sort *make_sort(Query *root, List *tlist, Plan *lefttree, int numCols,		  AttrNumber *sortColIdx, Oid *sortOperators){	Sort	   *node = makeNode(Sort);	Plan	   *plan = &node->plan;	Path		sort_path;		/* dummy for result of cost_sort */	copy_plan_costsize(plan, lefttree); /* only care about copying size */	cost_sort(&sort_path, root, NIL,			  lefttree->total_cost,			  lefttree->plan_rows,			  lefttree->plan_width);	plan->startup_cost = sort_path.startup_cost;	plan->total_cost = sort_path.total_cost;	plan->targetlist = tlist;	plan->qual = NIL;	plan->lefttree = lefttree;	plan->righttree = NULL;	node->numCols = numCols;	node->sortColIdx = sortColIdx;	node->sortOperators = sortOperators;	return node;}/* * add_sort_column --- utility subroutine for building sort info arrays * * We need this routine because the same column might be selected more than * once as a sort key column; if so, the extra mentions are redundant. * * Caller is assumed to have allocated the arrays large enough for the * max possible number of columns.	Return value is the new column count. */static intadd_sort_column(AttrNumber colIdx, Oid sortOp,				int numCols, AttrNumber *sortColIdx, Oid *sortOperators){	int			i;	for (i = 0; i < numCols; i++)	{		if (sortColIdx[i] == colIdx)		{			/* Already sorting by this col, so extra sort key is useless */			return numCols;		}	}	/* Add the column */	sortColIdx[numCols] = colIdx;	sortOperators[numCols] = sortOp;	return numCols + 1;}/* * make_sort_from_pathkeys *	  Create sort plan to sort according to given pathkeys * *	  'lefttree' is the node which yields input tuples *	  'pathkeys' is the list of pathkeys by which the result is to be sorted * * We must convert the pathkey information into arrays of sort key column * numbers and sort operator OIDs. * * If the pathkeys include expressions that aren't simple Vars, we will * usually need to add resjunk items to the input plan's targetlist to * compute these expressions (since the Sort node itself won't do it). * If the input plan type isn't one that can do projections, this means * adding a Result node just to do the projection. */static Sort *make_sort_from_pathkeys(Query *root, Plan *lefttree, List *pathkeys){	List	   *tlist = lefttree->targetlist;	List	   *sort_tlist;	List	   *i;	int			numsortkeys;	AttrNumber *sortColIdx;	Oid		   *sortOperators;	/* We will need at most length(pathkeys) sort columns; possibly less */	numsortkeys = length(pathkeys);	sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));	sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));	numsortkeys = 0;	foreach(i, pathkeys)	{		List	   *keysublist = (List *) lfirst(i);		PathKeyItem *pathkey = NULL;		Resdom	   *resdom = NULL;		List	   *j;		/*		 * We can sort by any one of the sort key items listed in this		 * sublist.  For now, we take the first one that corresponds to an		 * available Var in the tlist.	If there isn't any, use the first		 * one that is an expression in the input's vars.		 *		 * XXX if we have a choice, is there any way of figuring out which		 * might be cheapest to execute?  (For example, int4lt is likely		 * much cheaper to execute than numericlt, but both might appear		 * in the same pathkey sublist...)	Not clear that we ever will		 * have a choice in practice, so it may not matter.		 */		foreach(j, keysublist)		{			pathkey = lfirst(j);			Assert(IsA(pathkey, PathKeyItem));			resdom = tlist_member(pathkey->key, tlist);			if (resdom)				break;		}		if (!resdom)		{			/* No matching Var; look for a computable expression */			foreach(j, keysublist)			{				List   *exprvars;				List   *k;				pathkey = lfirst(j);				exprvars = pull_var_clause(pathkey->key, false);				foreach(k, exprvars)				{

⌨️ 快捷键说明

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