Move get_attdisbursion to lsyscache. Clean up get_typdefault.
authorTom Lane
Mon, 9 Aug 1999 03:13:31 +0000 (03:13 +0000)
committerTom Lane
Mon, 9 Aug 1999 03:13:31 +0000 (03:13 +0000)
src/backend/optimizer/prep/preptlist.c
src/backend/utils/cache/lsyscache.c
src/backend/utils/cache/syscache.c
src/include/utils/lsyscache.h
src/include/utils/syscache.h

index ac0223879ddfcb572b1881d0efd4952f9a2fe9ba..0cc4780807e85d0b8ac6f5d33e08f1d593058992 100644 (file)
@@ -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);
index 07583a4b72a3a4069741b2c6b74b4ac35f5f45c2..cd657ca32729b1cb52a3da3ee86da63ff0e585ca 100644 (file)
@@ -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;
 }
 
 /*
index 4e4c354e07b2bc6c581f27a6ad8304f51db7b734..470780676c29487ac142b9a50a7e8bef1e5e7952 100644 (file)
@@ -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;
-}
index 39cf80d9ebf8a8f5a23695593772e01723bb69e1..4ca8fddda108359a512ef2077c425c70245dee66 100644 (file)
@@ -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 */
index 313f543e45e90085b04e362138c97c8b8d10c08b..b2850a8a6b0d71d2f612429f3efcdcb3615d6ec7 100644 (file)
@@ -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 */