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

📄 indxpath.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
		{			if (index->indexkeys[i] == 0)			{				if (indexpr_item == NULL)					elog(ERROR, "wrong number of index expressions");				indexpr_item = lnext(indexpr_item);			}		}		if (indexpr_item == NULL)			elog(ERROR, "wrong number of index expressions");		indexkey = (Node *) lfirst(indexpr_item);		/*		 * Does it match the operand?  Again, strip any relabeling.		 */		if (indexkey && IsA(indexkey, RelabelType))			indexkey = (Node *) ((RelabelType *) indexkey)->arg;		if (equal(indexkey, operand))			return true;	}	return false;}/**************************************************************************** *			----  ROUTINES FOR "SPECIAL" INDEXABLE OPERATORS  ---- ****************************************************************************//*---------- * These routines handle special optimization of operators that can be * used with index scans even though they are not known to the executor's * indexscan machinery.  The key idea is that these operators allow us * to derive approximate indexscan qual clauses, such that any tuples * that pass the operator clause itself must also satisfy the simpler * indexscan condition(s).	Then we can use the indexscan machinery * to avoid scanning as much of the table as we'd otherwise have to, * while applying the original operator as a qpqual condition to ensure * we deliver only the tuples we want.	(In essence, we're using a regular * index as if it were a lossy index.) * * An example of what we're doing is *			textfield LIKE 'abc%' * from which we can generate the indexscanable conditions *			textfield >= 'abc' AND textfield < 'abd' * which allow efficient scanning of an index on textfield. * (In reality, character set and collation issues make the transformation * from LIKE to indexscan limits rather harder than one might think ... * but that's the basic idea.) * * Another thing that we do with this machinery is to provide special * smarts for "boolean" indexes (that is, indexes on boolean columns * that support boolean equality).	We can transform a plain reference * to the indexkey into "indexkey = true", or "NOT indexkey" into * "indexkey = false", so as to make the expression indexable using the * regular index operators.  (As of Postgres 8.1, we must do this here * because constant simplification does the reverse transformation; * without this code there'd be no way to use such an index at all.) * * Three routines are provided here: * * match_special_index_operator() is just an auxiliary function for * match_clause_to_indexcol(); after the latter fails to recognize a * restriction opclause's operator as a member of an index's opclass, * it asks match_special_index_operator() whether the clause should be * considered an indexqual anyway. * * match_boolean_index_clause() similarly detects clauses that can be * converted into boolean equality operators. * * expand_indexqual_conditions() converts a list of lists of RestrictInfo * nodes (with implicit AND semantics across list elements) into * a list of clauses that the executor can actually handle.  For operators * that are members of the index's opclass this transformation is a no-op, * but clauses recognized by match_special_index_operator() or * match_boolean_index_clause() must be converted into one or more "regular" * indexqual conditions. *---------- *//* * match_boolean_index_clause *	  Recognize restriction clauses that can be matched to a boolean index. * * This should be called only when IsBooleanOpclass() recognizes the * index's operator class.  We check to see if the clause matches the * index's key. */static boolmatch_boolean_index_clause(Node *clause,						   int indexcol,						   IndexOptInfo *index){	/* Direct match? */	if (match_index_to_operand(clause, indexcol, index))		return true;	/* NOT clause? */	if (not_clause(clause))	{		if (match_index_to_operand((Node *) get_notclausearg((Expr *) clause),								   indexcol, index))			return true;	}	/*	 * Since we only consider clauses at top level of WHERE, we can convert	 * indexkey IS TRUE and indexkey IS FALSE to index searches as well. The	 * different meaning for NULL isn't important.	 */	else if (clause && IsA(clause, BooleanTest))	{		BooleanTest *btest = (BooleanTest *) clause;		if (btest->booltesttype == IS_TRUE ||			btest->booltesttype == IS_FALSE)			if (match_index_to_operand((Node *) btest->arg,									   indexcol, index))				return true;	}	return false;}/* * match_special_index_operator *	  Recognize restriction clauses that can be used to generate *	  additional indexscanable qualifications. * * The given clause is already known to be a binary opclause having * the form (indexkey OP pseudoconst) or (pseudoconst OP indexkey), * but the OP proved not to be one of the index's opclass operators. * Return 'true' if we can do something with it anyway. */static boolmatch_special_index_operator(Expr *clause, Oid opclass,							 bool indexkey_on_left){	bool		isIndexable = false;	Node	   *rightop;	Oid			expr_op;	Const	   *patt;	Const	   *prefix = NULL;	Const	   *rest = NULL;	/*	 * Currently, all known special operators require the indexkey on the	 * left, but this test could be pushed into the switch statement if some	 * are added that do not...	 */	if (!indexkey_on_left)		return false;	/* we know these will succeed */	rightop = get_rightop(clause);	expr_op = ((OpExpr *) clause)->opno;	/* again, required for all current special ops: */	if (!IsA(rightop, Const) ||		((Const *) rightop)->constisnull)		return false;	patt = (Const *) rightop;	switch (expr_op)	{		case OID_TEXT_LIKE_OP:		case OID_BPCHAR_LIKE_OP:		case OID_NAME_LIKE_OP:			/* the right-hand const is type text for all of these */			isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Like,									  &prefix, &rest) != Pattern_Prefix_None;			break;		case OID_BYTEA_LIKE_OP:			isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Like,									  &prefix, &rest) != Pattern_Prefix_None;			break;		case OID_TEXT_ICLIKE_OP:		case OID_BPCHAR_ICLIKE_OP:		case OID_NAME_ICLIKE_OP:			/* the right-hand const is type text for all of these */			isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Like_IC,									  &prefix, &rest) != Pattern_Prefix_None;			break;		case OID_TEXT_REGEXEQ_OP:		case OID_BPCHAR_REGEXEQ_OP:		case OID_NAME_REGEXEQ_OP:			/* the right-hand const is type text for all of these */			isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Regex,									  &prefix, &rest) != Pattern_Prefix_None;			break;		case OID_TEXT_ICREGEXEQ_OP:		case OID_BPCHAR_ICREGEXEQ_OP:		case OID_NAME_ICREGEXEQ_OP:			/* the right-hand const is type text for all of these */			isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Regex_IC,									  &prefix, &rest) != Pattern_Prefix_None;			break;		case OID_INET_SUB_OP:		case OID_INET_SUBEQ_OP:		case OID_CIDR_SUB_OP:		case OID_CIDR_SUBEQ_OP:			isIndexable = true;			break;	}	if (prefix)	{		pfree(DatumGetPointer(prefix->constvalue));		pfree(prefix);	}	/* done if the expression doesn't look indexable */	if (!isIndexable)		return false;	/*	 * Must also check that index's opclass supports the operators we will	 * want to apply.  (A hash index, for example, will not support ">=".)	 * Currently, only btree supports the operators we need.	 *	 * We insist on the opclass being the specific one we expect, else we'd do	 * the wrong thing if someone were to make a reverse-sort opclass with the	 * same operators.	 */	switch (expr_op)	{		case OID_TEXT_LIKE_OP:		case OID_TEXT_ICLIKE_OP:		case OID_TEXT_REGEXEQ_OP:		case OID_TEXT_ICREGEXEQ_OP:			/* text operators will be used for varchar inputs, too */			isIndexable =				(opclass == TEXT_PATTERN_BTREE_OPS_OID) ||				(opclass == TEXT_BTREE_OPS_OID && lc_collate_is_c()) ||				(opclass == VARCHAR_PATTERN_BTREE_OPS_OID) ||				(opclass == VARCHAR_BTREE_OPS_OID && lc_collate_is_c());			break;		case OID_BPCHAR_LIKE_OP:		case OID_BPCHAR_ICLIKE_OP:		case OID_BPCHAR_REGEXEQ_OP:		case OID_BPCHAR_ICREGEXEQ_OP:			isIndexable =				(opclass == BPCHAR_PATTERN_BTREE_OPS_OID) ||				(opclass == BPCHAR_BTREE_OPS_OID && lc_collate_is_c());			break;		case OID_NAME_LIKE_OP:		case OID_NAME_ICLIKE_OP:		case OID_NAME_REGEXEQ_OP:		case OID_NAME_ICREGEXEQ_OP:			isIndexable =				(opclass == NAME_PATTERN_BTREE_OPS_OID) ||				(opclass == NAME_BTREE_OPS_OID && lc_collate_is_c());			break;		case OID_BYTEA_LIKE_OP:			isIndexable = (opclass == BYTEA_BTREE_OPS_OID);			break;		case OID_INET_SUB_OP:		case OID_INET_SUBEQ_OP:			isIndexable = (opclass == INET_BTREE_OPS_OID);			break;		case OID_CIDR_SUB_OP:		case OID_CIDR_SUBEQ_OP:			isIndexable = (opclass == CIDR_BTREE_OPS_OID);			break;	}	return isIndexable;}/* * expand_indexqual_conditions *	  Given a list of sublists of RestrictInfo nodes, produce a flat list *	  of index qual clauses.  Standard qual clauses (those in the index's *	  opclass) are passed through unchanged.  Boolean clauses and "special" *	  index operators are expanded into clauses that the indexscan machinery *	  will know what to do with. * * The input list is ordered by index key, and so the output list is too. * (The latter is not depended on by any part of the core planner, I believe, * but parts of the executor require it, and so do the amcostestimate * functions.) */List *expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups){	List	   *resultquals = NIL;	ListCell   *clausegroup_item;	int			indexcol = 0;	Oid		   *classes = index->classlist;	if (clausegroups == NIL)		return NIL;	clausegroup_item = list_head(clausegroups);	do	{		Oid			curClass = classes[0];		ListCell   *l;		foreach(l, (List *) lfirst(clausegroup_item))		{			RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);			/* First check for boolean cases */			if (IsBooleanOpclass(curClass))			{				Expr	   *boolqual;				boolqual = expand_boolean_index_clause((Node *) rinfo->clause,													   indexcol,													   index);				if (boolqual)				{					resultquals = lappend(resultquals,										  make_restrictinfo(boolqual,															true,															false,															NULL));					continue;				}			}			resultquals = list_concat(resultquals,									  expand_indexqual_condition(rinfo,																 curClass));		}		clausegroup_item = lnext(clausegroup_item);		indexcol++;		classes++;	} while (clausegroup_item != NULL && !DoneMatchingIndexKeys(classes));	Assert(clausegroup_item == NULL);	/* else more groups than indexkeys */	return resultquals;}/* * expand_boolean_index_clause *	  Convert a clause recognized by match_boolean_index_clause into *	  a boolean equality operator clause. * * Returns NULL if the clause isn't a boolean index qual. */static Expr *expand_boolean_index_clause(Node *clause,							int indexcol,							IndexOptInfo *index){	/* Direct match? */	if (match_index_to_operand(clause, indexcol, index))	{		/* convert to indexkey = TRUE */		return make_opclause(BooleanEqualOperator, BOOLOID, false,							 (Expr *) clause,							 (Expr *) makeBoolConst(true, false));	}	/* NOT clause? */	if (not_clause(clause))	{		Node	   *arg = (Node *) get_notclausearg((Expr *) clause);		/* It must have matched the indexkey */		Assert(match_index_to_operand(arg, indexcol, index));		/* convert to indexkey = FALSE */		return make_opclause(BooleanEqualOperator, BOOLOID, false,							 (Expr *) arg,							 (Expr *) makeBoolConst(false, false));	}	if (clause && IsA(clause, BooleanTest))	{		BooleanTest *btest = (BooleanTest *) clause;		Node	   *arg = (Node *) btest->arg;		/* It must have matched the indexkey */		Assert(match_index_to_operand(arg, indexcol, index));		if (btest->booltesttype == IS_TRUE)		{			/* convert to indexkey = TRUE */			return make_opclause(BooleanEqualOperator, BOOLOID, false,								 (Expr *) arg,								 (Expr *) makeBoolConst(true, false));		}		if (btest->booltesttype == IS_FALSE)		{			/* convert to indexkey = FALSE */			return make_opclause(BooleanEqualOperator, BOOLOID, false,								 (Expr *) arg,								 (Expr *) makeBoolConst(false, false));		}		/* Oops */		Assert(false);	}	return NULL;}/* * expand_indexqual_condition --- expand a single indexqual condition *		(other than a boolean-qual case) * * The input is a single RestrictInfo, the output a list of RestrictInfos */static List *expand_indexqual_condition(RestrictInfo *rinfo, Oid opclass){	Expr	   *clause = rinfo->clause;	/* we know these will succeed */	Node	   *leftop = get_leftop(clause);	Node	   *righ

⌨️ 快捷键说明

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