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

📄 indxpath.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * promising combination of bitmap index paths.	 */	if (bitindexpaths != NIL)	{		Path	   *bitmapqual;		BitmapHeapPath *bpath;		bitmapqual = choose_bitmap_and(root, rel, bitindexpaths);		bpath = create_bitmap_heap_path(root, rel, bitmapqual, true);		indexpaths = lappend(indexpaths, bpath);	}	/*	 * Now choose the cheapest member of indexpaths.	 */	cheapest = NULL;	foreach(l, indexpaths)	{		Path	   *path = (Path *) lfirst(l);		if (cheapest == NULL ||			compare_path_costs(path, cheapest, TOTAL_COST) < 0)			cheapest = path;	}	/* Cache the result --- whether positive or negative */	info = makeNode(InnerIndexscanInfo);	info->other_relids = outer_relids;	info->isouterjoin = isouterjoin;	info->best_innerpath = cheapest;	rel->index_inner_paths = lcons(info, rel->index_inner_paths);	MemoryContextSwitchTo(oldcontext);	return cheapest;}/* * find_clauses_for_join *	  Generate a list of clauses that are potentially useful for *	  scanning rel as the inner side of a nestloop join. * * We consider both join and restriction clauses.  Any joinclause that uses * only otherrels in the specified outer_relids is fair game.  But there must * be at least one such joinclause in the final list, otherwise we return NIL * indicating that there isn't any potential win here. */static List *find_clauses_for_join(PlannerInfo *root, RelOptInfo *rel,					  Relids outer_relids, bool isouterjoin){	List	   *clause_list = NIL;	Relids		join_relids;	ListCell   *l;	/* Look for joinclauses that are usable with given outer_relids */	join_relids = bms_union(rel->relids, outer_relids);	foreach(l, rel->joininfo)	{		RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);		/* Can't use pushed-down join clauses in outer join */		if (isouterjoin && rinfo->is_pushed_down)			continue;		if (!bms_is_subset(rinfo->required_relids, join_relids))			continue;		clause_list = lappend(clause_list, rinfo);	}	bms_free(join_relids);	/* if no join clause was matched then forget it, per comments above */	if (clause_list == NIL)		return NIL;	/*	 * We can also use any plain restriction clauses for the rel.  We put	 * these at the front of the clause list for the convenience of	 * remove_redundant_join_clauses, which can never remove non-join clauses	 * and hence won't be able to get rid of a non-join clause if it appears	 * after a join clause it is redundant with.	 */	clause_list = list_concat(list_copy(rel->baserestrictinfo), clause_list);	/*	 * We may now have clauses that are known redundant.  Get rid of 'em.	 */	if (list_length(clause_list) > 1)	{		clause_list = remove_redundant_join_clauses(root,													clause_list,													isouterjoin);	}	return clause_list;}/**************************************************************************** *				----  ROUTINES TO HANDLE PATHKEYS  ---- ****************************************************************************//* * match_variant_ordering *		Try to match an index's ordering to the query's requested ordering * * This is used when the index is ordered but a naive comparison fails to * match its ordering (pathkeys) to root->query_pathkeys.  It may be that * we need to scan the index backwards.  Also, a less naive comparison can * help for both forward and backward indexscans.  Columns of the index * that have an equality restriction clause can be ignored in the match; * that is, an index on (x,y) can be considered to match the ordering of *		... WHERE x = 42 ORDER BY y; * * Note: it would be possible to similarly ignore useless ORDER BY items; * that is, an index on just y could be considered to match the ordering of *		... WHERE x = 42 ORDER BY x, y; * But proving that this is safe would require finding a btree opclass * containing both the = operator and the < or > operator in the ORDER BY * item.  That's significantly more expensive than what we do here, since * we'd have to look at restriction clauses unrelated to the current index * and search for opclasses without any hint from the index.  The practical * use-cases seem to be mostly covered by ignoring index columns, so that's * all we do for now. * * Inputs: * 'index' is the index of interest. * 'restrictclauses' is the list of sublists of restriction clauses *		matching the columns of the index (NIL if none) * * If able to match the requested query pathkeys, returns either * ForwardScanDirection or BackwardScanDirection to indicate the proper index * scan direction.	If no match, returns NoMovementScanDirection. */static ScanDirectionmatch_variant_ordering(PlannerInfo *root,					   IndexOptInfo *index,					   List *restrictclauses){	List	   *ignorables;	/*	 * Forget the whole thing if not a btree index; our check for ignorable	 * columns assumes we are dealing with btree opclasses.  (It'd be possible	 * to factor out just the try for backwards indexscan, but considering	 * that we presently have no orderable indexes except btrees anyway, it's	 * hardly worth contorting this code for that case.)	 *	 * Note: if you remove this, you probably need to put in a check on	 * amoptionalkey to prevent possible clauseless scan on an index that	 * won't cope.	 */	if (index->relam != BTREE_AM_OID)		return NoMovementScanDirection;	/*	 * Figure out which index columns can be optionally ignored because they	 * have an equality constraint.  This is the same set for either forward	 * or backward scan, so we do it just once.	 */	ignorables = identify_ignorable_ordering_cols(root, index,												  restrictclauses);	/*	 * Try to match to forward scan, then backward scan.  However, we can skip	 * the forward-scan case if there are no ignorable columns, because	 * find_usable_indexes() would have found the match already.	 */	if (ignorables &&		match_index_to_query_keys(root, index, ForwardScanDirection,								  ignorables))		return ForwardScanDirection;	if (match_index_to_query_keys(root, index, BackwardScanDirection,								  ignorables))		return BackwardScanDirection;	return NoMovementScanDirection;}/* * identify_ignorable_ordering_cols *		Determine which index columns can be ignored for ordering purposes * * Returns an integer List of column numbers (1-based) of ignorable * columns.  The ignorable columns are those that have equality constraints * against pseudoconstants. */static List *identify_ignorable_ordering_cols(PlannerInfo *root,								 IndexOptInfo *index,								 List *restrictclauses){	List	   *result = NIL;	int			indexcol = 0;	/* note this is 0-based */	ListCell   *l;	/* restrictclauses is either NIL or has a sublist per column */	foreach(l, restrictclauses)	{		List	   *sublist = (List *) lfirst(l);		Oid			opclass = index->classlist[indexcol];		ListCell   *l2;		foreach(l2, sublist)		{			RestrictInfo *rinfo = (RestrictInfo *) lfirst(l2);			OpExpr	   *clause = (OpExpr *) rinfo->clause;			Oid			clause_op;			int			op_strategy;			bool		varonleft;			bool		ispc;			/* We know this clause passed match_clause_to_indexcol */			/* First check for boolean-index cases. */			if (IsBooleanOpclass(opclass))			{				if (match_boolean_index_clause((Node *) clause, indexcol,											   index))				{					/*					 * The clause means either col = TRUE or col = FALSE; we					 * do not care which, it's an equality constraint either					 * way.					 */					result = lappend_int(result, indexcol + 1);					break;				}			}			/* Else clause must be a binary opclause. */			Assert(IsA(clause, OpExpr));			/* Determine left/right sides and check the operator */			clause_op = clause->opno;			if (match_index_to_operand(linitial(clause->args), indexcol,									   index))			{				/* clause_op is correct */				varonleft = true;			}			else			{				Assert(match_index_to_operand(lsecond(clause->args), indexcol,											  index));				/* Must flip operator to get the opclass member */				clause_op = get_commutator(clause_op);				varonleft = false;			}			if (!OidIsValid(clause_op))				continue;		/* ignore non match, per next comment */			op_strategy = get_op_opclass_strategy(clause_op, opclass);			/*			 * You might expect to see Assert(op_strategy != 0) here, but you			 * won't: the clause might contain a special indexable operator			 * rather than an ordinary opclass member.	Currently none of the			 * special operators are very likely to expand to an equality			 * operator; we do not bother to check, but just assume no match.			 */			if (op_strategy != BTEqualStrategyNumber)				continue;			/* Now check that other side is pseudoconstant */			if (varonleft)				ispc = is_pseudo_constant_clause_relids(lsecond(clause->args),														rinfo->right_relids);			else				ispc = is_pseudo_constant_clause_relids(linitial(clause->args),														rinfo->left_relids);			if (ispc)			{				result = lappend_int(result, indexcol + 1);				break;			}		}		indexcol++;	}	return result;}/* * match_index_to_query_keys *		Check a single scan direction for "intelligent" match to query keys * * 'index' is the index of interest. * 'indexscandir' is the scan direction to consider * 'ignorables' is an integer list of indexes of ignorable index columns * * Returns TRUE on successful match (ie, the query_pathkeys can be considered * to match this index). */static boolmatch_index_to_query_keys(PlannerInfo *root,						  IndexOptInfo *index,						  ScanDirection indexscandir,						  List *ignorables){	List	   *index_pathkeys;	ListCell   *index_cell;	int			index_col;	ListCell   *r;	/* Get the pathkeys that exactly describe the index */	index_pathkeys = build_index_pathkeys(root, index, indexscandir, false);	/*	 * Can we match to the query's requested pathkeys?  The inner loop skips	 * over ignorable index columns while trying to match.	 */	index_cell = list_head(index_pathkeys);	index_col = 0;	foreach(r, root->query_pathkeys)	{		List	   *rsubkey = (List *) lfirst(r);		for (;;)		{			List	   *isubkey;			if (index_cell == NULL)				return false;			isubkey = (List *) lfirst(index_cell);			index_cell = lnext(index_cell);			index_col++;		/* index_col is now 1-based */			/*			 * Since we are dealing with canonicalized pathkeys, pointer			 * comparison is sufficient to determine a match.			 */			if (rsubkey == isubkey)				break;			/* matched current query pathkey */			if (!list_member_int(ignorables, index_col))				return false;	/* definite failure to match */			/* otherwise loop around and try to match to next index col */		}	}	return true;}/**************************************************************************** *				----  PATH CREATION UTILITIES  ---- ****************************************************************************//* * flatten_clausegroups_list *	  Given a list of lists of RestrictInfos, flatten it to a list *	  of RestrictInfos. * * This is used to flatten out the result of group_clauses_by_indexkey() * to produce an indexclauses list.  The original list structure mustn't * be altered, but it's OK to share copies of the underlying RestrictInfos. */List *flatten_clausegroups_list(List *clausegroups){	List	   *allclauses = NIL;	ListCell   *l;	foreach(l, clausegroups)		allclauses = list_concat(allclauses, list_copy((List *) lfirst(l)));	return allclauses;}/**************************************************************************** *				----  ROUTINES TO CHECK OPERANDS  ---- ****************************************************************************//* * match_index_to_operand() *	  Generalized test for a match between an index's key *	  and the operand on one side of a restriction or join clause. * * operand: the nodetree to be compared to the index * indexcol: the column number of the index (counting from 0) * index: the index of interest */boolmatch_index_to_operand(Node *operand,					   int indexcol,					   IndexOptInfo *index){	int			indkey;	/*	 * Ignore any RelabelType node above the operand.	This is needed to be	 * able to apply indexscanning in binary-compatible-operator cases. Note:	 * we can assume there is at most one RelabelType node;	 * eval_const_expressions() will have simplified if more than one.	 */	if (operand && IsA(operand, RelabelType))		operand = (Node *) ((RelabelType *) operand)->arg;	indkey = index->indexkeys[indexcol];	if (indkey != 0)	{		/*		 * Simple index column; operand must be a matching Var.		 */		if (operand && IsA(operand, Var) &&			index->rel->relid == ((Var *) operand)->varno &&			indkey == ((Var *) operand)->varattno)			return true;	}	else	{		/*		 * Index expression; find the correct expression.  (This search could		 * be avoided, at the cost of complicating all the callers of this		 * routine; doesn't seem worth it.)		 */		ListCell   *indexpr_item;		int			i;		Node	   *indexkey;		indexpr_item = list_head(index->indexprs);		for (i = 0; i < indexcol; i++)

⌨️ 快捷键说明

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