head 1.19; access; symbols Version_2_1:1.16 Version_2:1.11 C_Demo_1:1.4; locks; strict; comment @ * @; 1.19 date 92.01.13.02.21.26; author mao; state Exp; branches; next 1.18; 1.18 date 91.11.09.01.53.04; author mer; state Exp; branches; next 1.17; 1.17 date 91.10.16.23.15.20; author mer; state Exp; branches; next 1.16; 1.16 date 91.02.24.09.03.53; author mao; state Exp; branches; next 1.15; 1.15 date 90.10.01.16.44.51; author hong; state Exp; branches; next 1.14; 1.14 date 90.09.21.17.12.19; author hong; state Exp; branches; next 1.13; 1.13 date 90.08.15.08.20.01; author cimarron; state Exp; branches; next 1.12; 1.12 date 90.08.08.08.36.24; author cimarron; state Exp; branches; next 1.11; 1.11 date 90.06.09.18.47.59; author kemnitz; state Version_2; branches; next 1.10; 1.10 date 90.06.07.18.21.06; author cimarron; state Exp; branches; next 1.9; 1.9 date 90.05.25.15.24.24; author mao; state Exp; branches; next 1.8; 1.8 date 89.11.16.14.22.22; author hong; state Exp; branches; next 1.7; 1.7 date 89.10.31.11.29.06; author hong; state Exp; branches; next 1.6; 1.6 date 89.10.25.21.50.07; author hong; state Exp; branches; next 1.5; 1.5 date 89.09.28.17.50.25; author hirohama; state Exp; branches; next 1.4; 1.4 date 89.09.05.17.26.39; author mao; state C_Demo_1; branches; next 1.3; 1.3 date 89.08.09.18.11.28; author cimarron; state Exp; branches; next 1.2; 1.2 date 89.02.02.16.11.40; author aoki; state Stab; branches; next 1.1; 1.1 date 89.01.17.05.58.44; author cimarron; state Exp; branches; next ; desc @@ 1.19 log @flatten include file graph @ text @/* * 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. */ #include #include #include "access/heapam.h" #include "access/tqual.h" /* for NowTimeQual */ #include "utils/fmgr.h" #include "utils/builtins.h" /* for textout() prototype */ #include "utils/log.h" #include "catalog/catname.h" #include "catalog/syscache.h" #include "catalog/pg_statistic.h" RcsId("$Header: RCS/selfuncs.c,v 1.18 91/11/09 01:53:04 mer Exp $"); /* 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==InvalidAttributeNumber) int32 getattnvals ARGS((ObjectId relid , AttributeNumber attnum )); int gethilokey ARGS((ObjectId relid , AttributeNumber attnum , ObjectId opid , char **high , char **low )); /* * eqsel - Selectivity of "=" for any data type. */ /*ARGSUSED*/ float64 eqsel(opid, relid, attno, value, flag) ObjectId opid; ObjectId relid; AttributeNumber attno; char *value; int32 flag; { int32 nvals; float64 result; result = (float64) palloc(sizeof(float64data)); if (NONVALUE(attno) || NONVALUE(relid)) *result = 0.1; else { nvals = getattnvals(relid, (int) attno); if (nvals == 0) *result = 0.0; else *result = 1.0 / nvals; } return(result); } /* * neqsel - Selectivity of "!=" for any data type. */ float64 neqsel(opid, relid, attno, value, flag) ObjectId opid; ObjectId relid; AttributeNumber 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. */ float64 intltsel(opid, relid, attno, value, flag) ObjectId opid; ObjectId relid; AttributeNumber attno; /* XXX char *value;*/ int32 value; int32 flag; { float64 result; char *highchar, *lowchar; long val, high, low, top, bottom; extern long atol(); 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)) { int nvals; nvals = getattnvals(relid, (int) attno); if (nvals == 0) *result = 1.0 / 3.0; else *result = 3.0 / nvals; } 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. */ float64 intgtsel(opid, relid, attno, value, flag) ObjectId opid; ObjectId relid; AttributeNumber attno; /* XXX char *value;*/ 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 "=" */ /*ARGSUSED*/ float64 eqjoinsel(opid, relid1, attno1, relid2, attno2) ObjectId opid; ObjectId relid1; AttributeNumber attno1; ObjectId relid2; AttributeNumber attno2; { float64 result; int32 num1, num2, max; result = (float64) palloc(sizeof(float64data)); if (NONVALUE(attno1) || NONVALUE(relid1) || NONVALUE(attno2) || NONVALUE(relid2)) *result = 0.1; else { num1 = getattnvals(relid1, (int) attno1); num2 = getattnvals(relid2, (int) attno2); max = (num1 > num2) ? num1 : num2; if (max == 0) *result = 1.0; else *result = 1.0 / max; } return(result); } /* * neqjoinsel - Join selectivity of "!=" */ float64 neqjoinsel(opid, relid1, attno1, relid2, attno2) ObjectId opid; ObjectId relid1; AttributeNumber attno1; ObjectId relid2; AttributeNumber attno2; { float64 result; result = eqjoinsel(opid, relid1, attno1, relid2, attno2); *result = 1.0 - *result; return(result); } /* * intltjoinsel - Join selectivity of "<" */ /*ARGSUSED*/ float64 intltjoinsel(opid, relid1, attno1, relid2, attno2) ObjectId opid; ObjectId relid1; AttributeNumber attno1; ObjectId relid2; AttributeNumber attno2; { float64 result; result = (float64) palloc(sizeof(float64data)); *result = 1.0 / 3.0; return(result); } /* * intgtjoinsel - Join selectivity of ">" */ /*ARGSUSED*/ float64 intgtjoinsel(opid, relid1, attno1, relid2, attno2) ObjectId opid; ObjectId relid1; AttributeNumber attno1; ObjectId relid2; AttributeNumber attno2; { float64 result; result = (float64) palloc(sizeof(float64data)); *result = 1.0 / 3.0; return(result); } /* * getattnvals - Retrieves the number of values within an attribute. * * Note: * getattnvals 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. */ int32 getattnvals(relid, attnum) ObjectId relid; AttributeNumber attnum; { HeapTuple atp; int nvals; atp = SearchSysCacheTuple(ATTNUM, relid, attnum, NULL, NULL); if (!HeapTupleIsValid(atp)) { elog(WARN, "getattnvals: no attribute tuple %d %d", relid, attnum); return(0); } nvals = ((struct attribute *) GETSTRUCT(atp))->attnvals; if (nvals > 0) return(nvals); atp = SearchSysCacheTuple(RELOID, relid, NULL, NULL, NULL); /* 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(WARN, "getattnvals: no relation tuple %d", relid); return(0); } nvals = ((RelationTupleForm) GETSTRUCT(atp))->reltuples; 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? */ gethilokey(relid, attnum, opid, high, low) ObjectId relid; AttributeNumber attnum; ObjectId opid; char **high; char **low; { register Relation rdesc; register HeapScanDesc sdesc; static ScanKeyEntryData key[3] = { { 0, StatisticRelationIdAttributeNumber, F_OIDEQ }, { 0, StatisticAttributeNumberAttributeNumber, F_INT2EQ }, { 0, StatisticOperatorAttributeNumber, F_OIDEQ } }; Boolean isnull; HeapTuple tuple; rdesc = RelationNameOpenHeapRelation(StatisticRelationName); key[0].argument = ObjectIdGetDatum(relid); key[1].argument = Int16GetDatum((int16) attnum); key[2].argument = ObjectIdGetDatum(opid); sdesc = RelationBeginHeapScan(rdesc, 0, NowTimeQual, 3, (ScanKey) key); tuple = amgetnext(sdesc, 0, (Buffer *) NULL); if (!HeapTupleIsValid(tuple)) { *high = "n"; *low = "n"; /* XXX elog(WARN, "gethilokey: statistic tuple not found");*/ return; } *high = textout((struct varlena *) amgetattr(tuple, InvalidBuffer, StatisticHighKeyAttributeNumber, &rdesc->rd_att, &isnull)); if (isnull) elog(DEBUG, "gethilokey: high key is null"); *low = textout((struct varlena *) amgetattr(tuple, InvalidBuffer, StatisticLowKeyAttributeNumber, &rdesc->rd_att, &isnull)); if (isnull) elog(DEBUG, "gethilokey: low key is null"); HeapScanEnd(sdesc); RelationCloseHeapRelation(rdesc); } float64 btreesel(operatorObjectId, indrelid, attributeNumber, constValue, constFlag, nIndexKeys, indexrelid) ObjectId operatorObjectId, indrelid, indexrelid; AttributeNumber attributeNumber; char *constValue; int32 constFlag; int32 nIndexKeys; { float64 result; float64data resultData; if (FunctionalSelectivity(nIndexKeys, attributeNumber)) { /* * Need to call the functions selectivity * function here. For now simply assume it's * 1/3 since functions don't currently * have selectivity functions */ resultData = 1.0 / 3.0; result = &resultData; } else { result = (float64)fmgr(get_oprrest (operatorObjectId), (char*)operatorObjectId, (char*)indrelid, (char*)attributeNumber, (char*)constValue, (char*)constFlag); } if (!PointerIsValid(result)) elog(WARN, "Btree Selectivity: bad pointer"); if (*result < 0.0 || *result > 1.0) elog(WARN, "Btree Selectivity: bad value %lf", *result); return(result); } float64 btreenpage(operatorObjectId, indrelid, attributeNumber, constValue, constFlag, nIndexKeys, indexrelid) ObjectId operatorObjectId, indrelid, indexrelid; AttributeNumber attributeNumber; char *constValue; int32 constFlag; int32 nIndexKeys; { float64 temp, result; float64data tempData; HeapTuple atp; int npage; if (FunctionalSelectivity(nIndexKeys, attributeNumber)) { /* * Need to call the functions selectivity * function here. For now simply assume it's * 1/3 since functions don't currently * have selectivity functions */ tempData = 1.0 / 3.0; temp = &tempData; } else { temp = (float64)fmgr(get_oprrest (operatorObjectId), (char*)operatorObjectId, (char*)indrelid, (char*)attributeNumber, (char*)constValue, (char*)constFlag); } atp = SearchSysCacheTuple(RELOID, indexrelid, NULL, NULL, NULL); if (!HeapTupleIsValid(atp)) { elog(WARN, "btreenpage: no index tuple %d", indexrelid); return(0); } npage = ((RelationTupleForm) GETSTRUCT(atp))->relpages; result = (float64)palloc(sizeof(float64data)); *result = *temp * npage; return(result); } float64 rtsel(operatorObjectId, indrelid, attributeNumber, constValue, constFlag, nIndexKeys, indexrelid) ObjectId operatorObjectId, indrelid, indexrelid; AttributeNumber attributeNumber; char *constValue; int32 constFlag; int32 nIndexKeys; { return (btreesel(operatorObjectId, indrelid, attributeNumber, constValue, constFlag, nIndexKeys, indexrelid)); } float64 rtnpage(operatorObjectId, indrelid, attributeNumber, constValue, constFlag, nIndexKeys, indexrelid) ObjectId operatorObjectId, indrelid, indexrelid; AttributeNumber attributeNumber; char *constValue; int32 constFlag; int32 nIndexKeys; { return (btreenpage(operatorObjectId, indrelid, attributeNumber, constValue, constFlag, nIndexKeys, indexrelid)); } @ 1.18 log @function prototyping @ text @d17 1 d24 1 a24 1 RcsId("$Header: /users/mer/postgres/src/utils/adt/RCS/selfuncs.c,v 1.17 1991/10/16 23:15:20 mer Exp $"); @ 1.17 log @functional index support @ text @d23 1 a23 1 RcsId("$Header: /users/mer/postgres/src/utils/adt/RCS/selfuncs.c,v 1.16 1991/02/24 09:03:53 mao Exp mer $"); d33 2 d36 1 a50 1 extern int32 getattnvals(); a76 1 extern float64 eqsel(); a99 1 extern gethilokey(); a157 1 extern float64 intltsel(); a180 1 extern int32 getattnvals(); a209 1 extern float64 eqjoinsel(); a324 1 extern char *textout(); @ 1.16 log @add some selectivity functions for rtrees @ text @d23 1 a23 1 RcsId("$Header: RCS/selfuncs.c,v 1.15 90/10/01 16:44:51 hong Exp Locker: mao $"); d28 6 d373 1 d375 18 a392 6 result = (float64)fmgr(get_oprrest (operatorObjectId), (char*)operatorObjectId, (char*)indrelid, (char*)attributeNumber, (char*)constValue, (char*)constFlag); d412 1 d416 18 a433 6 temp = (float64)fmgr(get_oprrest (operatorObjectId), (char*)operatorObjectId, (char*)indrelid, (char*)attributeNumber, (char*)constValue, (char*)constFlag); @ 1.15 log @fixed high key and low key estimation @ text @d23 1 a23 1 RcsId("$Header: RCS/selfuncs.c,v 1.14 90/09/21 17:12:19 hong Exp Locker: hong $"); d412 26 @ 1.14 log @fixed selectivity estimation of "<" @ text @d23 1 a23 1 RcsId("$Header: RCS/selfuncs.c,v 1.13 90/08/15 08:20:01 cimarron Exp Locker: hong $"); d320 1 a320 1 /* XXX Boolean isnull;*/ a336 2 /* XXX stahikey doesn't exist for some reason ... */ #ifdef HAS_STAHIKEY a352 4 #else /* !HAS_STAHIKEY */ *high = "0"; *low = "0"; #endif /* !HAS_STAHIKEY */ @ 1.13 log @added pathnames to include statements @ text @d23 1 a23 1 RcsId("$Header: RCS/selfuncs.c,v 1.12 90/08/08 08:36:24 cimarron Exp Locker: cimarron $"); d99 34 a132 7 int nvals; nvals = getattnvals(relid, (int) attno); if (nvals == 0) *result = 1.0 / 3.0; else *result = 3.0 / nvals; d332 2 a333 2 *high = "0"; *low = "0"; @ 1.12 log @reorganized some header files. @ text @d14 4 a17 6 #include "catname.h" #include "fmgr.h" #include "heapam.h" #include "log.h" #include "syscache.h" #include "tqual.h" /* for NowTimeQual */ d19 2 d23 1 a23 1 RcsId("$Header: RCS/selfuncs.c,v 1.11 90/06/09 18:47:59 kemnitz Version_2 Locker: cimarron $"); @ 1.11 log @Got rid of datum indirection. @ text @d13 1 a13 2 #include "anum.h" #include "cat.h" d21 3 a23 1 RcsId("$Header: RCS/selfuncs.c,v 1.9 90/05/25 15:24:24 mao Exp $"); @ 1.10 log @made changes to simplify header include files @ text @d297 3 a299 3 key[0].argument.objectId.value = relid; key[1].argument.integer16.value = (int16) attnum; key[2].argument.objectId.value = opid; @ 1.9 log @change ltsel function for integers -- now 3/ntups in relation. this isn't very sensible, but it's way better than what we were returning @ text @d14 1 a14 1 #include "catalog.h" d22 1 a22 1 RcsId("$Header: RCS/selfuncs.c,v 1.8 89/11/16 14:22:22 hong Exp $"); @ 1.8 log @if we can fake the statistics for number of distinctive values, still use that instead of the number of tuples. @ text @d22 1 a22 1 RcsId("$Header: RCS/selfuncs.c,v 1.7 89/10/31 11:29:06 hong Exp $"); d98 7 a104 28 /* XXX val = atol(value);*/ val = value; gethilokey(relid, (int) attno, opid, &highchar, &lowchar); high = atol(highchar); low = atol(lowchar); if (high == 0 || low == 0) { *result = 1.0/3.0; return (result); } if ((flag & SEL_RIGHT && val < low) || (!(flag & SEL_RIGHT) && val > high)) *result = 0.0; 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); } } @ 1.7 log @add selectivity functions for btree, fixed intltsel @ text @d22 1 a22 1 RcsId("$Header: RCS/selfuncs.c,v 1.6 89/10/25 21:50:07 hong Exp Locker: hong $"); d266 9 d277 1 a277 1 just for now, because number of distinctive values is @ 1.6 log @replace attnvals with reltuples, because attnvals is not cached right now. @ text @d22 1 a22 1 RcsId("$Header: RCS/selfuncs.c,v 1.5 89/09/28 17:50:25 hirohama Exp Locker: hong $"); d103 4 d271 1 a271 2 elog(WARN, "getattnvals: no attribute tuple %d %d", relid, attnum); d345 57 @ 1.5 log @TimeRange -> TimeQual @ text @d22 1 a22 1 RcsId("$Header: RCS/selfuncs.c,v 1.4 89/09/05 17:26:39 mao C_Demo_1 Locker: hirohama $"); d262 4 a265 1 atp = SearchSysCacheTuple(ATTNUM, relid, attnum, NULL, NULL); d271 1 a271 1 nvals = ((struct attribute *) GETSTRUCT(atp))->attnvals; @ 1.4 log @Working version of C-only demo @ text @d20 1 d22 1 a22 1 RcsId("$Header: /usr6/postgres/mao/postgres/src/utils/adt/RCS/selfuncs.c,v 1.3 89/08/09 18:11:28 cimarron Exp $"); d306 1 a306 1 sdesc = RelationBeginHeapScan(rdesc, 0, NowTimeRange, @ 1.3 log @"retrieve(x=1)" @ text @d21 1 a21 1 RcsId("$Header: /usr6/postgres/cimarron/postgres3/src/utils/adt/RCS/selfuncs.c,v 1.2 89/02/02 16:11:40 aoki Stab $"); @ 1.2 log @MERGE WITH OLD TREE @ text @d21 1 a21 1 RcsId("$Header: selfuncs.c,v 2.7 88/07/16 11:47:30 aoki Locked $"); d291 1 a291 1 register HeapScan sdesc; @ 1.1 log @Initial revision @ text @a0 1 a1 26 * * POSTGRES Data Base Management System * * Copyright (c) 1988 Regents of the University of California * * Permission to use, copy, modify, and distribute this software and its * documentation for educational, research, and non-profit purposes and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of the University of California not be used in advertising * or publicity pertaining to distribution of the software without * specific, written prior permission. Permission to incorporate this * software into commercial products can be obtained from the Campus * Software Office, 295 Evans Hall, University of California, Berkeley, * Ca., 94720 provided only that the the requestor give the University * of California a free licence to any derived software for educational * and research purposes. The University of California makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * */ /* d21 1 a21 1 RcsId("$Header: selfuncs.c,v 1.1 88/11/11 16:35:47 postgres Exp $"); @