selfuncs.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,384 行 · 第 1/5 页

C
2,384
字号
		 */		Oid			eqopr = get_opclass_member(opclass, BTEqualStrategyNumber);		List	   *eqargs;		if (eqopr == InvalidOid)			elog(ERROR, "no = operator for opclass %u", opclass);		eqargs = makeList2(var, prefix);		result = DatumGetFloat8(DirectFunctionCall4(eqsel,													PointerGetDatum(root),												 ObjectIdGetDatum(eqopr),												 PointerGetDatum(eqargs),											   Int32GetDatum(varRelid)));	}	else	{		/*		 * Not exact-match pattern.  We estimate selectivity of the fixed		 * prefix and remainder of pattern separately, then combine the		 * two.		 */		Selectivity prefixsel;		Selectivity restsel;		Selectivity selec;		if (pstatus == Pattern_Prefix_Partial)			prefixsel = prefix_selectivity(root, var, opclass, prefix);		else			prefixsel = 1.0;		restsel = pattern_selectivity(rest, ptype);		selec = prefixsel * restsel;		/* result should be in range, but make sure... */		CLAMP_PROBABILITY(selec);		result = selec;	}	if (prefix)	{		pfree(DatumGetPointer(prefix->constvalue));		pfree(prefix);	}	return result;}/* *		regexeqsel		- Selectivity of regular-expression pattern match. */Datumregexeqsel(PG_FUNCTION_ARGS){	PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex));}/* *		icregexeqsel	- Selectivity of case-insensitive regex match. */Datumicregexeqsel(PG_FUNCTION_ARGS){	PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex_IC));}/* *		likesel			- Selectivity of LIKE pattern match. */Datumlikesel(PG_FUNCTION_ARGS){	PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like));}/* *		iclikesel			- Selectivity of ILIKE pattern match. */Datumiclikesel(PG_FUNCTION_ARGS){	PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like_IC));}/* *		regexnesel		- Selectivity of regular-expression pattern non-match. */Datumregexnesel(PG_FUNCTION_ARGS){	double		result;	result = patternsel(fcinfo, Pattern_Type_Regex);	result = 1.0 - result;	PG_RETURN_FLOAT8(result);}/* *		icregexnesel	- Selectivity of case-insensitive regex non-match. */Datumicregexnesel(PG_FUNCTION_ARGS){	double		result;	result = patternsel(fcinfo, Pattern_Type_Regex_IC);	result = 1.0 - result;	PG_RETURN_FLOAT8(result);}/* *		nlikesel		- Selectivity of LIKE pattern non-match. */Datumnlikesel(PG_FUNCTION_ARGS){	double		result;	result = patternsel(fcinfo, Pattern_Type_Like);	result = 1.0 - result;	PG_RETURN_FLOAT8(result);}/* *		icnlikesel		- Selectivity of ILIKE pattern non-match. */Datumicnlikesel(PG_FUNCTION_ARGS){	double		result;	result = patternsel(fcinfo, Pattern_Type_Like_IC);	result = 1.0 - result;	PG_RETURN_FLOAT8(result);}/* *		booltestsel		- Selectivity of BooleanTest Node. */Selectivitybooltestsel(Query *root, BoolTestType booltesttype, Node *arg,			int varRelid, JoinType jointype){	Var		   *var;	Oid			relid;	HeapTuple	statsTuple;	Datum	   *values;	int			nvalues;	float4	   *numbers;	int			nnumbers;	double		selec;	/*	 * Ignore any binary-compatible relabeling (probably unnecessary, but	 * can't hurt)	 */	if (IsA(arg, RelabelType))		arg = (Node *) ((RelabelType *) arg)->arg;	if (IsA(arg, Var) &&		(varRelid == 0 || varRelid == ((Var *) arg)->varno))		var = (Var *) arg;	else	{		/*		 * If argument is not a Var, we can't get statistics for it, but		 * perhaps clause_selectivity can do something with it.  We ignore		 * the possibility of a NULL value when using clause_selectivity,		 * and just assume the value is either TRUE or FALSE.		 */		switch (booltesttype)		{			case IS_UNKNOWN:				selec = DEFAULT_UNK_SEL;				break;			case IS_NOT_UNKNOWN:				selec = DEFAULT_NOT_UNK_SEL;				break;			case IS_TRUE:			case IS_NOT_FALSE:				selec = (double) clause_selectivity(root, arg,													varRelid, jointype);				break;			case IS_FALSE:			case IS_NOT_TRUE:				selec = 1.0 - (double) clause_selectivity(root, arg,													 varRelid, jointype);				break;			default:				elog(ERROR, "unrecognized booltesttype: %d",					 (int) booltesttype);				selec = 0.0;	/* Keep compiler quiet */				break;		}		return (Selectivity) selec;	}	/* get stats for the attribute, if available */	relid = getrelid(var->varno, root->rtable);	if (relid == InvalidOid)		statsTuple = NULL;	else		statsTuple = SearchSysCache(STATRELATT,									ObjectIdGetDatum(relid),									Int16GetDatum(var->varattno),									0, 0);	if (HeapTupleIsValid(statsTuple))	{		Form_pg_statistic stats;		double		freq_null;		stats = (Form_pg_statistic) GETSTRUCT(statsTuple);		freq_null = stats->stanullfrac;		if (get_attstatsslot(statsTuple, var->vartype, var->vartypmod,							 STATISTIC_KIND_MCV, InvalidOid,							 &values, &nvalues,							 &numbers, &nnumbers)			&& nnumbers > 0)		{			double		freq_true;			double		freq_false;			/*			 * Get first MCV frequency and derive frequency for true.			 */			if (DatumGetBool(values[0]))				freq_true = numbers[0];			else				freq_true = 1.0 - numbers[0] - freq_null;			/*			 * Next derive freqency for false. Then use these as			 * appropriate to derive frequency for each case.			 */			freq_false = 1.0 - freq_true - freq_null;			switch (booltesttype)			{				case IS_UNKNOWN:					/* select only NULL values */					selec = freq_null;					break;				case IS_NOT_UNKNOWN:					/* select non-NULL values */					selec = 1.0 - freq_null;					break;				case IS_TRUE:					/* select only TRUE values */					selec = freq_true;					break;				case IS_NOT_TRUE:					/* select non-TRUE values */					selec = 1.0 - freq_true;					break;				case IS_FALSE:					/* select only FALSE values */					selec = freq_false;					break;				case IS_NOT_FALSE:					/* select non-FALSE values */					selec = 1.0 - freq_false;					break;				default:					elog(ERROR, "unrecognized booltesttype: %d",						 (int) booltesttype);					selec = 0.0;	/* Keep compiler quiet */					break;			}			free_attstatsslot(var->vartype, values, nvalues,							  numbers, nnumbers);		}		else		{			/*			 * No most-common-value info available. Still have null			 * fraction information, so use it for IS [NOT] UNKNOWN.			 * Otherwise adjust for null fraction and assume an even split			 * for boolean tests.			 */			switch (booltesttype)			{				case IS_UNKNOWN:					/*					 * Use freq_null directly.					 */					selec = freq_null;					break;				case IS_NOT_UNKNOWN:					/*					 * Select not unknown (not null) values. Calculate					 * from freq_null.					 */					selec = 1.0 - freq_null;					break;				case IS_TRUE:				case IS_NOT_TRUE:				case IS_FALSE:				case IS_NOT_FALSE:					selec = (1.0 - freq_null) / 2.0;					break;				default:					elog(ERROR, "unrecognized booltesttype: %d",						 (int) booltesttype);					selec = 0.0;	/* Keep compiler quiet */					break;			}		}		ReleaseSysCache(statsTuple);	}	else	{		/*		 * No VACUUM ANALYZE stats available, so use a default value.		 * (Note: not much point in recursing to clause_selectivity here.)		 */		switch (booltesttype)		{			case IS_UNKNOWN:				selec = DEFAULT_UNK_SEL;				break;			case IS_NOT_UNKNOWN:				selec = DEFAULT_NOT_UNK_SEL;				break;			case IS_TRUE:			case IS_NOT_TRUE:			case IS_FALSE:			case IS_NOT_FALSE:				selec = DEFAULT_BOOL_SEL;				break;			default:				elog(ERROR, "unrecognized booltesttype: %d",					 (int) booltesttype);				selec = 0.0;	/* Keep compiler quiet */				break;		}	}	/* result should be in range, but make sure... */	CLAMP_PROBABILITY(selec);	return (Selectivity) selec;}/* *		nulltestsel		- Selectivity of NullTest Node. */Selectivitynulltestsel(Query *root, NullTestType nulltesttype, Node *arg, int varRelid){	Var		   *var;	Oid			relid;	HeapTuple	statsTuple;	double		selec;	double		defselec;	double		freq_null;	switch (nulltesttype)	{		case IS_NULL:			defselec = DEFAULT_UNK_SEL;			break;		case IS_NOT_NULL:			defselec = DEFAULT_NOT_UNK_SEL;			break;		default:			elog(ERROR, "unrecognized nulltesttype: %d",				 (int) nulltesttype);			return (Selectivity) 0;		/* keep compiler quiet */	}	/*	 * Ignore any binary-compatible relabeling	 */	if (IsA(arg, RelabelType))		arg = (Node *) ((RelabelType *) arg)->arg;	if (IsA(arg, Var) &&		(varRelid == 0 || varRelid == ((Var *) arg)->varno))		var = (Var *) arg;	else	{		/* punt if non-Var argument */		return (Selectivity) defselec;	}	relid = getrelid(var->varno, root->rtable);	if (relid == InvalidOid)		return (Selectivity) defselec;	/* get stats for the attribute, if available */	statsTuple = SearchSysCache(STATRELATT,								ObjectIdGetDatum(relid),								Int16GetDatum(var->varattno),								0, 0);	if (HeapTupleIsValid(statsTuple))	{		Form_pg_statistic stats;		stats = (Form_pg_statistic) GETSTRUCT(statsTuple);		freq_null = stats->stanullfrac;		switch (nulltesttype)		{			case IS_NULL:				/*				 * Use freq_null directly.				 */				selec = freq_null;				break;			case IS_NOT_NULL:				/*				 * Select not unknown (not null) values. Calculate from				 * freq_null.				 */				selec = 1.0 - freq_null;				break;			default:				elog(ERROR, "unrecognized nulltesttype: %d",					 (int) nulltesttype);				return (Selectivity) 0; /* keep compiler quiet */		}		ReleaseSysCache(statsTuple);	}	else	{		/*		 * No VACUUM ANALYZE stats available, so make a guess		 */		selec = defselec;	}	/* result should be in range, but make sure... */	CLAMP_PROBABILITY(selec);	return (Selectivity) selec;}/* *		eqjoinsel		- Join selectivity of "=" */Datumeqjoinsel(PG_FUNCTION_ARGS){	Query	   *root = (Query *) PG_GETARG_POINTER(0);	Oid			operator = PG_GETARG_OID(1);	List	   *args = (List *) PG_GETARG_POINTER(2);	JoinType	jointype = (JoinType) PG_GETARG_INT16(3);	Var		   *var1;	Var		   *var2;	double		selec;	get_join_vars(args, &var1, &var2);	if (var1 == NULL && var2 == NULL)		selec = DEFAULT_EQ_SEL;	else	{		HeapTuple	statsTuple1 = NULL;		HeapTuple	statsTuple2 = NULL;		Form_pg_statistic stats1 = NULL;		Form_pg_statistic stats2 = NULL;		double		nd1 = DEFAULT_NUM_DISTINCT;		double		nd2 = DEFAULT_NUM_DISTINCT;		bool		have_mcvs1 = false;		Datum	   *values1 = NULL;		int			nvalues1 = 0;		float4	   *numbers1 = NULL;		int			nnumbers1 = 0;		bool		have_mcvs2 = false;		Datum	   *values2 = NULL;		int			nvalues2 = 0;

⌨️ 快捷键说明

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