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

📄 xfunc.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
			 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);		}	}	Assert(cost >= 0);	return cost;}/* ** Recalculate the cost of a path node.  This includes the basic cost of the ** node, as well as the cost of its expensive functions. ** We need to do this to the parent after pulling a clause from a child into a ** parent.  Thus we should only be calling this function on JoinPaths. */Costxfunc_total_path_cost(JoinPath pathnode){	Cost		cost = xfunc_get_path_cost((Path) pathnode);	Assert(IsA(pathnode, JoinPath));	if (IsA(pathnode, MergePath))	{		MergePath	mrgnode = (MergePath) pathnode;		cost += cost_mergejoin(get_path_cost((Path) get_outerjoinpath(mrgnode)),						get_path_cost((Path) get_innerjoinpath(mrgnode)),							   get_outersortkeys(mrgnode),							   get_innersortkeys(mrgnode),						   get_tuples(get_parent((Path) get_outerjoinpath												 (mrgnode))),						   get_tuples(get_parent((Path) get_innerjoinpath												 (mrgnode))),							get_width(get_parent((Path) get_outerjoinpath												 (mrgnode))),							get_width(get_parent((Path) get_innerjoinpath												 (mrgnode))));		Assert(cost >= 0);		return cost;	}	else if (IsA(pathnode, HashPath))	{		HashPath hashnode = (HashPath) pathnode;		cost += cost_hashjoin(get_path_cost((Path) get_outerjoinpath(hashnode)),					   get_path_cost((Path) get_innerjoinpath(hashnode)),							  get_outerhashkeys(hashnode),							  get_innerhashkeys(hashnode),						   get_tuples(get_parent((Path) get_outerjoinpath												 (hashnode))),						   get_tuples(get_parent((Path) get_innerjoinpath												 (hashnode))),							get_width(get_parent((Path) get_outerjoinpath												 (hashnode))),							get_width(get_parent((Path) get_innerjoinpath												 (hashnode))));		Assert(cost >= 0);		return cost;	}	else/* Nested Loop Join */	{		cost += cost_nestloop(get_path_cost((Path) get_outerjoinpath(pathnode)),					   get_path_cost((Path) get_innerjoinpath(pathnode)),						   get_tuples(get_parent((Path) get_outerjoinpath												 (pathnode))),						   get_tuples(get_parent((Path) get_innerjoinpath												 (pathnode))),							get_pages(get_parent((Path) get_outerjoinpath												 (pathnode))),							IsA(get_innerjoinpath(pathnode), IndexPath));		Assert(cost >= 0);		return cost;	}}/* ** xfunc_expense_per_tuple **    return the expense of the join *per-tuple* of the input relation. ** The cost model here is that a join costs **		k*card(outer)*card(inner) + l*card(outer) + m*card(inner) + n ** ** We treat the l and m terms by considering them to be like restrictions ** constrained to be right under the join.  Thus the cost per inner and ** cost per outer of the join is different, reflecting these virtual nodes. ** ** The cost per tuple of outer is k + l/referenced(inner).  Cost per tuple ** of inner is k + m/referenced(outer). ** The constants k, l, m and n depend on the join method.	Measures here are ** based on the costs in costsize.c, with fudging for HashJoin and Sorts to ** make it fit our model (the 'q' in HashJoin results in a ** card(outer)/card(inner) term, and sorting results in a log term. */Costxfunc_expense_per_tuple(JoinPath joinnode, int whichchild){	RelOptInfo	outerrel = get_parent((Path) get_outerjoinpath(joinnode));	RelOptInfo	innerrel = get_parent((Path) get_innerjoinpath(joinnode));	Count		outerwidth = get_width(outerrel);	Count		outers_per_page = ceil(BLCKSZ / (outerwidth + MinTupleSize));	if (IsA(joinnode, HashPath))	{		if (whichchild == INNER)			return (1 + _CPU_PAGE_WEIGHT_) * outers_per_page / NBuffers;		else			return (((1 + _CPU_PAGE_WEIGHT_) * outers_per_page / NBuffers)					+ _CPU_PAGE_WEIGHT_					/ xfunc_card_product(get_relids(innerrel)));	}	else if (IsA(joinnode, MergePath))	{		/* assumes sort exists, and costs one (I/O + CPU) per tuple */		if (whichchild == INNER)			return ((2 * _CPU_PAGE_WEIGHT_ + 1)					/ xfunc_card_product(get_relids(outerrel)));		else			return ((2 * _CPU_PAGE_WEIGHT_ + 1)					/ xfunc_card_product(get_relids(innerrel)));	}	else/* nestloop */	{		Assert(IsA(joinnode, JoinPath));		return _CPU_PAGE_WEIGHT_;	}}/* ** xfunc_fixvars ** After pulling up a clause, we must walk its expression tree, fixing Var ** nodes to point to the correct varno (either INNER or OUTER, depending ** on which child the clause was pulled from), and the right varattno in the ** target list of the child's former relation.  If the target list of the ** child RelOptInfo does not contain the attribute we need, we add it. */voidxfunc_fixvars(LispValue clause, /* clause being pulled up */			  RelOptInfo rel,	/* rel it's being pulled from */			  int varno)		/* whether rel is INNER or OUTER of join */{	LispValue	tmpclause;		/* temporary variable */	TargetEntry *tle;			/* tlist member corresponding to var */	if (IsA(clause, Const) ||IsA(clause, Param))		return;	else if (IsA(clause, Var))	{		/* here's the meat */		tle = tlistentry_member((Var) clause, get_targetlist(rel));		if (tle == LispNil)		{			/*			 * * The attribute we need is not in the target list, * so we			 * have to add it. *			 *			 */			add_var_to_tlist(rel, (Var) clause);			tle = tlistentry_member((Var) clause, get_targetlist(rel));		}		set_varno(((Var) clause), varno);		set_varattno(((Var) clause), get_resno(get_resdom(get_entry(tle))));	}	else if (IsA(clause, Iter))		xfunc_fixvars(get_iterexpr((Iter) clause), rel, varno);	else if (fast_is_clause(clause))	{		xfunc_fixvars(lfirst(lnext(clause)), rel, varno);		xfunc_fixvars(lfirst(lnext(lnext(clause))), rel, varno);	}	else if (fast_is_funcclause(clause))		for (tmpclause = lnext(clause); tmpclause != LispNil;			 tmpclause = lnext(tmpclause))			xfunc_fixvars(lfirst(tmpclause), rel, varno);	else if (fast_not_clause(clause))		xfunc_fixvars(lsecond(clause), rel, varno);	else if (fast_or_clause(clause) || fast_and_clause(clause))		for (tmpclause = lnext(clause); tmpclause != LispNil;			 tmpclause = lnext(tmpclause))			xfunc_fixvars(lfirst(tmpclause), rel, varno);	else		elog(ERROR, "Clause node of undetermined type");}/* ** Comparison function for lisp_qsort() on a list of RestrictInfo's. ** arg1 and arg2 should really be of type (RestrictInfo *). */intxfunc_cinfo_compare(void *arg1, void *arg2){	RestrictInfo info1 = *(RestrictInfo *) arg1;	RestrictInfo info2 = *(RestrictInfo *) arg2;	LispValue	clause1 = (LispValue) get_clause(info1),				clause2 = (LispValue) get_clause(info2);	return xfunc_clause_compare((void *) &clause1, (void *) &clause2);}/* ** xfunc_clause_compare: comparison function for lisp_qsort() that compares two ** clauses based on expense/(1 - selectivity) ** arg1 and arg2 are really pointers to clauses. */intxfunc_clause_compare(void *arg1, void *arg2){	LispValue	clause1 = *(LispValue *) arg1;	LispValue	clause2 = *(LispValue *) arg2;	Cost		rank1,			/* total xfunc rank of clause1 */				rank2;			/* total xfunc rank of clause2 */	rank1 = xfunc_rank(clause1);	rank2 = xfunc_rank(clause2);	if (rank1 < rank2)		return -1;	else if (rank1 == rank2)		return 0;	else		return 1;}/* ** xfunc_disjunct_sort **   given a list of clauses, for each clause sort the disjuncts by cost **   (this assumes the predicates have been converted to Conjunctive NF) **   Modifies the clause list! */voidxfunc_disjunct_sort(LispValue clause_list){	LispValue	temp;	foreach(temp, clause_list)		if (or_clause(lfirst(temp)))		lnext(lfirst(temp)) = lisp_qsort(lnext(lfirst(temp)), xfunc_disjunct_compare);}/* ** xfunc_disjunct_compare: comparison function for qsort() that compares two ** disjuncts based on cost/selec. ** arg1 and arg2 are really pointers to disjuncts */intxfunc_disjunct_compare(Query *queryInfo, void *arg1, void *arg2){	LispValue	disjunct1 = *(LispValue *) arg1;	LispValue	disjunct2 = *(LispValue *) arg2;	Cost		cost1,			/* total cost of disjunct1 */				cost2,			/* total cost of disjunct2 */				selec1,				selec2;	Cost		rank1,				rank2;	cost1 = xfunc_expense(queryInfo, disjunct1);	cost2 = xfunc_expense(queryInfo, disjunct2);	selec1 = compute_clause_selec(queryInfo,								  disjunct1, LispNil);	selec2 = compute_clause_selec(queryInfo,								  disjunct2, LispNil);	if (selec1 == 0)		rank1 = MAXFLOAT;	else if (cost1 == 0)		rank1 = 0;	else		rank1 = cost1 / selec1;	if (selec2 == 0)		rank2 = MAXFLOAT;	else if (cost2 == 0)		rank2 = 0;	else		rank2 = cost2 / selec2;	if (rank1 < rank2)		return -1;	else if (rank1 == rank2)		return 0;	else		return 1;}/* ------------------------ UTILITY FUNCTIONS ------------------------------- *//* ** xfunc_func_width **    Given a function OID and operands, find the width of the return value. */intxfunc_func_width(RegProcedure funcid, LispValue args){	Relation	rd;				/* Relation Descriptor */	HeapTuple	tupl;			/* structure to hold a cached tuple */	Form_pg_proc proc;			/* structure to hold the pg_proc tuple */	Form_pg_type type;			/* structure to hold the pg_type tuple */	LispValue	tmpclause;	int			retval;	/* lookup function and find its return type */	Assert(RegProcedureIsValid(funcid));	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 function returns a tuple, get the width of that */	if (typeidTypeRelids(proc->prorettype))	{		rd = heap_open(typeidTypeRelids(proc->prorettype));		retval = xfunc_tuple_width(rd);		heap_close(rd);		goto exit;	}	else/* function returns a base type */	{		tupl = SearchSysCacheTuple(TYPOID,								   ObjectIdGetDatum(proc->prorettype),								   0, 0, 0);		if (!HeapTupleIsValid(tupl))			elog(ERROR, "Cache lookup failed for type %u", proc->prorettype);		type = (Form_pg_type) GETSTRUCT(tupl);		/* if the type length is known, return that */		if (type->typlen != -1)		{			retval = type->typlen;			goto exit;		}		else/* estimate the return size */		{			/* find width of the function's arguments */			for (tmpclause = args; tmpclause != LispNil;				 tmpclause = lnext(tmpclause))				retval += xfunc_width(lfirst(tmpclause));			/* multiply by outin_ratio */			retval = (int) (proc->prooutin_ratio / 100.0 * retval);			goto exit;		}	}exit:	return retval;}/* ** xfunc_tuple_width **		Return the sum of the lengths of all the attributes of a given relation */intxfunc_tuple_width(Relation rd){	int			i;	int			retval = 0;	TupleDesc	tdesc = RelationGetDescr(rd);	for (i = 0; i < tdesc->natts; i++)	{		if (tdesc->attrs[i]->attlen != -1)			retval += tdesc->attrs[i]->attlen;		else			retval += VARLEN_DEFAULT;	}	return retval;}/* ** xfunc_num_join_clauses **   Find the number of join clauses associated with this join path */intxfunc_num_join_clauses(JoinPath path){	int			num = length(get_pathrestrictinfo(path));	if (IsA(path, MergePath))		return num + length(get_path_mergeclauses((MergePath) path));	else if (IsA(path, HashPath))		return num + length(get_path_hashclauses((HashPath) path));	else		return num;}/* ** xfunc_LispRemove **   Just like LispRemove, but it whines if the item to be removed ain't there */LispValuexfunc_LispRemove(LispValue foo, List bar){	LispValue	temp = LispNil;	LispValue	result = LispNil;	int			sanity = false;	for (temp = bar; !null(temp); temp = lnext(temp))		if (!equal((Node) (foo), (Node) (lfirst(temp))))			result = lappend(result, lfirst(temp));		else			sanity = true;		/* found a matching item to remove! */	if (!sanity)		elog(ERROR, "xfunc_LispRemove: didn't find a match!");	return result;}#define Node_Copy(a, b, c, d) \do { \	if (NodeCopy((Node)((a)->d), (Node*)&((b)->d), c) != true) \	{ \		return false; \	} \} while(0)/* ** xfunc_copyrel **   Just like _copyRel, but doesn't copy the paths */boolxfunc_copyrel(RelOptInfo from, RelOptInfo *to){	RelOptInfo	newnode;	Pointer		(*alloc) () = palloc;	/* COPY_CHECKARGS() */	if (to == NULL)		return false;	/* COPY_CHECKNULL() */	if (from == NULL)	{		(*to) = NULL;		return true;	}	/* COPY_NEW(c) */	newnode = (RelOptInfo) (*alloc) (classSize(RelOptInfo));	if (newnode == NULL)		return false;	/* ----------------	 *	copy node superclass fields	 * ----------------	 */	CopyNodeFields((Node) from, (Node) newnode, alloc);	/* ----------------	 *	copy remainder of node	 * ----------------	 */	Node_Copy(from, newnode, alloc, relids);	newnode->indexed = from->indexed;	newnode->pages = from->pages;	newnode->tuples = from->tuples;	newnode->size = from->size;	newnode->width = from->width;	Node_Copy(from, newnode, alloc, targetlist);	/*	 * No!!!!	 Node_Copy(from, newnode, alloc, pathlist);	 * Node_Copy(from, newnode, alloc, unorderedpath); Node_Copy(from,	 * newnode, alloc, cheapestpath);	 */#if 0							/* can't use Node_copy now. 2/95 -ay */	Node_Copy(from, newnode, alloc, classlist);	Node_Copy(from, newnode, alloc, indexkeys);	Node_Copy(from, newnode, alloc, ordering);#endif	Node_Copy(from, newnode, alloc, restrictinfo);	Node_Copy(from, newnode, alloc, joininfo);	Node_Copy(from, newnode, alloc, innerjoin);	(*to) = newnode;	return true;}

⌨️ 快捷键说明

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