OSDN Git Service

pgindent run.
[pg-rex/syncrep.git] / src / backend / catalog / pg_type.c
index 0c2292a..d43c1ed 100644 (file)
 /*-------------------------------------------------------------------------
  *
- * pg_type.c--
+ * pg_type.c
  *       routines to support manipulation of the pg_type relation
  *
- * Copyright (c) 1994, Regents of the University of California
+ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.11 1997/09/18 20:20:19 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.82 2002/09/04 20:31:14 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
-#include <postgres.h>
-
-#include <utils/syscache.h>
-#include <catalog/pg_proc.h>
-#include <access/heapam.h>
-#include <access/relscan.h>
-#include <utils/builtins.h>
-#include <fmgr.h>
-#include <parser/catalog_utils.h>
-#include <catalog/catname.h>
-#include <catalog/indexing.h>
-#include <storage/lmgr.h>
-#include <miscadmin.h>
-#ifndef HAVE_MEMMOVE
-#include <regex/utils.h>
-#else
-#include <string.h>
-#endif
-
-static Oid
-TypeShellMakeWithOpenRelation(Relation pg_type_desc,
-                                                         char *typeName);
+#include "postgres.h"
 
-/* ----------------------------------------------------------------
- *             TypeGetWithOpenRelation
- *
- *             preforms a scan on pg_type for a type tuple with the
- *             given type name.
- * ----------------------------------------------------------------
- *             pg_type_desc                     -- reldesc for pg_type
- *             typeName                                 -- name of type to be fetched
- *             defined                                  -- has the type been defined?
- */
-static Oid
-TypeGetWithOpenRelation(Relation pg_type_desc,
-                                               char *typeName,
-                                               bool *defined)
-{
-       HeapScanDesc scan;
-       HeapTuple       tup;
-
-       static ScanKeyData typeKey[1] = {
-               {0, Anum_pg_type_typname, NameEqualRegProcedure}
-       };
-
-       /* ----------------
-        *      initialize the scan key and begin a scan of pg_type
-        * ----------------
-        */
-       fmgr_info(NameEqualRegProcedure,
-                         &typeKey[0].sk_func, &typeKey[0].sk_nargs);
-       typeKey[0].sk_argument = PointerGetDatum(typeName);
-
-       scan = heap_beginscan(pg_type_desc,
-                                                 0,
-                                                 SelfTimeQual,
-                                                 1,
-                                                 typeKey);
-
-       /* ----------------
-        *      get the type tuple, if it exists.
-        * ----------------
-        */
-       tup = heap_getnext(scan, 0, (Buffer *) 0);
-
-       /* ----------------
-        *      if no type tuple exists for the given type name, then
-        *      end the scan and return appropriate information.
-        * ----------------
-        */
-       if (!HeapTupleIsValid(tup))
-       {
-               heap_endscan(scan);
-               *defined = false;
-               return InvalidOid;
-       }
+#include "access/heapam.h"
+#include "catalog/catname.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_type.h"
+#include "miscadmin.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+#include "utils/syscache.h"
 
-       /* ----------------
-        *      here, the type tuple does exist so we pull information from
-        *      the typisdefined field of the tuple and return the tuple's
-        *      oid, which is the oid of the type.
-        * ----------------
-        */
-       heap_endscan(scan);
-       *defined = (bool) ((TypeTupleForm) GETSTRUCT(tup))->typisdefined;
-
-       return
-               tup->t_oid;
-}
 
 /* ----------------------------------------------------------------
- *             TypeGet
- *
- *             Finds the ObjectId of a type, even if uncommitted; "defined"
- *             is only set if the type has actually been defined, i.e., if
- *             the type tuple is not a shell.
+ *             TypeShellMake
  *
- *             Note: the meat of this function is now in the function
- *                       TypeGetWithOpenRelation().  -cim 6/15/90
+ *             This procedure inserts a "shell" tuple into the type
+ *             relation.  The type tuple inserted has invalid values
+ *             and in particular, the "typisdefined" field is false.
  *
- *             Also called from util/remove.c
+ *             This is used so that a tuple exists in the catalogs.
+ *             The invalid fields should be fixed up sometime after
+ *             this routine is called, and then the "typeisdefined"
+ *             field is set to true. -cim 6/15/90
  * ----------------------------------------------------------------
  */
 Oid
-TypeGet(char *typeName,                        /* name of type to be fetched */
-               bool *defined)                  /* has the type been defined? */
+TypeShellMake(const char *typeName, Oid typeNamespace)
 {
        Relation        pg_type_desc;
-       Oid                     typeoid;
-
-       /* ----------------
-        *      open the pg_type relation
-        * ----------------
-        */
-       pg_type_desc = heap_openr(TypeRelationName);
-
-       /* ----------------
-        *      scan the type relation for the information we want
-        * ----------------
-        */
-       typeoid = TypeGetWithOpenRelation(pg_type_desc,
-                                                                         typeName,
-                                                                         defined);
-
-       /* ----------------
-        *      close the type relation and return the type oid.
-        * ----------------
-        */
-       heap_close(pg_type_desc);
-
-       return
-               typeoid;
-}
-
-/* ----------------------------------------------------------------
- *             TypeShellMakeWithOpenRelation
- *
- * ----------------------------------------------------------------
- */
-static Oid
-TypeShellMakeWithOpenRelation(Relation pg_type_desc, char *typeName)
-{
-       register int i;
+       TupleDesc       tupDesc;
+       int                     i;
        HeapTuple       tup;
        Datum           values[Natts_pg_type];
        char            nulls[Natts_pg_type];
        Oid                     typoid;
-       TupleDesc       tupDesc;
+       NameData        name;
 
-       /* ----------------
-        *      initialize our nulls[] and values[] arrays
-        * ----------------
+       Assert(PointerIsValid(typeName));
+
+       /*
+        * open pg_type
+        */
+       pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
+       tupDesc = pg_type_desc->rd_att;
+
+       /*
+        * initialize our *nulls and *values arrays
         */
        for (i = 0; i < Natts_pg_type; ++i)
        {
@@ -170,336 +67,207 @@ TypeShellMakeWithOpenRelation(Relation pg_type_desc, char *typeName)
                values[i] = (Datum) NULL;               /* redundant, but safe */
        }
 
-       /* ----------------
-        *      initialize values[] with the type name and
-        * ----------------
+       /*
+        * initialize *values with the type name and dummy values
         */
        i = 0;
-       values[i++] = (Datum) typeName;         /* 1 */
-       values[i++] = (Datum) InvalidOid;       /* 2 */
-       values[i++] = (Datum) (int16) 0;        /* 3 */
-       values[i++] = (Datum) (int16) 0;        /* 4 */
-       values[i++] = (Datum) (bool) 0;         /* 5 */
-       values[i++] = (Datum) (bool) 0;         /* 6 */
-       values[i++] = (Datum) (bool) 0;         /* 7 */
-       values[i++] = (Datum) (bool) 0;         /* 8 */
-       values[i++] = (Datum) InvalidOid;       /* 9 */
-       values[i++] = (Datum) InvalidOid;       /* 10 */
-       values[i++] = (Datum) InvalidOid;       /* 11 */
-       values[i++] = (Datum) InvalidOid;       /* 12 */
-       values[i++] = (Datum) InvalidOid;       /* 13 */
-       values[i++] = (Datum) InvalidOid;       /* 14 */
-       values[i++] = (Datum) 'i';      /* 15 */
+       namestrcpy(&name, typeName);
+       values[i++] = NameGetDatum(&name);      /* typname */
+       values[i++] = ObjectIdGetDatum(typeNamespace);          /* typnamespace */
+       values[i++] = ObjectIdGetDatum(InvalidOid); /* typowner */
+       values[i++] = Int16GetDatum(0);         /* typlen */
+       values[i++] = BoolGetDatum(false);      /* typbyval */
+       values[i++] = CharGetDatum(0);          /* typtype */
+       values[i++] = BoolGetDatum(false);      /* typisdefined */
+       values[i++] = CharGetDatum(0);          /* typdelim */
+       values[i++] = ObjectIdGetDatum(InvalidOid); /* typrelid */
+       values[i++] = ObjectIdGetDatum(InvalidOid); /* typelem */
+       values[i++] = ObjectIdGetDatum(InvalidOid); /* typinput */
+       values[i++] = ObjectIdGetDatum(InvalidOid); /* typoutput */
+       values[i++] = CharGetDatum('i');        /* typalign */
+       values[i++] = CharGetDatum('p');        /* typstorage */
+       values[i++] = BoolGetDatum(false);      /* typnotnull */
+       values[i++] = ObjectIdGetDatum(InvalidOid); /* typbasetype */
+       values[i++] = Int32GetDatum(-1);        /* typtypmod */
+       values[i++] = Int32GetDatum(0);         /* typndims */
+       nulls[i++] = 'n';                       /* typdefaultbin */
+       nulls[i++] = 'n';                       /* typdefault */
 
        /*
-        * ... and fill typdefault with a bogus value
-        */
-       values[i++] =
-               (Datum) fmgr(TextInRegProcedure, typeName);             /* 15 */
-
-       /* ----------------
-        *      create a new type tuple with FormHeapTuple
-        * ----------------
+        * create a new type tuple
         */
-       tupDesc = pg_type_desc->rd_att;
-
        tup = heap_formtuple(tupDesc, values, nulls);
 
-       /* ----------------
-        *      insert the tuple in the relation and get the tuple's oid.
-        * ----------------
-        */
-       heap_insert(pg_type_desc, tup);
-       typoid = tup->t_oid;
-
-       if (RelationGetRelationTupleForm(pg_type_desc)->relhasindex)
-       {
-               Relation        idescs[Num_pg_type_indices];
-
-               CatalogOpenIndices(Num_pg_type_indices, Name_pg_type_indices, idescs);
-               CatalogIndexInsert(idescs, Num_pg_type_indices, pg_type_desc, tup);
-               CatalogCloseIndices(Num_pg_type_indices, idescs);
-       }
-       /* ----------------
-        *      free the tuple and return the type-oid
-        * ----------------
-        */
-       pfree(tup);
-
-       return
-               typoid;
-}
-
-/* ----------------------------------------------------------------
- *             TypeShellMake
- *
- *             This procedure inserts a "shell" tuple into the type
- *             relation.  The type tuple inserted has invalid values
- *             and in particular, the "typisdefined" field is false.
- *
- *             This is used so that a tuple exists in the catalogs.
- *             The invalid fields should be fixed up sometime after
- *             this routine is called, and then the "typeisdefined"
- *             field is set to true. -cim 6/15/90
- * ----------------------------------------------------------------
- */
-Oid
-TypeShellMake(char *typeName)
-{
-       Relation        pg_type_desc;
-       Oid                     typoid;
-
-       Assert(PointerIsValid(typeName));
-
-       /* ----------------
-        *      open pg_type
-        * ----------------
+       /*
+        * insert the tuple in the relation and get the tuple's oid.
         */
-       pg_type_desc = heap_openr(TypeRelationName);
+       typoid = simple_heap_insert(pg_type_desc, tup);
 
-       /* ----------------
-        *      insert the shell tuple
-        * ----------------
-        */
-       typoid = TypeShellMakeWithOpenRelation(pg_type_desc, typeName);
+       CatalogUpdateIndexes(pg_type_desc, tup);
 
-       /* ----------------
-        *      close pg_type and return the tuple's oid.
-        * ----------------
+       /*
+        * clean up and return the type-oid
         */
-       heap_close(pg_type_desc);
+       heap_freetuple(tup);
+       heap_close(pg_type_desc, RowExclusiveLock);
 
-       return
-               typoid;
+       return typoid;
 }
 
 /* ----------------------------------------------------------------
  *             TypeCreate
  *
  *             This does all the necessary work needed to define a new type.
+ *
+ * NOTE: if assignedTypeOid is not InvalidOid, then that OID is assigned to
+ * the new type (which, therefore, cannot already exist as a shell type).
+ * This hack is only intended for use in creating a relation's associated
+ * type, where we need to have created the relation tuple already.
  * ----------------------------------------------------------------
  */
 Oid
-TypeCreate(char *typeName,
-                  Oid relationOid,             /* only for 'c'atalog typeTypes */
+TypeCreate(const char *typeName,
+                  Oid typeNamespace,
+                  Oid assignedTypeOid,
+                  Oid relationOid,             /* only for 'c'atalog typeType */
+                  char relationKind,   /* ditto */
                   int16 internalSize,
-                  int16 externalSize,
                   char typeType,
                   char typDelim,
-                  char *inputProcedure,
-                  char *outputProcedure,
-                  char *sendProcedure,
-                  char *receiveProcedure,
-                  char *elementTypeName,
-                  char *defaultTypeValue,              /* internal rep */
+                  Oid inputProcedure,
+                  Oid outputProcedure,
+                  Oid elementType,
+                  Oid baseType,
+                  const char *defaultTypeValue,                /* human readable rep */
+                  const char *defaultTypeBin,  /* cooked rep */
                   bool passedByValue,
-                  char alignment)
+                  char alignment,
+                  char storage,
+                  int32 typeMod,
+                  int32 typNDims,              /* Array dimensions for baseType */
+                  bool typeNotNull)
 {
-       register        i,
-                               j;
        Relation        pg_type_desc;
-       HeapScanDesc pg_type_scan;
-
        Oid                     typeObjectId;
-       Oid                     elementObjectId = InvalidOid;
-
        HeapTuple       tup;
        char            nulls[Natts_pg_type];
        char            replaces[Natts_pg_type];
        Datum           values[Natts_pg_type];
-
-       Buffer          buffer;
-       char       *procname;
-       char       *procs[4];
-       bool            defined;
-       ItemPointerData itemPointerData;
+       NameData        name;
        TupleDesc       tupDesc;
+       int                     i;
 
-       Oid                     argList[8];
-
-
-       static ScanKeyData typeKey[1] = {
-               {0, Anum_pg_type_typname, NameEqualRegProcedure}
-       };
-
-       fmgr_info(NameEqualRegProcedure,
-                         &typeKey[0].sk_func, &typeKey[0].sk_nargs);
-
-       /* ----------------
-        *      check that the type is not already defined.
-        * ----------------
-        */
-       typeObjectId = TypeGet(typeName, &defined);
-       if (OidIsValid(typeObjectId) && defined)
-       {
-               elog(WARN, "TypeCreate: type %s already defined", typeName);
-       }
-
-       /* ----------------
-        *      if this type has an associated elementType, then we check that
-        *      it is defined.
-        * ----------------
+       /*
+        * We assume that the caller validated the arguments individually, but
+        * did not check for bad combinations.
+        *
+        * Validate size specifications: either positive (fixed-length) or -1
+        * (varlena) or -2 (cstring).  Pass-by-value types must have a fixed
+        * length not more than sizeof(Datum).
         */
-       if (elementTypeName)
-       {
-               elementObjectId = TypeGet(elementTypeName, &defined);
-               if (!defined)
-               {
-                       elog(WARN, "TypeCreate: type %s is not defined", elementTypeName);
-               }
-       }
+       if (!(internalSize > 0 ||
+                 internalSize == -1 ||
+                 internalSize == -2))
+               elog(ERROR, "TypeCreate: invalid type internal size %d",
+                        internalSize);
+       if (passedByValue &&
+               (internalSize <= 0 || internalSize > (int16) sizeof(Datum)))
+               elog(ERROR, "TypeCreate: invalid type internal size %d",
+                        internalSize);
+
+       /* Only varlena types can be toasted */
+       if (storage != 'p' && internalSize != -1)
+               elog(ERROR, "TypeCreate: fixed size types must have storage PLAIN");
 
-       /* ----------------
-        *      XXX comment me
-        * ----------------
-        */
-       if (externalSize == 0)
-       {
-               externalSize = -1;              /* variable length */
-       }
-
-       /* ----------------
-        *      initialize arrays needed by FormHeapTuple
-        * ----------------
+       /*
+        * initialize arrays needed for heap_formtuple or heap_modifytuple
         */
        for (i = 0; i < Natts_pg_type; ++i)
        {
                nulls[i] = ' ';
                replaces[i] = 'r';
-               values[i] = (Datum) NULL;               /* redundant, but nice */
+               values[i] = (Datum) 0;
        }
 
        /*
-        * XXX
-        *
-        * Do this so that user-defined types have size -1 instead of zero if
-        * they are variable-length - this is so that everything else in the
-        * backend works.
-        */
-
-       if (internalSize == 0)
-               internalSize = -1;
-
-       /* ----------------
-        *      initialize the values[] information
-        * ----------------
+        * initialize the *values information
         */
        i = 0;
-       values[i++] = PointerGetDatum(typeName);        /* 1 */
-       values[i++] = (Datum) GetUserId();      /* 2 */
-       values[i++] = (Datum) internalSize; /* 3 */
-       values[i++] = (Datum) externalSize; /* 4 */
-       values[i++] = (Datum) passedByValue;            /* 5 */
-       values[i++] = (Datum) typeType;         /* 6 */
-       values[i++] = (Datum) (bool) 1;         /* 7 */
-       values[i++] = (Datum) typDelim;         /* 8 */
-       values[i++] = (Datum) (typeType == 'c' ? relationOid : InvalidOid); /* 9 */
-       values[i++] = (Datum) elementObjectId;          /* 10 */
+       namestrcpy(&name, typeName);
+       values[i++] = NameGetDatum(&name);      /* typname */
+       values[i++] = ObjectIdGetDatum(typeNamespace);          /* typnamespace */
+       values[i++] = Int32GetDatum(GetUserId());       /* typowner */
+       values[i++] = Int16GetDatum(internalSize);      /* typlen */
+       values[i++] = BoolGetDatum(passedByValue);      /* typbyval */
+       values[i++] = CharGetDatum(typeType);           /* typtype */
+       values[i++] = BoolGetDatum(true);       /* typisdefined */
+       values[i++] = CharGetDatum(typDelim);           /* typdelim */
+       values[i++] = ObjectIdGetDatum(typeType == 'c' ? relationOid : InvalidOid); /* typrelid */
+       values[i++] = ObjectIdGetDatum(elementType);            /* typelem */
+       values[i++] = ObjectIdGetDatum(inputProcedure);         /* typinput */
+       values[i++] = ObjectIdGetDatum(outputProcedure);        /* typoutput */
+       values[i++] = CharGetDatum(alignment);          /* typalign */
+       values[i++] = CharGetDatum(storage);            /* typstorage */
+       values[i++] = BoolGetDatum(typeNotNull);        /* typnotnull */
+       values[i++] = ObjectIdGetDatum(baseType);       /* typbasetype */
+       values[i++] = Int32GetDatum(typeMod);           /* typtypmod */
+       values[i++] = Int32GetDatum(typNDims);          /* typndims */
 
        /*
-        * arguments to type input and output functions must be 0
+        * initialize the default binary value for this type.  Check for nulls
+        * of course.
         */
-       MemSet(argList, 0, 8 * sizeof(Oid));
-
-       procs[0] = inputProcedure;
-       procs[1] = outputProcedure;
-       procs[2] = (receiveProcedure) ? receiveProcedure : inputProcedure;
-       procs[3] = (sendProcedure) ? sendProcedure : outputProcedure;
-
-       for (j = 0; j < 4; ++j)
-       {
-               procname = procs[j];
-
-               tup = SearchSysCacheTuple(PRONAME,
-                                                                 PointerGetDatum(procname),
-                                                                 Int32GetDatum(1),
-                                                                 PointerGetDatum(argList),
-                                                                 0);
-
-               if (!HeapTupleIsValid(tup))
-               {
-
-                       /*
-                        * it is possible for the input/output procedure to take two
-                        * arguments, where the second argument is the element type
-                        * (eg array_in/array_out)
-                        */
-                       if (OidIsValid(elementObjectId))
-                       {
-                               tup = SearchSysCacheTuple(PRONAME,
-                                                                                 PointerGetDatum(procname),
-                                                                                 Int32GetDatum(2),
-                                                                                 PointerGetDatum(argList),
-                                                                                 0);
-                       }
-                       if (!HeapTupleIsValid(tup))
-                       {
-                               func_error("TypeCreate", procname, 1, argList);
-                       }
-               }
-
-               values[i++] = (Datum) tup->t_oid;               /* 11 - 14 */
-       }
+       if (defaultTypeBin)
+               values[i] = DirectFunctionCall1(textin,
+                                                                               CStringGetDatum(defaultTypeBin));
+       else
+               nulls[i] = 'n';
+       i++;                                            /* typdefaultbin */
 
-       /* ----------------
-        * set default alignment
-        * ----------------
+       /*
+        * initialize the default value for this type.
         */
-       values[i++] = (Datum) alignment;        /* 15 */
+       if (defaultTypeValue)
+               values[i] = DirectFunctionCall1(textin,
+                                                                         CStringGetDatum(defaultTypeValue));
+       else
+               nulls[i] = 'n';
+       i++;                                            /* typdefault */
 
-       /* ----------------
-        *      initialize the default value for this type.
-        * ----------------
-        */
-       values[i] = (Datum) fmgr(TextInRegProcedure,            /* 16 */
-                                                        PointerIsValid(defaultTypeValue)
-                                                        ? defaultTypeValue : "-"); /* XXX default
-                                                                                                                * typdefault */
-
-       /* ----------------
-        *      open pg_type and begin a scan for the type name.
-        * ----------------
+       /*
+        * open pg_type and prepare to insert or update a row.
+        *
+        * NOTE: updating will not work correctly in bootstrap mode; but we don't
+        * expect to be overwriting any shell types in bootstrap mode.
         */
-       pg_type_desc = heap_openr(TypeRelationName);
+       pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
 
-       /* -----------------
-        * Set a write lock initially so as not upgrade a read to a write
-        * when the heap_insert() or heap_replace() is called.
-        * -----------------
-        */
-       RelationSetLockForWrite(pg_type_desc);
-
-       typeKey[0].sk_argument = PointerGetDatum(typeName);
-       pg_type_scan = heap_beginscan(pg_type_desc,
-                                                                 0,
-                                                                 SelfTimeQual,
-                                                                 1,
-                                                                 typeKey);
-
-       /* ----------------
-        *      define the type either by adding a tuple to the type
-        *      relation, or by updating the fields of the "shell" tuple
-        *      already there.
-        * ----------------
-        */
-       tup = heap_getnext(pg_type_scan, 0, &buffer);
+       tup = SearchSysCacheCopy(TYPENAMENSP,
+                                                        CStringGetDatum(typeName),
+                                                        ObjectIdGetDatum(typeNamespace),
+                                                        0, 0);
        if (HeapTupleIsValid(tup))
        {
+               /*
+                * check that the type is not already defined.  It may exist as a
+                * shell type, however (but only if assignedTypeOid is not given).
+                */
+               if (((Form_pg_type) GETSTRUCT(tup))->typisdefined ||
+                       assignedTypeOid != InvalidOid)
+                       elog(ERROR, "type %s already exists", typeName);
+
+               /*
+                * Okay to update existing "shell" type tuple
+                */
                tup = heap_modifytuple(tup,
-                                                          buffer,
                                                           pg_type_desc,
                                                           values,
                                                           nulls,
                                                           replaces);
 
-               /* XXX may not be necessary */
-               ItemPointerCopy(&tup->t_ctid, &itemPointerData);
+               simple_heap_update(pg_type_desc, &tup->t_self, tup);
 
-               setheapoverride(true);
-               heap_replace(pg_type_desc, &itemPointerData, tup);
-               setheapoverride(false);
-
-               typeObjectId = tup->t_oid;
+               typeObjectId = HeapTupleGetOid(tup);
        }
        else
        {
@@ -509,111 +277,159 @@ TypeCreate(char *typeName,
                                                         values,
                                                         nulls);
 
-               heap_insert(pg_type_desc, tup);
+               /* preassign tuple Oid, if one was given */
+               HeapTupleSetOid(tup, assignedTypeOid);
 
-               typeObjectId = tup->t_oid;
+               typeObjectId = simple_heap_insert(pg_type_desc, tup);
        }
 
-       /* ----------------
-        *      finish up
-        * ----------------
-        */
-       heap_endscan(pg_type_scan);
+       /* Update indexes */
+       CatalogUpdateIndexes(pg_type_desc, tup);
 
-       if (RelationGetRelationTupleForm(pg_type_desc)->relhasindex)
+       /*
+        * Create dependencies.  We can/must skip this in bootstrap mode.
+        */
+       if (!IsBootstrapProcessingMode())
        {
-               Relation        idescs[Num_pg_type_indices];
+               ObjectAddress myself,
+                                       referenced;
+
+               myself.classId = RelOid_pg_type;
+               myself.objectId = typeObjectId;
+               myself.objectSubId = 0;
+
+               /* dependency on namespace */
+               /* skip for relation rowtype, since we have indirect dependency */
+               if (!OidIsValid(relationOid))
+               {
+                       referenced.classId = get_system_catalog_relid(NamespaceRelationName);
+                       referenced.objectId = typeNamespace;
+                       referenced.objectSubId = 0;
+                       recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+               }
 
-               CatalogOpenIndices(Num_pg_type_indices, Name_pg_type_indices, idescs);
-               CatalogIndexInsert(idescs, Num_pg_type_indices, pg_type_desc, tup);
-               CatalogCloseIndices(Num_pg_type_indices, idescs);
+               /* Normal dependencies on the I/O functions */
+               referenced.classId = RelOid_pg_proc;
+               referenced.objectId = inputProcedure;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+               referenced.classId = RelOid_pg_proc;
+               referenced.objectId = outputProcedure;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+               /*
+                * If the type is a rowtype for a relation, mark it as internally
+                * dependent on the relation, *unless* it is a stand-alone
+                * composite type relation. For the latter case, we have to
+                * reverse the dependency.
+                *
+                * In the former case, this allows the type to be auto-dropped when
+                * the relation is, and not otherwise. And in the latter, of
+                * course we get the opposite effect.
+                */
+               if (OidIsValid(relationOid))
+               {
+                       referenced.classId = RelOid_pg_class;
+                       referenced.objectId = relationOid;
+                       referenced.objectSubId = 0;
+
+                       if (relationKind != RELKIND_COMPOSITE_TYPE)
+                               recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
+                       else
+                               recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
+               }
+
+               /*
+                * If the type is an array type, mark it auto-dependent on the
+                * base type.  (This is a compromise between the typical case
+                * where the array type is automatically generated and the case
+                * where it is manually created: we'd prefer INTERNAL for the
+                * former case and NORMAL for the latter.)
+                */
+               if (OidIsValid(elementType))
+               {
+                       referenced.classId = RelOid_pg_type;
+                       referenced.objectId = elementType;
+                       referenced.objectSubId = 0;
+                       recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
+               }
+
+               /* Normal dependency from a domain to its base type. */
+               if (OidIsValid(baseType))
+               {
+                       referenced.classId = RelOid_pg_type;
+                       referenced.objectId = baseType;
+                       referenced.objectSubId = 0;
+                       recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+               }
        }
-       RelationUnsetLockForWrite(pg_type_desc);
-       heap_close(pg_type_desc);
 
+       /*
+        * finish up
+        */
+       heap_close(pg_type_desc, RowExclusiveLock);
 
-       return
-               typeObjectId;
+       return typeObjectId;
 }
 
-/* ----------------------------------------------------------------
- *             TypeRename
- *
+/*
+ * TypeRename
  *             This renames a type
- * ----------------------------------------------------------------
+ *
+ * Note: any associated array type is *not* renamed; caller must make
+ * another call to handle that case.  Currently this is only used for
+ * renaming types associated with tables, for which there are no arrays.
  */
 void
-TypeRename(char *oldTypeName, char *newTypeName)
+TypeRename(const char *oldTypeName, Oid typeNamespace,
+                  const char *newTypeName)
 {
        Relation        pg_type_desc;
-       Relation        idescs[Num_pg_type_indices];
-       Oid                     type_oid;
-       HeapTuple       tup;
-       bool            defined;
-       ItemPointerData itemPointerData;
+       HeapTuple       tuple;
 
-       /* check that that the new type is not already defined */
-       type_oid = TypeGet(newTypeName, &defined);
-       if (OidIsValid(type_oid) && defined)
-       {
-               elog(WARN, "TypeRename: type %s already defined", newTypeName);
-       }
+       pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
 
-       /* get the type tuple from the catalog index scan manager */
-       pg_type_desc = heap_openr(TypeRelationName);
-       tup = TypeNameIndexScan(pg_type_desc, oldTypeName);
+       tuple = SearchSysCacheCopy(TYPENAMENSP,
+                                                          CStringGetDatum(oldTypeName),
+                                                          ObjectIdGetDatum(typeNamespace),
+                                                          0, 0);
+       if (!HeapTupleIsValid(tuple))
+               elog(ERROR, "type %s does not exist", oldTypeName);
 
-       /* ----------------
-        *      change the name of the type
-        * ----------------
-        */
-       if (HeapTupleIsValid(tup))
-       {
+       if (SearchSysCacheExists(TYPENAMENSP,
+                                                        CStringGetDatum(newTypeName),
+                                                        ObjectIdGetDatum(typeNamespace),
+                                                        0, 0))
+               elog(ERROR, "type named %s already exists", newTypeName);
 
-               namestrcpy(&(((TypeTupleForm) GETSTRUCT(tup))->typname), newTypeName);
+       namestrcpy(&(((Form_pg_type) GETSTRUCT(tuple))->typname), newTypeName);
 
-               ItemPointerCopy(&tup->t_ctid, &itemPointerData);
+       simple_heap_update(pg_type_desc, &tuple->t_self, tuple);
 
-               setheapoverride(true);
-               heap_replace(pg_type_desc, &itemPointerData, tup);
-               setheapoverride(false);
+       /* update the system catalog indexes */
+       CatalogUpdateIndexes(pg_type_desc, tuple);
 
-               /* update the system catalog indices */
-               CatalogOpenIndices(Num_pg_type_indices, Name_pg_type_indices, idescs);
-               CatalogIndexInsert(idescs, Num_pg_type_indices, pg_type_desc, tup);
-               CatalogCloseIndices(Num_pg_type_indices, idescs);
-
-               /* all done */
-               pfree(tup);
-
-       }
-       else
-       {
-               elog(WARN, "TypeRename: type %s not defined", oldTypeName);
-       }
-
-       /* finish up */
-       heap_close(pg_type_desc);
+       heap_freetuple(tuple);
+       heap_close(pg_type_desc, RowExclusiveLock);
 }
 
 /*
  * makeArrayTypeName(typeName);
  *       - given a base type name, make an array of type name out of it
  *
- * the CALLER is responsible for pfreeing the
+ * the caller is responsible for pfreeing the result
  */
-
-char      *
-makeArrayTypeName(char *typeName)
+char *
+makeArrayTypeName(const char *typeName)
 {
        char       *arr;
 
        if (!typeName)
                return NULL;
-       arr = palloc(strlen(typeName) + 2);
-       arr[0] = '_';
-       strcpy(arr + 1, typeName);
-
+       arr = palloc(NAMEDATALEN);
+       snprintf(arr, NAMEDATALEN,
+                        "_%.*s", NAMEDATALEN - 2, typeName);
        return arr;
-
 }