clausesel.c

来自「PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统」· C语言 代码 · 共 677 行 · 第 1/2 页

C
677
字号
	/* No matching var found, so make a new clause-pair data structure */	rqelem = (RangeQueryClause *) palloc(sizeof(RangeQueryClause));	rqelem->var = var;	if (is_lobound)	{		rqelem->have_lobound = true;		rqelem->have_hibound = false;		rqelem->lobound = s2;	}	else	{		rqelem->have_lobound = false;		rqelem->have_hibound = true;		rqelem->hibound = s2;	}	rqelem->next = *rqlist;	*rqlist = rqelem;}/* * bms_is_subset_singleton * * Same result as bms_is_subset(s, bms_make_singleton(x)), * but a little faster and doesn't leak memory. * * Is this of use anywhere else?  If so move to bitmapset.c ... */static boolbms_is_subset_singleton(const Bitmapset *s, int x){	switch (bms_membership(s))	{		case BMS_EMPTY_SET:			return true;		case BMS_SINGLETON:			return bms_is_member(x, s);		case BMS_MULTIPLE:			return false;	}	/* can't get here... */	return false;}/* * clause_selectivity - *	  Compute the selectivity of a general boolean expression clause. * * The clause can be either a RestrictInfo or a plain expression.  If it's * a RestrictInfo, we try to cache the selectivity for possible re-use, * so passing RestrictInfos is preferred. * * varRelid is either 0 or a rangetable index. * * When varRelid is not 0, only variables belonging to that relation are * considered in computing selectivity; other vars are treated as constants * of unknown values.  This is appropriate for estimating the selectivity of * a join clause that is being used as a restriction clause in a scan of a * nestloop join's inner relation --- varRelid should then be the ID of the * inner relation. * * When varRelid is 0, all variables are treated as variables.	This * is appropriate for ordinary join clauses and restriction clauses. * * jointype is the join type, if the clause is a join clause.  Pass JOIN_INNER * if the clause isn't a join clause or the context is uncertain. */Selectivityclause_selectivity(PlannerInfo *root,				   Node *clause,				   int varRelid,				   JoinType jointype){	Selectivity s1 = 1.0;		/* default for any unhandled clause type */	RestrictInfo *rinfo = NULL;	bool		cacheable = false;	if (clause == NULL)			/* can this still happen? */		return s1;	if (IsA(clause, RestrictInfo))	{		rinfo = (RestrictInfo *) clause;		/*		 * If possible, cache the result of the selectivity calculation for		 * the clause.	We can cache if varRelid is zero or the clause		 * contains only vars of that relid --- otherwise varRelid will affect		 * the result, so mustn't cache.  We also have to be careful about the		 * jointype.  It's OK to cache when jointype is JOIN_INNER or one of		 * the outer join types (any given outer-join clause should always be		 * examined with the same jointype, so result won't change). It's not		 * OK to cache when jointype is one of the special types associated		 * with IN processing, because the same clause may be examined with		 * different jointypes and the result should vary.		 */		if (varRelid == 0 ||			bms_is_subset_singleton(rinfo->clause_relids, varRelid))		{			switch (jointype)			{				case JOIN_INNER:				case JOIN_LEFT:				case JOIN_FULL:				case JOIN_RIGHT:					/* Cacheable --- do we already have the result? */					if (rinfo->this_selec >= 0)						return rinfo->this_selec;					cacheable = true;					break;				case JOIN_UNION:					/* unimplemented anyway... */				case JOIN_IN:				case JOIN_REVERSE_IN:				case JOIN_UNIQUE_OUTER:				case JOIN_UNIQUE_INNER:					/* unsafe to cache */					break;			}		}		/*		 * Proceed with examination of contained clause.  If the clause is an		 * OR-clause, we want to look at the variant with sub-RestrictInfos,		 * so that per-subclause selectivities can be cached.		 */		if (rinfo->orclause)			clause = (Node *) rinfo->orclause;		else			clause = (Node *) rinfo->clause;	}	if (IsA(clause, Var))	{		Var		   *var = (Var *) clause;		/*		 * We probably shouldn't ever see an uplevel Var here, but if we do,		 * return the default selectivity...		 */		if (var->varlevelsup == 0 &&			(varRelid == 0 || varRelid == (int) var->varno))		{			RangeTblEntry *rte = rt_fetch(var->varno, root->parse->rtable);			if (rte->rtekind == RTE_SUBQUERY)			{				/*				 * XXX not smart about subquery references... any way to do				 * better?				 */				s1 = 0.5;			}			else			{				/*				 * A Var at the top of a clause must be a bool Var. This is				 * equivalent to the clause reln.attribute = 't', so we				 * compute the selectivity as if that is what we have.				 */				s1 = restriction_selectivity(root,											 BooleanEqualOperator,											 list_make2(var,														makeBoolConst(true,																	  false)),											 varRelid);			}		}	}	else if (IsA(clause, Const))	{		/* bool constant is pretty easy... */		s1 = ((bool) ((Const *) clause)->constvalue) ? 1.0 : 0.0;	}	else if (IsA(clause, Param))	{		/* see if we can replace the Param */		Node	   *subst = estimate_expression_value(clause);		if (IsA(subst, Const))		{			/* bool constant is pretty easy... */			s1 = ((bool) ((Const *) subst)->constvalue) ? 1.0 : 0.0;		}		else		{			/* XXX any way to do better? */			s1 = (Selectivity) 0.5;		}	}	else if (not_clause(clause))	{		/* inverse of the selectivity of the underlying clause */		s1 = 1.0 - clause_selectivity(root,								  (Node *) get_notclausearg((Expr *) clause),									  varRelid,									  jointype);	}	else if (and_clause(clause))	{		/* share code with clauselist_selectivity() */		s1 = clauselist_selectivity(root,									((BoolExpr *) clause)->args,									varRelid,									jointype);	}	else if (or_clause(clause))	{		/*		 * Selectivities for an OR clause are computed as s1+s2 - s1*s2 to		 * account for the probable overlap of selected tuple sets.		 *		 * XXX is this too conservative?		 */		ListCell   *arg;		s1 = 0.0;		foreach(arg, ((BoolExpr *) clause)->args)		{			Selectivity s2 = clause_selectivity(root,												(Node *) lfirst(arg),												varRelid,												jointype);			s1 = s1 + s2 - s1 * s2;		}	}	else if (is_opclause(clause))	{		Oid			opno = ((OpExpr *) clause)->opno;		bool		is_join_clause;		if (varRelid != 0)		{			/*			 * If we are considering a nestloop join then all clauses are			 * restriction clauses, since we are only interested in the one			 * relation.			 */			is_join_clause = false;		}		else		{			/*			 * Otherwise, it's a join if there's more than one relation used.			 * We can optimize this calculation if an rinfo was passed.			 */			if (rinfo)				is_join_clause = (bms_membership(rinfo->clause_relids) ==								  BMS_MULTIPLE);			else				is_join_clause = (NumRelids(clause) > 1);		}		if (is_join_clause)		{			/* Estimate selectivity for a join clause. */			s1 = join_selectivity(root, opno,								  ((OpExpr *) clause)->args,								  jointype);		}		else		{			/* Estimate selectivity for a restriction clause. */			s1 = restriction_selectivity(root, opno,										 ((OpExpr *) clause)->args,										 varRelid);		}	}	else if (is_funcclause(clause))	{		/*		 * This is not an operator, so we guess at the selectivity. THIS IS A		 * HACK TO GET V4 OUT THE DOOR.  FUNCS SHOULD BE ABLE TO HAVE		 * SELECTIVITIES THEMSELVES.	   -- JMH 7/9/92		 */		s1 = (Selectivity) 0.3333333;	}	else if (is_subplan(clause))	{		/*		 * Just for the moment! FIX ME! - vadim 02/04/98		 */		s1 = (Selectivity) 0.5;	}	else if (IsA(clause, DistinctExpr) ||			 IsA(clause, ScalarArrayOpExpr))	{		/* can we do better? */		s1 = (Selectivity) 0.5;	}	else if (IsA(clause, NullTest))	{		/* Use node specific selectivity calculation function */		s1 = nulltestsel(root,						 ((NullTest *) clause)->nulltesttype,						 (Node *) ((NullTest *) clause)->arg,						 varRelid);	}	else if (IsA(clause, BooleanTest))	{		/* Use node specific selectivity calculation function */		s1 = booltestsel(root,						 ((BooleanTest *) clause)->booltesttype,						 (Node *) ((BooleanTest *) clause)->arg,						 varRelid,						 jointype);	}	else if (IsA(clause, RelabelType))	{		/* Not sure this case is needed, but it can't hurt */		s1 = clause_selectivity(root,								(Node *) ((RelabelType *) clause)->arg,								varRelid,								jointype);	}	else if (IsA(clause, CoerceToDomain))	{		/* Not sure this case is needed, but it can't hurt */		s1 = clause_selectivity(root,								(Node *) ((CoerceToDomain *) clause)->arg,								varRelid,								jointype);	}	/* Cache the result if possible */	if (cacheable)		rinfo->this_selec = s1;#ifdef SELECTIVITY_DEBUG	elog(DEBUG4, "clause_selectivity: s1 %f", s1);#endif   /* SELECTIVITY_DEBUG */	return s1;}

⌨️ 快捷键说明

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