OSDN Git Service

pg_type has a typnamespace column; system now supports creating types
[pg-rex/syncrep.git] / src / backend / utils / cache / lsyscache.c
index 3247c0a..6ec682f 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.61 2002/03/06 20:34:54 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.67 2002/03/29 19:06:15 tgl Exp $
  *
  * NOTES
  *       Eventually, the index information should go through here, too.
@@ -23,7 +23,7 @@
 #include "catalog/pg_shadow.h"
 #include "catalog/pg_statistic.h"
 #include "catalog/pg_type.h"
-#include "parser/parse_coerce.h"
+#include "nodes/makefuncs.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
@@ -634,6 +634,21 @@ func_iscachable(Oid funcid)
 
 /*                             ---------- RELATION CACHE ----------                                     */
 
+/*
+ * get_relname_relid
+ *             Given name and namespace of a relation, look up the OID.
+ *
+ * Returns InvalidOid if there is no such relation.
+ */
+Oid
+get_relname_relid(const char *relname, Oid relnamespace)
+{
+       return GetSysCacheOid(RELNAMENSP,
+                                                 PointerGetDatum(relname),
+                                                 ObjectIdGetDatum(relnamespace),
+                                                 0, 0);
+}
+
 #ifdef NOT_USED
 /*
  * get_relnatts
@@ -664,10 +679,12 @@ get_relnatts(Oid relid)
 
 /*
  * get_rel_name
- *
  *             Returns the name of a given relation.
  *
- * Note: returns a palloc'd copy of the string, or NULL if no such relation.
+ * Returns a palloc'd copy of the string, or NULL if no such relation.
+ *
+ * NOTE: since relation name is not unique, be wary of code that uses this
+ * for anything except preparing error messages.
  */
 char *
 get_rel_name(Oid relid)
@@ -690,9 +707,65 @@ get_rel_name(Oid relid)
                return NULL;
 }
 
+/*
+ * get_rel_type_id
+ *
+ *             Returns the pg_type OID associated with a given relation.
+ *
+ * Note: not all pg_class entries have associated pg_type OIDs; so be
+ * careful to check for InvalidOid result.
+ */
+Oid
+get_rel_type_id(Oid relid)
+{
+       HeapTuple       tp;
+
+       tp = SearchSysCache(RELOID,
+                                               ObjectIdGetDatum(relid),
+                                               0, 0, 0);
+       if (HeapTupleIsValid(tp))
+       {
+               Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
+               Oid             result;
+
+               result = reltup->reltype;
+               ReleaseSysCache(tp);
+               return result;
+       }
+       else
+               return InvalidOid;
+}
+
 /*                             ---------- TYPE CACHE ----------                                                 */
 
 /*
+ * get_typisdefined
+ *
+ *             Given the type OID, determine whether the type is defined
+ *             (if not, it's only a shell).
+ */
+bool
+get_typisdefined(Oid typid)
+{
+       HeapTuple       tp;
+
+       tp = SearchSysCache(TYPEOID,
+                                               ObjectIdGetDatum(typid),
+                                               0, 0, 0);
+       if (HeapTupleIsValid(tp))
+       {
+               Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
+               bool            result;
+
+               result = typtup->typisdefined;
+               ReleaseSysCache(tp);
+               return result;
+       }
+       else
+               return false;
+}
+
+/*
  * get_typlen
  *
  *             Given the type OID, return the length of the type.
@@ -818,19 +891,19 @@ get_typstorage(Oid typid)
 
 /*
  * get_typdefault
- *
  *       Given a type OID, return the type's default value, if any.
- *       Returns FALSE if there is no default (effectively, default is NULL).
- *       The result points to palloc'd storage for pass-by-reference types.
+ *
+ *       The result is a palloc'd expression node tree, or NULL if there
+ *       is no defined default for the datatype.
+ *
+ * NB: caller should be prepared to coerce result to correct datatype;
+ * the returned expression tree might produce something of the wrong type.
  */
 Node *
-get_typdefault(Oid typid, int32 atttypmod)
+get_typdefault(Oid typid)
 {
        HeapTuple       typeTuple;
        Form_pg_type type;
-       Oid                     typinput;
-       Oid                     typbasetype;
-       char            typtype;
        Datum           datum;
        bool            isNull;
        Node       *expr;
@@ -838,48 +911,102 @@ get_typdefault(Oid typid, int32 atttypmod)
        typeTuple = SearchSysCache(TYPEOID,
                                                           ObjectIdGetDatum(typid),
                                                           0, 0, 0);
-
        if (!HeapTupleIsValid(typeTuple))
                elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
-
        type = (Form_pg_type) GETSTRUCT(typeTuple);
 
-       typinput = type->typinput;
-       typbasetype = type->typbasetype;
-       typtype = type->typtype;
-
        /*
-        * typdefaultbin is potentially null, so don't try to access it as a
-        * struct field. Must do it the hard way with SysCacheGetAttr.
+        * typdefault and typdefaultbin are potentially null, so don't try to
+        * access 'em as struct fields. Must do it the hard way with
+        * SysCacheGetAttr.
         */
        datum = SysCacheGetAttr(TYPEOID,
                                                        typeTuple,
                                                        Anum_pg_type_typdefaultbin,
                                                        &isNull);
 
-       ReleaseSysCache(typeTuple);
-       if (isNull)
-               return (Node *) NULL;
+       if (!isNull)
+       {
+               /* We have an expression default */
+               expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout,
+                                                                                                                               datum)));
+       }
+       else
+       {
+               /* Perhaps we have a plain literal default */
+               datum = SysCacheGetAttr(TYPEOID,
+                                                               typeTuple,
+                                                               Anum_pg_type_typdefault,
+                                                               &isNull);
 
-       /* Convert Datum to a Node */
-       expr = stringToNode(DatumGetCString(
-                                               DirectFunctionCall1(textout, datum)));
+               if (!isNull)
+               {
+                       char       *strDefaultVal;
+
+                       /* Convert text datum to C string */
+                       strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
+                                                                                                                               datum));
+                       /* Convert C string to a value of the given type */
+                       datum = OidFunctionCall3(type->typinput,
+                                                                        CStringGetDatum(strDefaultVal),
+                                                                        ObjectIdGetDatum(type->typelem),
+                                                                        Int32GetDatum(-1));
+                       /* Build a Const node containing the value */
+                       expr = (Node *) makeConst(typid,
+                                                                         type->typlen,
+                                                                         datum,
+                                                                         false,
+                                                                         type->typbyval,
+                                                                         false,        /* not a set */
+                                                                         false);
+                       pfree(strDefaultVal);
+               }
+               else
+               {
+                       /* No default */
+                       expr = NULL;
+               }
+       }
 
+       ReleaseSysCache(typeTuple);
 
+       return expr;
+}
+
+/*
+ * getBaseType
+ *             If the given type is a domain, return its base type;
+ *             otherwise return the type's own OID.
+ */
+Oid
+getBaseType(Oid typid)
+{
        /*
-        * Ensure we goto the basetype before the domain type.
-        *
-        * Prevents scenarios like the below from failing:
-        * CREATE DOMAIN dom text DEFAULT random();
-        *
+        * We loop to find the bottom base type in a stack of domains.
         */
-       if (typbasetype != InvalidOid) {
-               expr = coerce_type(NULL, expr, typid,
-                                                 typbasetype, atttypmod);
-       }
+       for (;;)
+       {
+               HeapTuple       tup;
+               Form_pg_type typTup;
+
+               tup = SearchSysCache(TYPEOID,
+                                                        ObjectIdGetDatum(typid),
+                                                        0, 0, 0);
+               if (!HeapTupleIsValid(tup))
+                       elog(ERROR, "getBaseType: failed to lookup type %u", typid);
+               typTup = (Form_pg_type) GETSTRUCT(tup);
+               if (typTup->typtype != 'd')
+               {
+                       /* Not a domain, so done */
+                       ReleaseSysCache(tup);
+                       break;
+               }
 
+               typid = typTup->typbasetype;
+               ReleaseSysCache(tup);
+       }
 
-       return expr;
+       return typid;
 }
 
 /*