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

📄 createplan.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 5 页
字号:
					if (!tlist_member(lfirst(k), tlist))						break;				}				freeList(exprvars);				if (!k)					break;		/* found usable expression */			}			if (!j)				elog(ERROR, "could not find pathkey item to sort");			/*			 * Do we need to insert a Result node?			 *			 * Currently, the only non-projection-capable plan types we can			 * see here are Append and Unique.			 */			if (IsA(lefttree, Append) || IsA(lefttree, Unique))			{				tlist = copyObject(tlist);				lefttree = (Plan *) make_result(tlist, NULL, lefttree);			}			/*			 * Add resjunk entry to input's tlist			 */			resdom = makeResdom(length(tlist) + 1,								exprType(pathkey->key),								exprTypmod(pathkey->key),								NULL,								true);			tlist = lappend(tlist,							makeTargetEntry(resdom,											(Expr *) pathkey->key));			lefttree->targetlist = tlist;		/* just in case NIL before */		}		/*		 * The column might already be selected as a sort key, if the		 * pathkeys contain duplicate entries.	(This can happen in		 * scenarios where multiple mergejoinable clauses mention the same		 * var, for example.)  So enter it only once in the sort arrays.		 */		numsortkeys = add_sort_column(resdom->resno, pathkey->sortop,								 numsortkeys, sortColIdx, sortOperators);	}	Assert(numsortkeys > 0);	/* Give Sort node its own copy of the tlist (still necessary?) */	sort_tlist = copyObject(tlist);	return make_sort(root, sort_tlist, lefttree, numsortkeys,					 sortColIdx, sortOperators);}/* * make_sort_from_sortclauses *	  Create sort plan to sort according to given sortclauses * *	  'tlist' is the targetlist *	  'lefttree' is the node which yields input tuples *	  'sortcls' is a list of SortClauses */Sort *make_sort_from_sortclauses(Query *root, List *tlist,						   Plan *lefttree, List *sortcls){	List	   *sort_tlist;	List	   *i;	int			numsortkeys;	AttrNumber *sortColIdx;	Oid		   *sortOperators;	/* We will need at most length(sortcls) sort columns; possibly less */	numsortkeys = length(sortcls);	sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));	sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));	numsortkeys = 0;	foreach(i, sortcls)	{		SortClause *sortcl = (SortClause *) lfirst(i);		TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist);		Resdom	   *resdom = tle->resdom;		/*		 * Check for the possibility of duplicate order-by clauses --- the		 * parser should have removed 'em, but no point in sorting		 * redundantly.		 */		numsortkeys = add_sort_column(resdom->resno, sortcl->sortop,								 numsortkeys, sortColIdx, sortOperators);	}	Assert(numsortkeys > 0);	/* Give Sort node its own copy of the tlist (still necessary?) */	sort_tlist = copyObject(tlist);	return make_sort(root, sort_tlist, lefttree, numsortkeys,					 sortColIdx, sortOperators);}/* * make_sort_from_groupcols *	  Create sort plan to sort based on grouping columns * * 'groupcls' is the list of GroupClauses * 'grpColIdx' gives the column numbers to use * * This might look like it could be merged with make_sort_from_sortclauses, * but presently we *must* use the grpColIdx[] array to locate sort columns, * because the child plan's tlist is not marked with ressortgroupref info * appropriate to the grouping node.  So, only the sortop is used from the * GroupClause entries. */Sort *make_sort_from_groupcols(Query *root,						 List *groupcls,						 AttrNumber *grpColIdx,						 Plan *lefttree){	List	   *sub_tlist = lefttree->targetlist;	List	   *sort_tlist;	int			grpno = 0;	List	   *i;	int			numsortkeys;	AttrNumber *sortColIdx;	Oid		   *sortOperators;	/* We will need at most length(groupcls) sort columns; possibly less */	numsortkeys = length(groupcls);	sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));	sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));	numsortkeys = 0;	foreach(i, groupcls)	{		GroupClause *grpcl = (GroupClause *) lfirst(i);		TargetEntry *tle = get_tle_by_resno(sub_tlist, grpColIdx[grpno]);		Resdom	   *resdom = tle->resdom;		/*		 * Check for the possibility of duplicate group-by clauses --- the		 * parser should have removed 'em, but no point in sorting		 * redundantly.		 */		numsortkeys = add_sort_column(resdom->resno, grpcl->sortop,								 numsortkeys, sortColIdx, sortOperators);		grpno++;	}	Assert(numsortkeys > 0);	/* Give Sort node its own copy of the tlist (still necessary?) */	sort_tlist = copyObject(sub_tlist);	return make_sort(root, sort_tlist, lefttree, numsortkeys,					 sortColIdx, sortOperators);}Material *make_material(List *tlist, Plan *lefttree){	Material   *node = makeNode(Material);	Plan	   *plan = &node->plan;	/* cost should be inserted by caller */	plan->targetlist = tlist;	plan->qual = NIL;	plan->lefttree = lefttree;	plan->righttree = NULL;	return node;}/* * materialize_finished_plan: stick a Material node atop a completed plan * * There are a couple of places where we want to attach a Material node * after completion of subquery_planner().	This currently requires hackery. * Since subquery_planner has already run SS_finalize_plan on the subplan * tree, we have to kluge up parameter lists for the Material node. * Possibly this could be fixed by postponing SS_finalize_plan processing * until setrefs.c is run? */Plan *materialize_finished_plan(Plan *subplan){	Plan	   *matplan;	Path		matpath;		/* dummy for result of cost_material */	matplan = (Plan *) make_material(subplan->targetlist, subplan);	/* Set cost data */	cost_material(&matpath,				  subplan->total_cost,				  subplan->plan_rows,				  subplan->plan_width);	matplan->startup_cost = matpath.startup_cost;	matplan->total_cost = matpath.total_cost;	matplan->plan_rows = subplan->plan_rows;	matplan->plan_width = subplan->plan_width;	/* parameter kluge --- see comments above */	matplan->extParam = bms_copy(subplan->extParam);	matplan->allParam = bms_copy(subplan->allParam);	return matplan;}Agg *make_agg(Query *root, List *tlist, List *qual,		 AggStrategy aggstrategy,		 int numGroupCols, AttrNumber *grpColIdx,		 long numGroups, int numAggs,		 Plan *lefttree){	Agg		   *node = makeNode(Agg);	Plan	   *plan = &node->plan;	Path		agg_path;		/* dummy for result of cost_agg */	QualCost	qual_cost;	node->aggstrategy = aggstrategy;	node->numCols = numGroupCols;	node->grpColIdx = grpColIdx;	node->numGroups = numGroups;	copy_plan_costsize(plan, lefttree); /* only care about copying size */	cost_agg(&agg_path, root,			 aggstrategy, numAggs,			 numGroupCols, numGroups,			 lefttree->startup_cost,			 lefttree->total_cost,			 lefttree->plan_rows);	plan->startup_cost = agg_path.startup_cost;	plan->total_cost = agg_path.total_cost;	/*	 * We will produce a single output tuple if not grouping, and a tuple	 * per group otherwise.	 */	if (aggstrategy == AGG_PLAIN)		plan->plan_rows = 1;	else		plan->plan_rows = numGroups;	/*	 * We also need to account for the cost of evaluation of the qual (ie,	 * the HAVING clause) and the tlist.  Note that cost_qual_eval doesn't	 * charge anything for Aggref nodes; this is okay since they are	 * really comparable to Vars.	 *	 * See notes in grouping_planner about why this routine and make_group	 * are the only ones in this file that worry about tlist eval cost.	 */	if (qual)	{		cost_qual_eval(&qual_cost, qual);		plan->startup_cost += qual_cost.startup;		plan->total_cost += qual_cost.startup;		plan->total_cost += qual_cost.per_tuple * plan->plan_rows;	}	cost_qual_eval(&qual_cost, tlist);	plan->startup_cost += qual_cost.startup;	plan->total_cost += qual_cost.startup;	plan->total_cost += qual_cost.per_tuple * plan->plan_rows;	plan->qual = qual;	plan->targetlist = tlist;	plan->lefttree = lefttree;	plan->righttree = (Plan *) NULL;	return node;}Group *make_group(Query *root,		   List *tlist,		   int numGroupCols,		   AttrNumber *grpColIdx,		   double numGroups,		   Plan *lefttree){	Group	   *node = makeNode(Group);	Plan	   *plan = &node->plan;	Path		group_path;		/* dummy for result of cost_group */	QualCost	qual_cost;	node->numCols = numGroupCols;	node->grpColIdx = grpColIdx;	copy_plan_costsize(plan, lefttree); /* only care about copying size */	cost_group(&group_path, root,			   numGroupCols, numGroups,			   lefttree->startup_cost,			   lefttree->total_cost,			   lefttree->plan_rows);	plan->startup_cost = group_path.startup_cost;	plan->total_cost = group_path.total_cost;	/* One output tuple per estimated result group */	plan->plan_rows = numGroups;	/*	 * We also need to account for the cost of evaluation of the tlist.	 *	 * XXX this double-counts the cost of evaluation of any expressions used	 * for grouping, since in reality those will have been evaluated at a	 * lower plan level and will only be copied by the Group node. Worth	 * fixing?	 *	 * See notes in grouping_planner about why this routine and make_agg are	 * the only ones in this file that worry about tlist eval cost.	 */	cost_qual_eval(&qual_cost, tlist);	plan->startup_cost += qual_cost.startup;	plan->total_cost += qual_cost.startup;	plan->total_cost += qual_cost.per_tuple * plan->plan_rows;	plan->qual = NIL;	plan->targetlist = tlist;	plan->lefttree = lefttree;	plan->righttree = (Plan *) NULL;	return node;}/* * distinctList is a list of SortClauses, identifying the targetlist items * that should be considered by the Unique filter. */Unique *make_unique(List *tlist, Plan *lefttree, List *distinctList){	Unique	   *node = makeNode(Unique);	Plan	   *plan = &node->plan;	int			numCols = length(distinctList);	int			keyno = 0;	AttrNumber *uniqColIdx;	List	   *slitem;	copy_plan_costsize(plan, lefttree);	/*	 * Charge one cpu_operator_cost per comparison per input tuple. We	 * assume all columns get compared at most of the tuples.  (XXX	 * probably this is an overestimate.)	 */	plan->total_cost += cpu_operator_cost * plan->plan_rows * numCols;	/*	 * plan->plan_rows is left as a copy of the input subplan's plan_rows;	 * ie, we assume the filter removes nothing.  The caller must alter	 * this if he has a better idea.	 */	plan->targetlist = tlist;	plan->qual = NIL;	plan->lefttree = lefttree;	plan->righttree = NULL;	/*	 * convert SortClause list into array of attr indexes, as wanted by	 * exec	 */	Assert(numCols > 0);	uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);	foreach(slitem, distinctList)	{		SortClause *sortcl = (SortClause *) lfirst(slitem);		TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist);		uniqColIdx[keyno++] = tle->resdom->resno;	}	node->numCols = numCols;	node->uniqColIdx = uniqColIdx;	return node;}/* * distinctList is a list of SortClauses, identifying the targetlist items * that should be considered by the SetOp filter. */SetOp *make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree,		   List *distinctList, AttrNumber flagColIdx){	SetOp	   *node = makeNode(SetOp);	Plan	   *plan = &node->plan;	int			numCols = length(distinctList);	int			keyno = 0;	AttrNumber *dupColIdx;	List	   *slitem;	copy_plan_costsize(plan, lefttree);	/*	 * Charge one cpu_operator_cost per comparison per input tuple. We	 * assume all columns get compared at most of the tuples.	 */	plan->total_cost += cpu_operator_cost * plan->plan_rows * numCols;	/*	 * We make the unsupported assumption that there will be 10% as many	 * tuples out as in.  Any way to do better?	 */	plan->plan_rows *= 0.1;	if (plan->plan_rows < 1)		plan->plan_rows = 1;	plan->targetlist = tlist;	plan->qual = NIL;	plan->lefttree = lefttree;	plan->righttree = NULL;	/*	 * convert SortClause list into array of attr indexes, as wanted by	 * exec	 */	Assert(numCols > 0);	dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);	foreach(slitem, distinctList)	{		SortClause *sortcl = (SortClause *) lfirst(slitem);		TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist);		dupColIdx[keyno++] = tle->resdom->resno;	}	node->cmd = cmd;	node->numCols = numCols;	node->dupColIdx = dupColIdx;	node->flagColIdx = flagColIdx;	return node;}Limit *make_limit(List *tlist, Plan *lefttree,		   Node *limitOffset, Node *limitCount){	Limit	   *node = makeNode(Limit);	Plan	   *plan = &node->plan;	copy_plan_costsize(plan, lefttree);	/*	 * If offset/count are constants, adjust the output rows count and	 * costs accordingly.  This is only a cosmetic issue if we are at top	 * level, but if we are building a subquery then it's important to	 * report correct info to the outer planner.	 */	if (limitOffset && IsA(limitOffset, Const))	{		Const	   *limito = (Const *) limitOffset;		int32		offset = DatumGetInt32(limito->con

⌨️ 快捷键说明

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