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

📄 selfuncs.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * selfuncs.c *	  Selectivity functions for system catalogs and builtin types * *	  These routines are registered in the operator catalog in the *	  "oprrest" and "oprjoin" attributes. * *	  XXX check all the functions--I suspect them to be 1-based. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.30.2.1 1999/08/02 05:24:57 scrappy Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/heapam.h"#include "catalog/catname.h"#include "catalog/pg_statistic.h"#include "utils/builtins.h"#include "utils/lsyscache.h"#include "utils/syscache.h"/* N is not a valid var/constant or relation id */#define NONVALUE(N)		((N) == -1)/* * generalize the test for functional index selectivity request */#define FunctionalSelectivity(nIndKeys,attNum) (attNum==InvalidAttrNumber)static float32data getattdisbursion(Oid relid, AttrNumber attnum);static void gethilokey(Oid relid, AttrNumber attnum, Oid opid,		   char **high, char **low);/* *		eqsel			- Selectivity of "=" for any data type. */float64eqsel(Oid opid,	  Oid relid,	  AttrNumber attno,	  char *value,	  int32 flag){	float64		result;	result = (float64) palloc(sizeof(float64data));	if (NONVALUE(attno) || NONVALUE(relid))		*result = 0.1;	else		*result = (float64data) getattdisbursion(relid, (int) attno);	return result;}/* *		neqsel			- Selectivity of "!=" for any data type. */float64neqsel(Oid opid,	   Oid relid,	   AttrNumber attno,	   char *value,	   int32 flag){	float64		result;	result = eqsel(opid, relid, attno, value, flag);	*result = 1.0 - *result;	return result;}/* *		intltsel		- Selectivity of "<" for integers. *						  Should work for both longs and shorts. */float64intltsel(Oid opid,		 Oid relid,		 AttrNumber attno,		 int32 value,		 int32 flag){	float64		result;	char	   *highchar,			   *lowchar;	long		val,				high,				low,				top,				bottom;	result = (float64) palloc(sizeof(float64data));	if (NONVALUE(attno) || NONVALUE(relid))		*result = 1.0 / 3;	else	{		/* XXX			val = atol(value); */		val = value;		gethilokey(relid, (int) attno, opid, &highchar, &lowchar);		if (*highchar == 'n' || *lowchar == 'n')		{			*result = 1.0 / 3.0;			return result;		}		high = atol(highchar);		low = atol(lowchar);		if ((flag & SEL_RIGHT && val < low) ||			(!(flag & SEL_RIGHT) && val > high))		{			float32data nvals;			nvals = getattdisbursion(relid, (int) attno);			if (nvals == 0)				*result = 1.0 / 3.0;			else			{				*result = 3.0 * (float64data) nvals;				if (*result > 1.0)					*result = 1;			}		}		else		{			bottom = high - low;			if (bottom == 0)				++bottom;			if (flag & SEL_RIGHT)				top = val - low;			else				top = high - val;			if (top > bottom)				*result = 1.0;			else			{				if (top == 0)					++top;				*result = ((1.0 * top) / bottom);			}		}	}	return result;}/* *		intgtsel		- Selectivity of ">" for integers. *						  Should work for both longs and shorts. */float64intgtsel(Oid opid,		 Oid relid,		 AttrNumber attno,		 int32 value,		 int32 flag){	float64		result;	int			notflag;	if (flag & 0)		notflag = flag & ~SEL_RIGHT;	else		notflag = flag | SEL_RIGHT;	result = intltsel(opid, relid, attno, value, (int32) notflag);	return result;}/* *		eqjoinsel		- Join selectivity of "=" */float64eqjoinsel(Oid opid,		  Oid relid1,		  AttrNumber attno1,		  Oid relid2,		  AttrNumber attno2){	float64		result;	float32data num1,				num2,				max;	result = (float64) palloc(sizeof(float64data));	if (NONVALUE(attno1) || NONVALUE(relid1) ||		NONVALUE(attno2) || NONVALUE(relid2))		*result = 0.1;	else	{		num1 = getattdisbursion(relid1, (int) attno1);		num2 = getattdisbursion(relid2, (int) attno2);		max = (num1 > num2) ? num1 : num2;		if (max == 0)			*result = 1.0;		else			*result = (float64data) max;	}	return result;}/* *		neqjoinsel		- Join selectivity of "!=" */float64neqjoinsel(Oid opid,		   Oid relid1,		   AttrNumber attno1,		   Oid relid2,		   AttrNumber attno2){	float64		result;	result = eqjoinsel(opid, relid1, attno1, relid2, attno2);	*result = 1.0 - *result;	return result;}/* *		intltjoinsel	- Join selectivity of "<" */float64intltjoinsel(Oid opid,			 Oid relid1,			 AttrNumber attno1,			 Oid relid2,			 AttrNumber attno2){	float64		result;	result = (float64) palloc(sizeof(float64data));	*result = 1.0 / 3.0;	return result;}/* *		intgtjoinsel	- Join selectivity of ">" */float64intgtjoinsel(Oid opid,			 Oid relid1,			 AttrNumber attno1,			 Oid relid2,			 AttrNumber attno2){	float64		result;	result = (float64) palloc(sizeof(float64data));	*result = 1.0 / 3.0;	return result;}/* *		getattdisbursion		- Retrieves the number of values within an attribute. * *		Note: *				getattdisbursion and gethilokey both currently use keyed *				relation scans and amgetattr.  Alternatively, *				the relation scan could be non-keyed and the tuple *				returned could be cast (struct X *) tuple + tuple->t_hoff. *				The first method is good for testing the implementation, *				but the second may ultimately be faster?!?	In any case, *				using the cast instead of amgetattr would be *				more efficient.  However, the cast will not work *				for gethilokey which accesses stahikey in struct statistic. */static float32datagetattdisbursion(Oid relid, AttrNumber attnum){	HeapTuple	atp;	float32data nvals;	int32		ntuples;	atp = SearchSysCacheTuple(ATTNUM,							  ObjectIdGetDatum(relid),							  Int16GetDatum(attnum),							  0, 0);	if (!HeapTupleIsValid(atp))	{		elog(ERROR, "getattdisbursion: no attribute tuple %u %d",			 relid, attnum);		return 0;	}	nvals = ((Form_pg_attribute) GETSTRUCT(atp))->attdisbursion;	if (nvals > 0)		return nvals;	atp = SearchSysCacheTuple(RELOID,							  ObjectIdGetDatum(relid),							  0, 0, 0);	/*	 * XXX -- use number of tuples as number of distinctive values just	 * for now, in case number of distinctive values is not cached	 */	if (!HeapTupleIsValid(atp))	{		elog(ERROR, "getattdisbursion: no relation tuple %u", relid);		return 0;	}	ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples;	/* Look above how nvals is used.	- vadim 04/09/97 */	if (ntuples > 0)		nvals = 1.0 / ntuples;	return nvals;}/* *		gethilokey		- Returns a pointer to strings containing *						  the high and low keys within an attribute. * *		Currently returns "0", and "0" in high and low if the statistic *		catalog does not contain the proper tuple.	Eventually, the *		statistic demon should have the tuple maintained, and it should *		elog() if the tuple is missing. * *		XXX Question: is this worth sticking in the catalog caches, *			or will this get invalidated too often? */static voidgethilokey(Oid relid,		   AttrNumber attnum,		   Oid opid,		   char **high,		   char **low){	Relation	rel;	HeapScanDesc scan;	static ScanKeyData key[3] = {		{0, Anum_pg_statistic_starelid, F_OIDEQ, {0, 0, F_OIDEQ}},		{0, Anum_pg_statistic_staattnum, F_INT2EQ, {0, 0, F_INT2EQ}},		{0, Anum_pg_statistic_staop, F_OIDEQ, {0, 0, F_OIDEQ}}	};	bool		isnull;	HeapTuple	tuple;	rel = heap_openr(StatisticRelationName);	key[0].sk_argument = ObjectIdGetDatum(relid);	key[1].sk_argument = Int16GetDatum((int16) attnum);	key[2].sk_argument = ObjectIdGetDatum(opid);	scan = heap_beginscan(rel, 0, SnapshotNow, 3, key);	tuple = heap_getnext(scan, 0);	if (!HeapTupleIsValid(tuple))	{		*high = "n";		*low = "n";		/*		 * XXX			elog(ERROR, "gethilokey: statistic tuple not		 * found");		 */		return;	}	*high = textout((struct varlena *)					heap_getattr(tuple,								 Anum_pg_statistic_stahikey,								 RelationGetDescr(rel),

⌨️ 快捷键说明

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