aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/prep/preptlist.c11
-rw-r--r--src/backend/utils/cache/lsyscache.c182
-rw-r--r--src/backend/utils/cache/syscache.c111
-rw-r--r--src/include/utils/lsyscache.h9
-rw-r--r--src/include/utils/syscache.h5
5 files changed, 187 insertions, 131 deletions
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index ac0223879dd..0cc4780807e 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 07583a4b72a..cd657ca3272 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 4e4c354e07b..470780676c2 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 39cf80d9ebf..4ca8fddda10 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 313f543e45e..b2850a8a6b0 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 */