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

📄 pathnode.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
	 * otherwise punt.	 */	if (sub_targetlist)	{		pathnode->rows = estimate_num_groups(root, sub_targetlist, rel->rows);		numCols = list_length(sub_targetlist);	}	else	{		pathnode->rows = rel->rows;		numCols = list_length(rel->reltargetlist);	}	/*	 * Estimate cost for sort+unique implementation	 */	cost_sort(&sort_path, root, NIL,			  subpath->total_cost,			  rel->rows,			  rel->width);	/*	 * 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.)  This should agree with make_unique.	 */	sort_path.total_cost += cpu_operator_cost * rel->rows * numCols;	/*	 * Is it safe to use a hashed implementation?  If so, estimate and compare	 * costs.  We only try this if we know the targetlist for sure (else we	 * can't be sure about the datatypes involved).	 */	pathnode->umethod = UNIQUE_PATH_SORT;	if (enable_hashagg && sub_targetlist && hash_safe_tlist(sub_targetlist))	{		/*		 * Estimate the overhead per hashtable entry at 64 bytes (same as in		 * planner.c).		 */		int			hashentrysize = rel->width + 64;		if (hashentrysize * pathnode->rows <= work_mem * 1024L)		{			cost_agg(&agg_path, root,					 AGG_HASHED, 0,					 numCols, pathnode->rows,					 subpath->startup_cost,					 subpath->total_cost,					 rel->rows);			if (agg_path.total_cost < sort_path.total_cost)				pathnode->umethod = UNIQUE_PATH_HASH;		}	}	if (pathnode->umethod == UNIQUE_PATH_HASH)	{		pathnode->path.startup_cost = agg_path.startup_cost;		pathnode->path.total_cost = agg_path.total_cost;	}	else	{		pathnode->path.startup_cost = sort_path.startup_cost;		pathnode->path.total_cost = sort_path.total_cost;	}	rel->cheapest_unique_path = (Path *) pathnode;	return pathnode;}/* * translate_sub_tlist - get subquery column numbers represented by tlist * * The given targetlist should contain only Vars referencing the given relid. * Extract their varattnos (ie, the column numbers of the subquery) and return * as an integer List. * * If any of the tlist items is not a simple Var, we cannot determine whether * the subquery's uniqueness condition (if any) matches ours, so punt and * return NIL. */static List *translate_sub_tlist(List *tlist, int relid){	List	   *result = NIL;	ListCell   *l;	foreach(l, tlist)	{		Var		   *var = (Var *) lfirst(l);		if (!var || !IsA(var, Var) ||			var->varno != relid)			return NIL;			/* punt */		result = lappend_int(result, var->varattno);	}	return result;}/* * query_is_distinct_for - does query never return duplicates of the *		specified columns? * * colnos is an integer list of output column numbers (resno's).  We are * interested in whether rows consisting of just these columns are certain * to be distinct. */static boolquery_is_distinct_for(Query *query, List *colnos){	ListCell   *l;	/*	 * DISTINCT (including DISTINCT ON) guarantees uniqueness if all the	 * columns in the DISTINCT clause appear in colnos.	 */	if (query->distinctClause)	{		foreach(l, query->distinctClause)		{			SortClause *scl = (SortClause *) lfirst(l);			TargetEntry *tle = get_sortgroupclause_tle(scl,													   query->targetList);			if (!list_member_int(colnos, tle->resno))				break;			/* exit early if no match */		}		if (l == NULL)			/* had matches for all? */			return true;	}	/*	 * Similarly, GROUP BY guarantees uniqueness if all the grouped columns	 * appear in colnos.	 */	if (query->groupClause)	{		foreach(l, query->groupClause)		{			GroupClause *grpcl = (GroupClause *) lfirst(l);			TargetEntry *tle = get_sortgroupclause_tle(grpcl,													   query->targetList);			if (!list_member_int(colnos, tle->resno))				break;			/* exit early if no match */		}		if (l == NULL)			/* had matches for all? */			return true;	}	else	{		/*		 * If we have no GROUP BY, but do have aggregates or HAVING, then the		 * result is at most one row so it's surely unique.		 */		if (query->hasAggs || query->havingQual)			return true;	}	/*	 * UNION, INTERSECT, EXCEPT guarantee uniqueness of the whole output row,	 * except with ALL	 */	if (query->setOperations)	{		SetOperationStmt *topop = (SetOperationStmt *) query->setOperations;		Assert(IsA(topop, SetOperationStmt));		Assert(topop->op != SETOP_NONE);		if (!topop->all)		{			/* We're good if all the nonjunk output columns are in colnos */			foreach(l, query->targetList)			{				TargetEntry *tle = (TargetEntry *) lfirst(l);				if (!tle->resjunk &&					!list_member_int(colnos, tle->resno))					break;		/* exit early if no match */			}			if (l == NULL)		/* had matches for all? */				return true;		}	}	/*	 * XXX Are there any other cases in which we can easily see the result	 * must be distinct?	 */	return false;}/* * hash_safe_tlist - can datatypes of given tlist be hashed? * * We assume hashed aggregation will work if the datatype's equality operator * is marked hashjoinable. * * XXX this probably should be somewhere else.	See also hash_safe_grouping * in plan/planner.c. */static boolhash_safe_tlist(List *tlist){	ListCell   *tl;	foreach(tl, tlist)	{		Node	   *expr = (Node *) lfirst(tl);		Operator	optup;		bool		oprcanhash;		optup = equality_oper(exprType(expr), true);		if (!optup)			return false;		oprcanhash = ((Form_pg_operator) GETSTRUCT(optup))->oprcanhash;		ReleaseSysCache(optup);		if (!oprcanhash)			return false;	}	return true;}/* * create_subqueryscan_path *	  Creates a path corresponding to a sequential scan of a subquery, *	  returning the pathnode. */Path *create_subqueryscan_path(RelOptInfo *rel, List *pathkeys){	Path	   *pathnode = makeNode(Path);	pathnode->pathtype = T_SubqueryScan;	pathnode->parent = rel;	pathnode->pathkeys = pathkeys;	cost_subqueryscan(pathnode, rel);	return pathnode;}/* * create_functionscan_path *	  Creates a path corresponding to a sequential scan of a function, *	  returning the pathnode. */Path *create_functionscan_path(PlannerInfo *root, RelOptInfo *rel){	Path	   *pathnode = makeNode(Path);	pathnode->pathtype = T_FunctionScan;	pathnode->parent = rel;	pathnode->pathkeys = NIL;	/* for now, assume unordered result */	cost_functionscan(pathnode, root, rel);	return pathnode;}/* * create_nestloop_path *	  Creates a pathnode corresponding to a nestloop join between two *	  relations. * * 'joinrel' is the join relation. * 'jointype' is the type of join required * 'outer_path' is the outer path * 'inner_path' is the inner path * 'restrict_clauses' are the RestrictInfo nodes to apply at the join * 'pathkeys' are the path keys of the new join path * * Returns the resulting path node. */NestPath *create_nestloop_path(PlannerInfo *root,					 RelOptInfo *joinrel,					 JoinType jointype,					 Path *outer_path,					 Path *inner_path,					 List *restrict_clauses,					 List *pathkeys){	NestPath   *pathnode = makeNode(NestPath);	pathnode->path.pathtype = T_NestLoop;	pathnode->path.parent = joinrel;	pathnode->jointype = jointype;	pathnode->outerjoinpath = outer_path;	pathnode->innerjoinpath = inner_path;	pathnode->joinrestrictinfo = restrict_clauses;	pathnode->path.pathkeys = pathkeys;	cost_nestloop(pathnode, root);	return pathnode;}/* * create_mergejoin_path *	  Creates a pathnode corresponding to a mergejoin join between *	  two relations * * 'joinrel' is the join relation * 'jointype' is the type of join required * 'outer_path' is the outer path * 'inner_path' is the inner path * 'restrict_clauses' are the RestrictInfo nodes to apply at the join * 'pathkeys' are the path keys of the new join path * 'mergeclauses' are the RestrictInfo nodes to use as merge clauses *		(this should be a subset of the restrict_clauses list) * 'outersortkeys' are the sort varkeys for the outer relation * 'innersortkeys' are the sort varkeys for the inner relation */MergePath *create_mergejoin_path(PlannerInfo *root,					  RelOptInfo *joinrel,					  JoinType jointype,					  Path *outer_path,					  Path *inner_path,					  List *restrict_clauses,					  List *pathkeys,					  List *mergeclauses,					  List *outersortkeys,					  List *innersortkeys){	MergePath  *pathnode = makeNode(MergePath);	/*	 * If the given paths are already well enough ordered, we can skip doing	 * an explicit sort.	 */	if (outersortkeys &&		pathkeys_contained_in(outersortkeys, outer_path->pathkeys))		outersortkeys = NIL;	if (innersortkeys &&		pathkeys_contained_in(innersortkeys, inner_path->pathkeys))		innersortkeys = NIL;	/*	 * If we are not sorting the inner path, we may need a materialize node to	 * ensure it can be marked/restored.  (Sort does support mark/restore, so	 * no materialize is needed in that case.)	 *	 * Since the inner side must be ordered, and only Sorts and IndexScans can	 * create order to begin with, you might think there's no problem --- but	 * you'd be wrong.  Nestloop and merge joins can *preserve* the order of	 * their inputs, so they can be selected as the input of a mergejoin, and	 * they don't support mark/restore at present.	 */	if (innersortkeys == NIL &&		!ExecSupportsMarkRestore(inner_path->pathtype))		inner_path = (Path *)			create_material_path(inner_path->parent, inner_path);	pathnode->jpath.path.pathtype = T_MergeJoin;	pathnode->jpath.path.parent = joinrel;	pathnode->jpath.jointype = jointype;	pathnode->jpath.outerjoinpath = outer_path;	pathnode->jpath.innerjoinpath = inner_path;	pathnode->jpath.joinrestrictinfo = restrict_clauses;	pathnode->jpath.path.pathkeys = pathkeys;	pathnode->path_mergeclauses = mergeclauses;	pathnode->outersortkeys = outersortkeys;	pathnode->innersortkeys = innersortkeys;	cost_mergejoin(pathnode, root);	return pathnode;}/* * create_hashjoin_path *	  Creates a pathnode corresponding to a hash join between two relations. * * 'joinrel' is the join relation * 'jointype' is the type of join required * 'outer_path' is the cheapest outer path * 'inner_path' is the cheapest inner path * 'restrict_clauses' are the RestrictInfo nodes to apply at the join * 'hashclauses' are the RestrictInfo nodes to use as hash clauses *		(this should be a subset of the restrict_clauses list) */HashPath *create_hashjoin_path(PlannerInfo *root,					 RelOptInfo *joinrel,					 JoinType jointype,					 Path *outer_path,					 Path *inner_path,					 List *restrict_clauses,					 List *hashclauses){	HashPath   *pathnode = makeNode(HashPath);	pathnode->jpath.path.pathtype = T_HashJoin;	pathnode->jpath.path.parent = joinrel;	pathnode->jpath.jointype = jointype;	pathnode->jpath.outerjoinpath = outer_path;	pathnode->jpath.innerjoinpath = inner_path;	pathnode->jpath.joinrestrictinfo = restrict_clauses;	/* A hashjoin never has pathkeys, since its ordering is unpredictable */	pathnode->jpath.path.pathkeys = NIL;	pathnode->path_hashclauses = hashclauses;	cost_hashjoin(pathnode, root);	return pathnode;}

⌨️ 快捷键说明

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