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

📄 xfunc.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
	tupl = SearchSysCacheTuple(PROOID,							   ObjectIdGetDatum(funcid),							   0, 0, 0);	if (!HeapTupleIsValid(tupl))		elog(ERROR, "Cache lookup failed for procedure %u", funcid);	proc = (Form_pg_proc) GETSTRUCT(tupl);	/*	 * * if it's a Postquel function, its cost is stored in the *	 * associated plan.	 */	if (proc->prolang == SQLlanguageId)	{		LispValue	tmpplan;		List		planlist;		if (IsA(node, Oper) ||get_func_planlist((Func) node) == LispNil)		{			Oid		   *argOidVect;		/* vector of argtypes */			char	   *pq_src; /* text of PQ function */			int			nargs;	/* num args to PQ function */			QueryTreeList *queryTree_list;		/* dummy variable */			/*			 * * plan the function, storing it in the Func node for later *			 * use by the executor.			 */			pq_src = (char *) textout(&(proc->prosrc));			nargs = proc->pronargs;			if (nargs > 0)				argOidVect = proc->proargtypes;			planlist = (List) pg_parse_and_plan(pq_src, argOidVect, nargs,										   &parseTree_list, None, FALSE);			if (IsA(node, Func))				set_func_planlist((Func) node, planlist);		}		else		{						/* plan has been cached inside the Func								 * node already */			planlist = get_func_planlist((Func) node);		}		/*		 * * Return the sum of the costs of the plans (the PQ function *		 * may have many queries in its body).		 */		foreach(tmpplan, planlist)			cost += get_cost((Plan) lfirst(tmpplan));		return cost;	}	else	{							/* it's a C function */		/*		 * *  find the cost of evaluating the function's arguments *  and		 * the width of the operands		 */		for (tmpclause = args; tmpclause != LispNil;			 tmpclause = lnext(tmpclause))		{			if ((operand = lfirst(tmpclause)) != LispNil)			{				cost += xfunc_local_expense(operand);				width += xfunc_width(operand);			}		}		/*		 * * when stats become available, add in cost of accessing		 * secondary * and tertiary storage here.		 */		return (cost +				(Cost) proc->propercall_cpu +		(Cost) proc->properbyte_cpu * (Cost) proc->probyte_pct / 100.00 *				(Cost) width		/*		 * Pct_of_obj_in_mem DISK_COST * proc->probyte_pct/100.00 * width		 * Pct_of_obj_on_disk + ARCH_COST * proc->probyte_pct/100.00 *		 * width Pct_of_obj_on_arch		 */			);	}}/* ** xfunc_width **    recursively find the width of a expression */intxfunc_width(LispValue clause){	Relation	rd;				/* Relation Descriptor */	HeapTuple	tupl;			/* structure to hold a cached tuple */	Form_pg_type type;			/* structure to hold a type tuple */	int			retval = 0;	if (IsA(clause, Const))	{		/* base case: width is the width of this constant */		retval = get_constlen((Const) clause);		goto exit;	}	else if (IsA(clause, ArrayRef))	{		/* base case: width is width of the refelem within the array */		retval = get_refelemlength((ArrayRef) clause);		goto exit;	}	else if (IsA(clause, Var))	{		/* base case: width is width of this attribute */		tupl = SearchSysCacheTuple(TYPOID,							 ObjectIdGetDatum(get_vartype((Var) clause)),								   0, 0, 0);		if (!HeapTupleIsValid(tupl))			elog(ERROR, "Cache lookup failed for type %u",				 get_vartype((Var) clause));		type = (Form_pg_type) GETSTRUCT(tupl);		if (get_varattno((Var) clause) == 0)		{			/* clause is a tuple.  Get its width */			rd = heap_open(type->typrelid);			retval = xfunc_tuple_width(rd);			heap_close(rd);		}		else		{			/* attribute is a base type */			retval = type->typlen;		}		goto exit;	}	else if (IsA(clause, Param))	{		if (typeidTypeRelids(get_paramtype((Param) clause)))		{			/* Param node returns a tuple.	Find its width */			rd = heap_open(typeidTypeRelids(get_paramtype((Param) clause)));			retval = xfunc_tuple_width(rd);			heap_close(rd);		}		else if (get_param_tlist((Param) clause) != LispNil)		{			/* Param node projects a complex type */			Assert(length(get_param_tlist((Param) clause)) == 1);		/* sanity */			retval = xfunc_width((LispValue)					  get_expr(lfirst(get_param_tlist((Param) clause))));		}		else		{			/* Param node returns a base type */			retval = typeLen(typeidType(get_paramtype((Param) clause)));		}		goto exit;	}	else if (IsA(clause, Iter))	{		/*		 * * An Iter returns a setof things, so return the width of a		 * single * thing. * Note:	THIS MAY NOT WORK RIGHT WHEN AGGS GET		 * FIXED, * SINCE AGG FUNCTIONS CHEW ON THE WHOLE SETOF THINGS!!!! *		 * This whole Iter business is bogus, anyway.		 */		retval = xfunc_width(get_iterexpr((Iter) clause));		goto exit;	}	else if (fast_is_clause(clause))	{		/*		 * * get function associated with this Oper, and treat this as * a		 * Func		 */		tupl = SearchSysCacheTuple(OPROID,					   ObjectIdGetDatum(get_opno((Oper) get_op(clause))),								   0, 0, 0);		if (!HeapTupleIsValid(tupl))			elog(ERROR, "Cache lookup failed for procedure %u",				 get_opno((Oper) get_op(clause)));		return (xfunc_func_width		((RegProcedure) (((Form_pg_operator) (GETSTRUCT(tupl)))->oprcode),		 (LispValue) get_opargs(clause)));	}	else if (fast_is_funcclause(clause))	{		Func		func = (Func) get_function(clause);		if (get_func_tlist(func) != LispNil)		{			/*			 * this function has a projection on it.  Get the length of			 * the projected attribute			 */			Assert(length(get_func_tlist(func)) == 1);	/* sanity */			retval = xfunc_width((LispValue)								 get_expr(lfirst(get_func_tlist(func))));			goto exit;		}		else		{			return (xfunc_func_width((RegProcedure) get_funcid(func),									 (LispValue) get_funcargs(clause)));		}	}	else	{		elog(ERROR, "Clause node of undetermined type");		return -1;	}exit:	if (retval == -1)		retval = VARLEN_DEFAULT;	return retval;}/* ** xfunc_card_unreferenced: **   find all relations not referenced in clause, and multiply their ** cardinalities.	Ignore relation of cardinality 0. ** User may pass in referenced list, if they know it (useful ** for joins). */static Countxfunc_card_unreferenced(Query *queryInfo,						LispValue clause, Relids referenced){	Relids		unreferenced,				allrelids = LispNil;	LispValue	temp;	/* find all relids of base relations referenced in query */	foreach(temp, queryInfo->base_rel_list)	{		Assert(lnext(get_relids((RelOptInfo) lfirst(temp))) == LispNil);		allrelids = lappend(allrelids,						  lfirst(get_relids((RelOptInfo) lfirst(temp))));	}	/* find all relids referenced in query but not in clause */	if (!referenced)		referenced = xfunc_find_references(clause);	unreferenced = set_difference(allrelids, referenced);	return xfunc_card_product(unreferenced);}/* ** xfunc_card_product **   multiple together cardinalities of a list relations. */Countxfunc_card_product(Query *queryInfo, Relids relids){	LispValue	cinfonode;	LispValue	temp;	RelOptInfo	currel;	Cost		tuples;	Count		retval = 0;	foreach(temp, relids)	{		currel = get_rel(lfirst(temp));		tuples = get_tuples(currel);		if (tuples)		{						/* not of cardinality 0 */			/* factor in the selectivity of all zero-cost clauses */			foreach(cinfonode, get_restrictinfo(currel))			{				if (!xfunc_expense(queryInfo, get_clause((RestrictInfo) lfirst(cinfonode))))					tuples *= compute_clause_selec(queryInfo,							get_clause((RestrictInfo) lfirst(cinfonode)),												   LispNil);			}			if (retval == 0)				retval = tuples;			else				retval *= tuples;		}	}	if (retval == 0)		retval = 1;				/* saves caller from dividing by zero */	return retval;}/* ** xfunc_find_references: **   Traverse a clause and find all relids referenced in the clause. */Listxfunc_find_references(LispValue clause){	List		retval = (List) LispNil;	LispValue	tmpclause;	/* Base cases */	if (IsA(clause, Var))		return lispCons(lfirst(get_varid((Var) clause)), LispNil);	else if (IsA(clause, Const) ||IsA(clause, Param))		return (List) LispNil;	/* recursion */	else if (IsA(clause, Iter))		/*		 * Too low. Should multiply by the expected number of iterations.		 * maybe		 */		return xfunc_find_references(get_iterexpr((Iter) clause));	else if (IsA(clause, ArrayRef))		return xfunc_find_references(get_refexpr((ArrayRef) clause));	else if (fast_is_clause(clause))	{		/* string together result of all operands of Oper */		for (tmpclause = (LispValue) get_opargs(clause); tmpclause != LispNil;			 tmpclause = lnext(tmpclause))			retval = nconc(retval, xfunc_find_references(lfirst(tmpclause)));		return retval;	}	else if (fast_is_funcclause(clause))	{		/* string together result of all args of Func */		for (tmpclause = (LispValue) get_funcargs(clause);			 tmpclause != LispNil;			 tmpclause = lnext(tmpclause))			retval = nconc(retval, xfunc_find_references(lfirst(tmpclause)));		return retval;	}	else if (fast_not_clause(clause))		return xfunc_find_references(lsecond(clause));	else if (fast_or_clause(clause) || fast_and_clause(clause))	{		/* string together result of all operands of OR */		for (tmpclause = lnext(clause); tmpclause != LispNil;			 tmpclause = lnext(tmpclause))			retval = nconc(retval, xfunc_find_references(lfirst(tmpclause)));		return retval;	}	else	{		elog(ERROR, "Clause node of undetermined type");		return (List) LispNil;	}}/* ** xfunc_primary_join: **   Find the primary join clause: for Hash and Merge Joins, this is the ** min rank Hash or Merge clause, while for Nested Loop it's the ** min rank pathclause */LispValuexfunc_primary_join(JoinPath pathnode){	LispValue	joinclauselist = get_pathrestrictinfo(pathnode);	RestrictInfo mincinfo;	LispValue	tmplist;	LispValue	minclause = LispNil;	Cost		minrank,				tmprank;	if (IsA(pathnode, MergePath))	{		for (tmplist = get_path_mergeclauses((MergePath) pathnode),			 minclause = lfirst(tmplist),			 minrank = xfunc_rank(minclause);			 tmplist != LispNil;			 tmplist = lnext(tmplist))			if ((tmprank = xfunc_rank(lfirst(tmplist)))				< minrank)			{				minrank = tmprank;				minclause = lfirst(tmplist);			}		return minclause;	}	else if (IsA(pathnode, HashPath))	{		for (tmplist = get_path_hashclauses((HashPath) pathnode),			 minclause = lfirst(tmplist),			 minrank = xfunc_rank(minclause);			 tmplist != LispNil;			 tmplist = lnext(tmplist))			if ((tmprank = xfunc_rank(lfirst(tmplist)))				< minrank)			{				minrank = tmprank;				minclause = lfirst(tmplist);			}		return minclause;	}	/* if we drop through, it's nested loop join */	if (joinclauselist == LispNil)		return LispNil;	for (tmplist = joinclauselist, mincinfo = (RestrictInfo) lfirst(joinclauselist),		 minrank = xfunc_rank(get_clause((RestrictInfo) lfirst(tmplist)));		 tmplist != LispNil;		 tmplist = lnext(tmplist))		if ((tmprank = xfunc_rank(get_clause((RestrictInfo) lfirst(tmplist))))			< minrank)		{			minrank = tmprank;			mincinfo = (RestrictInfo) lfirst(tmplist);		}	return (LispValue) get_clause(mincinfo);}/* ** xfunc_get_path_cost **   get the expensive function costs of the path */Costxfunc_get_path_cost(Query *queryInfo, Path pathnode){	Cost		cost = 0;	LispValue	tmplist;	Cost		selec = 1.0;	/*	 * * first add in the expensive local function costs. * We ensure that	 * the clauses are sorted by rank, so that we * know (via	 * selectivities) the number of tuples that will be checked * by each	 * function.  If we're not doing any optimization of expensive *	 * functions, we don't sort.	 */	if (XfuncMode != XFUNC_OFF)		set_locrestrictinfo(pathnode, lisp_qsort(get_loc_restrictinfo(pathnode),												 xfunc_cinfo_compare));	for (tmplist = get_loc_restrictinfo(pathnode), selec = 1.0;		 tmplist != LispNil;		 tmplist = lnext(tmplist))	{		cost += (Cost) (xfunc_local_expense(get_clause((RestrictInfo) lfirst(tmplist)))					  * (Cost) get_tuples(get_parent(pathnode)) * selec);		selec *= compute_clause_selec(queryInfo,							  get_clause((RestrictInfo) lfirst(tmplist)),									  LispNil);	}	/*	 * * Now add in any node-specific expensive function costs. * Again,	 * we must ensure that the clauses are sorted by rank.	 */	if (IsA(pathnode, JoinPath))	{		if (XfuncMode != XFUNC_OFF)			set_pathrestrictinfo((JoinPath) pathnode, lisp_qsort							  (get_pathrestrictinfo((JoinPath) pathnode),							   xfunc_cinfo_compare));		for (tmplist = get_pathrestrictinfo((JoinPath) pathnode), selec = 1.0;			 tmplist != LispNil;			 tmplist = lnext(tmplist))		{			cost += (Cost) (xfunc_local_expense(get_clause((RestrictInfo) lfirst(tmplist)))					  * (Cost) get_tuples(get_parent(pathnode)) * selec);			selec *= compute_clause_selec(queryInfo,							  get_clause((RestrictInfo) lfirst(tmplist)),										  LispNil);		}	}	if (IsA(pathnode, HashPath))	{		if (XfuncMode != XFUNC_OFF)			set_path_hashclauses				((HashPath) pathnode,				 lisp_qsort(get_path_hashclauses((HashPath) pathnode),							xfunc_clause_compare));		for (tmplist = get_path_hashclauses((HashPath) pathnode), selec = 1.0;			 tmplist != LispNil;			 tmplist = lnext(tmplist))		{			cost += (Cost) (xfunc_local_expense(lfirst(tmplist))					  * (Cost) get_tuples(get_parent(pathnode)) * selec);			selec *= compute_clause_selec(queryInfo,										  lfirst(tmplist), LispNil);		}	}	if (IsA(pathnode, MergePath))	{		if (XfuncMode != XFUNC_OFF)			set_path_mergeclauses				((MergePath) pathnode,				 lisp_qsort(get_path_mergeclauses((MergePath) pathnode),							xfunc_clause_compare));		for (tmplist = get_path_mergeclauses((MergePath) pathnode), selec = 1.0;

⌨️ 快捷键说明

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