diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c index ac0223879ddfcb572b1881d0efd4952f9a2fe9ba..0cc4780807e85d0b8ac6f5d33e08f1d593058992 100644 --- a/src/backend/optimizer/prep/preptlist.c +++ b/src/backend/optimizer/prep/preptlist.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.28 1999/08/09 00:51:26 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.29 1999/08/09 03:13:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -297,12 +297,12 @@ new_relation_targetlist(Oid relid, Index rt_index, NodeTag node_type) { case T_Const: /* INSERT command */ { - struct varlena *typedefault = get_typdefault(atttype); + Datum typedefault = get_typdefault(atttype); int typlen; Const *temp_const; TargetEntry *temp_tle; - if (typedefault == NULL) + if (typedefault == PointerGetDatum(NULL)) typlen = 0; else { @@ -319,9 +319,8 @@ new_relation_targetlist(Oid relid, Index rt_index, NodeTag node_type) temp_const = makeConst(atttype, typlen, - (Datum) typedefault, - (typedefault == NULL), - /* XXX ? */ + typedefault, + (typedefault == PointerGetDatum(NULL)), false, false, /* not a set */ false); diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 07583a4b72a3a4069741b2c6b74b4ac35f5f45c2..cd657ca32729b1cb52a3da3ee86da63ff0e585ca 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -1,13 +1,12 @@ /*------------------------------------------------------------------------- * * lsyscache.c - * Routines to access information within system caches + * Convenience routines for common queries in the system catalog cache. * * Copyright (c) 1994, Regents of the University of California * - * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.31 1999/07/17 20:18:01 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.32 1999/08/09 03:13:30 tgl Exp $ * * NOTES * Eventually, the index information should go through here, too. @@ -15,7 +14,6 @@ */ #include "postgres.h" - #include "catalog/pg_operator.h" #include "catalog/pg_type.h" #include "utils/lsyscache.h" @@ -166,6 +164,77 @@ get_atttypmod(Oid relid, AttrNumber attnum) return -1; } +/* + * get_attdisbursion + * + * Retrieve the disbursion statistic for an attribute, + * or produce an estimate if no info is available. + * + * min_estimate is the minimum estimate to return if insufficient data + * is available to produce a reliable value. This value may vary + * depending on context. (For example, when deciding whether it is + * safe to use a hashjoin, we want to be more conservative than when + * estimating the number of tuples produced by an equijoin.) + */ +double +get_attdisbursion(Oid relid, AttrNumber attnum, double min_estimate) +{ + HeapTuple atp; + double disbursion; + int32 ntuples; + + atp = SearchSysCacheTuple(ATTNUM, + ObjectIdGetDatum(relid), + Int16GetDatum(attnum), + 0, 0); + if (!HeapTupleIsValid(atp)) + { + /* this should not happen */ + elog(ERROR, "get_attdisbursion: no attribute tuple %u %d", + relid, attnum); + return min_estimate; + } + + disbursion = ((Form_pg_attribute) GETSTRUCT(atp))->attdisbursion; + if (disbursion > 0.0) + return disbursion; /* we have a specific estimate */ + + /* + * Disbursion is either 0 (no data available) or -1 (disbursion + * is 1/numtuples). Either way, we need the relation size. + */ + + atp = SearchSysCacheTuple(RELOID, + ObjectIdGetDatum(relid), + 0, 0, 0); + if (!HeapTupleIsValid(atp)) + { + /* this should not happen */ + elog(ERROR, "get_attdisbursion: no relation tuple %u", relid); + return min_estimate; + } + + ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples; + + if (ntuples == 0) + return min_estimate; /* no data available */ + + if (disbursion < 0.0) /* VACUUM thinks there are no duplicates */ + return 1.0 / (double) ntuples; + + /* + * VACUUM ANALYZE has not been run for this table. + * Produce an estimate = 1/numtuples. This may produce + * unreasonably small estimates for large tables, so limit + * the estimate to no less than min_estimate. + */ + disbursion = 1.0 / (double) ntuples; + if (disbursion < min_estimate) + disbursion = min_estimate; + + return disbursion; +} + /* ---------- INDEX CACHE ---------- */ /* watch this space... @@ -504,15 +573,110 @@ get_typalign(Oid typid) /* * get_typdefault - * - * Given the type OID, return the default value of the ADT. - * + * Given a type OID, return the typdefault field associated with that + * type, or Datum(NULL) if there is no typdefault. (This implies + * that pass-by-value types can't have a default value that has + * a representation of zero. Not worth fixing now.) + * The result points to palloc'd storage for non-pass-by-value types. */ -struct varlena * +Datum get_typdefault(Oid typid) { - struct varlena *typdefault = (struct varlena *) TypeDefaultRetrieve(typid); + struct varlena *typDefault; + int32 dataSize; + HeapTuple typeTuple; + Form_pg_type type; + int32 typLen; + bool typByVal; + Datum returnValue; + + /* + * First, see if there is a non-null typdefault field (usually there isn't) + */ + typDefault = (struct varlena *) + SearchSysCacheGetAttribute(TYPOID, + Anum_pg_type_typdefault, + ObjectIdGetDatum(typid), + 0, 0, 0); + + if (typDefault == NULL) + return PointerGetDatum(NULL); + + dataSize = VARSIZE(typDefault) - VARHDRSZ; + + /* + * Need the type's length and byVal fields. + * + * XXX silly to repeat the syscache search that SearchSysCacheGetAttribute + * just did --- but at present this path isn't taken often enough to + * make it worth fixing. + */ + typeTuple = SearchSysCacheTuple(TYPOID, + ObjectIdGetDatum(typid), + 0, 0, 0); + + if (!HeapTupleIsValid(typeTuple)) + elog(ERROR, "get_typdefault: failed to lookup type %u", typid); + + type = (Form_pg_type) GETSTRUCT(typeTuple); + typLen = type->typlen; + typByVal = type->typbyval; + + if (typByVal) + { + int8 i8; + int16 i16; + int32 i32 = 0; + + if (dataSize == typLen) + { + switch (typLen) + { + case sizeof(int8): + memcpy((char *) &i8, VARDATA(typDefault), sizeof(int8)); + i32 = i8; + break; + case sizeof(int16): + memcpy((char *) &i16, VARDATA(typDefault), sizeof(int16)); + i32 = i16; + break; + case sizeof(int32): + memcpy((char *) &i32, VARDATA(typDefault), sizeof(int32)); + break; + } + returnValue = Int32GetDatum(i32); + } + else + returnValue = PointerGetDatum(NULL); + } + else if (typLen < 0) + { + /* variable-size type */ + if (dataSize < 0) + returnValue = PointerGetDatum(NULL); + else + { + returnValue = PointerGetDatum(palloc(VARSIZE(typDefault))); + memcpy((char *) DatumGetPointer(returnValue), + (char *) typDefault, + (int) VARSIZE(typDefault)); + } + } + else + { + /* fixed-size pass-by-ref type */ + if (dataSize != typLen) + returnValue = PointerGetDatum(NULL); + else + { + returnValue = PointerGetDatum(palloc(dataSize)); + memcpy((char *) DatumGetPointer(returnValue), + VARDATA(typDefault), + (int) dataSize); + } + } - return typdefault; + return returnValue; } /* diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index 4e4c354e07b2bc6c581f27a6ad8304f51db7b734..470780676c29487ac142b9a50a7e8bef1e5e7952 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.33 1999/07/20 17:14:06 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.34 1999/08/09 03:13:30 tgl Exp $ * * NOTES * These routines allow the parser/planner/executor to perform @@ -631,112 +631,3 @@ SearchSysCacheGetAttribute(int cacheId, heap_close(relation); return returnValue; } - -/* - * TypeDefaultRetrieve - * - * Given a type OID, return the typdefault field associated with that - * type. The result is a Datum, and points to palloc'd storage for - * non-pass-by-value types. - * - * [identical to get_typdefault, expecting a (struct varlena *) as ret val. - * some day, either of the functions should be removed -ay 10/94] - */ -void * -TypeDefaultRetrieve(Oid typId) -{ - struct varlena *typDefault; - int32 dataSize; - HeapTuple typeTuple; - Form_pg_type type; - int32 typByVal, - typLen; - void *returnValue; - - /* - * First, see if there is a non-null typdefault field (usually there isn't) - */ - typDefault = (struct varlena *) - SearchSysCacheGetAttribute(TYPOID, - Anum_pg_type_typdefault, - ObjectIdGetDatum(typId), - 0, 0, 0); - - if (typDefault == NULL) - { -#ifdef CACHEDEBUG - elog(DEBUG, "TypeDefaultRetrieve: No extractable typdefault in %s(%d)", - cacheinfo[TYPOID].name, TYPOID); -#endif /* defined(CACHEDEBUG) */ - return NULL; - } - - dataSize = VARSIZE(typDefault) - VARHDRSZ; - - /* - * Need the type's length and byVal fields. - * - * XXX silly to repeat the syscache search that SearchSysCacheGetAttribute - * just did --- but at present this path isn't taken often enough to - * make it worth fixing. - */ - typeTuple = SearchSysCacheTuple(TYPOID, - ObjectIdGetDatum(typId), - 0, 0, 0); - - if (!HeapTupleIsValid(typeTuple)) - { - /* should never get here, really... */ -#ifdef CACHEDEBUG - elog(DEBUG, "TypeDefaultRetrieve: Lookup in %s(%d) failed", - cacheinfo[TYPOID].name, TYPOID); -#endif /* defined(CACHEDEBUG) */ - return NULL; - } - - type = (Form_pg_type) GETSTRUCT(typeTuple); - typLen = type->typlen; - typByVal = type->typbyval; - - if (typByVal) - { - int8 i8; - int16 i16; - int32 i32 = 0; - - if (dataSize == typLen) - { - switch (typLen) - { - case sizeof(int8): - memcpy((char *) &i8, VARDATA(typDefault), sizeof(int8)); - i32 = i8; - break; - case sizeof(int16): - memcpy((char *) &i16, VARDATA(typDefault), sizeof(int16)); - i32 = i16; - break; - case sizeof(int32): - memcpy((char *) &i32, VARDATA(typDefault), sizeof(int32)); - break; - } - returnValue = (void *) i32; - } - else - returnValue = NULL; - } - else - { - if ((typLen < 0 && dataSize < 0) || dataSize != typLen) - returnValue = NULL; - else - { - returnValue = (void *) palloc(VARSIZE(typDefault)); - memcpy((char *) returnValue, - (char *) typDefault, - (int) VARSIZE(typDefault)); - } - } - - return returnValue; -} diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index 39cf80d9ebf8a8f5a23695593772e01723bb69e1..4ca8fddda108359a512ef2077c425c70245dee66 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -1,12 +1,11 @@ /*------------------------------------------------------------------------- * * lsyscache.h - * - * + * Convenience routines for common queries in the system catalog cache. * * Copyright (c) 1994, Regents of the University of California * - * $Id: lsyscache.h,v 1.18 1999/07/15 23:04:23 momjian Exp $ + * $Id: lsyscache.h,v 1.19 1999/08/09 03:13:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +20,8 @@ extern AttrNumber get_attnum(Oid relid, char *attname); extern Oid get_atttype(Oid relid, AttrNumber attnum); extern bool get_attisset(Oid relid, char *attname); extern int32 get_atttypmod(Oid relid, AttrNumber attnum); +extern double get_attdisbursion(Oid relid, AttrNumber attnum, + double min_estimate); extern RegProcedure get_opcode(Oid opid); extern char *get_opname(Oid opid); extern bool op_mergejoinable(Oid opid, Oid ltype, Oid rtype, @@ -38,6 +39,6 @@ extern Oid get_ruleid(char *rulename); extern Oid get_eventrelid(Oid ruleid); extern int16 get_typlen(Oid typid); extern bool get_typbyval(Oid typid); -extern struct varlena *get_typdefault(Oid typid); +extern Datum get_typdefault(Oid typid); #endif /* LSYSCACHE_H */ diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h index 313f543e45e90085b04e362138c97c8b8d10c08b..b2850a8a6b0d71d2f612429f3efcdcb3615d6ec7 100644 --- a/src/include/utils/syscache.h +++ b/src/include/utils/syscache.h @@ -3,10 +3,12 @@ * syscache.h * System catalog cache definitions. * + * See also lsyscache.h, which provides convenience routines for + * common cache-lookup operations. * * Copyright (c) 1994, Regents of the University of California * - * $Id: syscache.h,v 1.17 1999/07/20 17:14:08 momjian Exp $ + * $Id: syscache.h,v 1.18 1999/08/09 03:13:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -87,6 +89,5 @@ extern int32 SearchSysCacheStruct(int cacheId, char *returnStruct, extern void *SearchSysCacheGetAttribute(int cacheId, AttrNumber attributeNumber, Datum key1, Datum key2, Datum key3, Datum key4); -extern void *TypeDefaultRetrieve(Oid typId); #endif /* SYSCACHE_H */