]> granicus.if.org Git - postgresql/blobdiff - src/backend/catalog/pg_type.c
Standard pgindent run for 8.1.
[postgresql] / src / backend / catalog / pg_type.c
index 476bfa61be659e6a15531d6d5619d17b5603517a..ab250b02ea9aa77246e85f1f05693507e51b0be1 100644 (file)
@@ -3,21 +3,22 @@
  * pg_type.c
  *       routines to support manipulation of the pg_type relation
  *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2005, 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.85 2002/12/06 05:00:10 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.104 2005/10/15 02:49:14 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
 #include "access/heapam.h"
-#include "catalog/catname.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
 #include "miscadmin.h"
 #include "utils/builtins.h"
@@ -55,7 +56,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace)
        /*
         * open pg_type
         */
-       pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
+       pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);
        tupDesc = pg_type_desc->rd_att;
 
        /*
@@ -74,7 +75,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace)
        namestrcpy(&name, typeName);
        values[i++] = NameGetDatum(&name);      /* typname */
        values[i++] = ObjectIdGetDatum(typeNamespace);          /* typnamespace */
-       values[i++] = ObjectIdGetDatum(InvalidOid); /* typowner */
+       values[i++] = ObjectIdGetDatum(GetUserId());            /* typowner */
        values[i++] = Int16GetDatum(0);         /* typlen */
        values[i++] = BoolGetDatum(false);      /* typbyval */
        values[i++] = CharGetDatum(0);          /* typtype */
@@ -84,6 +85,9 @@ TypeShellMake(const char *typeName, Oid typeNamespace)
        values[i++] = ObjectIdGetDatum(InvalidOid); /* typelem */
        values[i++] = ObjectIdGetDatum(InvalidOid); /* typinput */
        values[i++] = ObjectIdGetDatum(InvalidOid); /* typoutput */
+       values[i++] = ObjectIdGetDatum(InvalidOid); /* typreceive */
+       values[i++] = ObjectIdGetDatum(InvalidOid); /* typsend */
+       values[i++] = ObjectIdGetDatum(InvalidOid); /* typanalyze */
        values[i++] = CharGetDatum('i');        /* typalign */
        values[i++] = CharGetDatum('p');        /* typstorage */
        values[i++] = BoolGetDatum(false);      /* typnotnull */
@@ -105,6 +109,25 @@ TypeShellMake(const char *typeName, Oid typeNamespace)
 
        CatalogUpdateIndexes(pg_type_desc, tup);
 
+       /*
+        * Create dependencies.  We can/must skip this in bootstrap mode.
+        */
+       if (!IsBootstrapProcessingMode())
+               GenerateTypeDependencies(typeNamespace,
+                                                                typoid,
+                                                                InvalidOid,
+                                                                0,
+                                                                GetUserId(),
+                                                                InvalidOid,
+                                                                InvalidOid,
+                                                                InvalidOid,
+                                                                InvalidOid,
+                                                                InvalidOid,
+                                                                InvalidOid,
+                                                                InvalidOid,
+                                                                NULL,
+                                                                false);
+
        /*
         * clean up and return the type-oid
         */
@@ -119,23 +142,22 @@ TypeShellMake(const char *typeName, Oid typeNamespace)
  *
  *             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.
+ *             Returns the OID assigned to the new type.
  * ----------------------------------------------------------------
  */
 Oid
 TypeCreate(const char *typeName,
                   Oid typeNamespace,
-                  Oid assignedTypeOid,
-                  Oid relationOid,             /* only for 'c'atalog typeType */
+                  Oid relationOid,             /* only for 'c'atalog types */
                   char relationKind,   /* ditto */
                   int16 internalSize,
                   char typeType,
                   char typDelim,
                   Oid inputProcedure,
                   Oid outputProcedure,
+                  Oid receiveProcedure,
+                  Oid sendProcedure,
+                  Oid analyzeProcedure,
                   Oid elementType,
                   Oid baseType,
                   const char *defaultTypeValue,                /* human readable rep */
@@ -149,17 +171,17 @@ TypeCreate(const char *typeName,
 {
        Relation        pg_type_desc;
        Oid                     typeObjectId;
+       bool            rebuildDeps = false;
        HeapTuple       tup;
        char            nulls[Natts_pg_type];
        char            replaces[Natts_pg_type];
        Datum           values[Natts_pg_type];
        NameData        name;
-       TupleDesc       tupDesc;
        int                     i;
 
        /*
-        * We assume that the caller validated the arguments individually, but
-        * did not check for bad combinations.
+        * 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
@@ -168,16 +190,22 @@ TypeCreate(const char *typeName,
        if (!(internalSize > 0 ||
                  internalSize == -1 ||
                  internalSize == -2))
-               elog(ERROR, "TypeCreate: invalid type internal size %d",
-                        internalSize);
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                errmsg("invalid type internal size %d",
+                                               internalSize)));
        if (passedByValue &&
                (internalSize <= 0 || internalSize > (int16) sizeof(Datum)))
-               elog(ERROR, "TypeCreate: invalid type internal size %d",
-                        internalSize);
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                          errmsg("internal size %d is invalid for passed-by-value type",
+                                         internalSize)));
 
        /* Only varlena types can be toasted */
        if (storage != 'p' && internalSize != -1)
-               elog(ERROR, "TypeCreate: fixed size types must have storage PLAIN");
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                errmsg("fixed-size types must have storage PLAIN")));
 
        /*
         * initialize arrays needed for heap_formtuple or heap_modifytuple
@@ -196,7 +224,7 @@ TypeCreate(const char *typeName,
        namestrcpy(&name, typeName);
        values[i++] = NameGetDatum(&name);      /* typname */
        values[i++] = ObjectIdGetDatum(typeNamespace);          /* typnamespace */
-       values[i++] = Int32GetDatum(GetUserId());       /* typowner */
+       values[i++] = ObjectIdGetDatum(GetUserId());            /* typowner */
        values[i++] = Int16GetDatum(internalSize);      /* typlen */
        values[i++] = BoolGetDatum(passedByValue);      /* typbyval */
        values[i++] = CharGetDatum(typeType);           /* typtype */
@@ -206,6 +234,9 @@ TypeCreate(const char *typeName,
        values[i++] = ObjectIdGetDatum(elementType);            /* typelem */
        values[i++] = ObjectIdGetDatum(inputProcedure);         /* typinput */
        values[i++] = ObjectIdGetDatum(outputProcedure);        /* typoutput */
+       values[i++] = ObjectIdGetDatum(receiveProcedure);       /* typreceive */
+       values[i++] = ObjectIdGetDatum(sendProcedure);          /* typsend */
+       values[i++] = ObjectIdGetDatum(analyzeProcedure);       /* typanalyze */
        values[i++] = CharGetDatum(alignment);          /* typalign */
        values[i++] = CharGetDatum(storage);            /* typstorage */
        values[i++] = BoolGetDatum(typeNotNull);        /* typnotnull */
@@ -214,8 +245,8 @@ TypeCreate(const char *typeName,
        values[i++] = Int32GetDatum(typNDims);          /* typndims */
 
        /*
-        * initialize the default binary value for this type.  Check for nulls
-        * of course.
+        * initialize the default binary value for this type.  Check for nulls of
+        * course.
         */
        if (defaultTypeBin)
                values[i] = DirectFunctionCall1(textin,
@@ -229,7 +260,7 @@ TypeCreate(const char *typeName,
         */
        if (defaultTypeValue)
                values[i] = DirectFunctionCall1(textin,
-                                                                         CStringGetDatum(defaultTypeValue));
+                                                                               CStringGetDatum(defaultTypeValue));
        else
                nulls[i] = 'n';
        i++;                                            /* typdefault */
@@ -240,7 +271,7 @@ TypeCreate(const char *typeName,
         * 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, RowExclusiveLock);
+       pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);
 
        tup = SearchSysCacheCopy(TYPENAMENSP,
                                                         CStringGetDatum(typeName),
@@ -250,17 +281,18 @@ TypeCreate(const char *typeName,
        {
                /*
                 * check that the type is not already defined.  It may exist as a
-                * shell type, however (but only if assignedTypeOid is not given).
+                * shell type, however.
                 */
-               if (((Form_pg_type) GETSTRUCT(tup))->typisdefined ||
-                       assignedTypeOid != InvalidOid)
-                       elog(ERROR, "type %s already exists", typeName);
+               if (((Form_pg_type) GETSTRUCT(tup))->typisdefined)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_DUPLICATE_OBJECT),
+                                        errmsg("type \"%s\" already exists", typeName)));
 
                /*
                 * Okay to update existing "shell" type tuple
                 */
                tup = heap_modifytuple(tup,
-                                                          pg_type_desc,
+                                                          RelationGetDescr(pg_type_desc),
                                                           values,
                                                           nulls,
                                                           replaces);
@@ -268,18 +300,15 @@ TypeCreate(const char *typeName,
                simple_heap_update(pg_type_desc, &tup->t_self, tup);
 
                typeObjectId = HeapTupleGetOid(tup);
+
+               rebuildDeps = true;             /* get rid of shell type's dependencies */
        }
        else
        {
-               tupDesc = pg_type_desc->rd_att;
-
-               tup = heap_formtuple(tupDesc,
+               tup = heap_formtuple(RelationGetDescr(pg_type_desc),
                                                         values,
                                                         nulls);
 
-               /* preassign tuple Oid, if one was given */
-               HeapTupleSetOid(tup, assignedTypeOid);
-
                typeObjectId = simple_heap_insert(pg_type_desc, tup);
        }
 
@@ -290,18 +319,22 @@ TypeCreate(const char *typeName,
         * Create dependencies.  We can/must skip this in bootstrap mode.
         */
        if (!IsBootstrapProcessingMode())
-       {
                GenerateTypeDependencies(typeNamespace,
                                                                 typeObjectId,
                                                                 relationOid,
                                                                 relationKind,
+                                                                GetUserId(),
                                                                 inputProcedure,
                                                                 outputProcedure,
+                                                                receiveProcedure,
+                                                                sendProcedure,
+                                                                analyzeProcedure,
                                                                 elementType,
                                                                 baseType,
-                                                                defaultTypeBin,
-                                                                false);
-       }
+                                                                (defaultTypeBin ?
+                                                                 stringToNode(defaultTypeBin) :
+                                                                 NULL),
+                                                                rebuildDeps);
 
        /*
         * finish up
@@ -311,31 +344,41 @@ TypeCreate(const char *typeName,
        return typeObjectId;
 }
 
+/*
+ * GenerateTypeDependencies: build the dependencies needed for a type
+ *
+ * If rebuild is true, we remove existing dependencies and rebuild them
+ * from scratch.  This is needed for ALTER TYPE, and also when replacing
+ * a shell type.
+ *
+ * NOTE: a shell type will have a dependency to its namespace, and no others.
+ */
 void
 GenerateTypeDependencies(Oid typeNamespace,
                                                 Oid typeObjectId,
-                                                Oid relationOid,               /* only for 'c'atalog typeType */
-                                                char relationKind,
+                                                Oid relationOid,               /* only for 'c'atalog types */
+                                                char relationKind,             /* ditto */
+                                                Oid owner,
                                                 Oid inputProcedure,
                                                 Oid outputProcedure,
+                                                Oid receiveProcedure,
+                                                Oid sendProcedure,
+                                                Oid analyzeProcedure,
                                                 Oid elementType,
                                                 Oid baseType,
-                                                char *defaultTypeBin,  /* cooked rep */
+                                                Node *defaultExpr,
                                                 bool rebuild)
 {
        ObjectAddress myself,
                                referenced;
 
-       /*
-        * If true, we need to remove all current dependencies that the type
-        * holds, and rebuild them from scratch.  This allows us to easily 
-        * implement alter type, and alter domain statements.
-        */
        if (rebuild)
-               deleteDependencyRecordsFor(RelOid_pg_type,
-                                                                  typeObjectId);
+       {
+               deleteDependencyRecordsFor(TypeRelationId, typeObjectId);
+               deleteSharedDependencyRecordsFor(TypeRelationId, typeObjectId);
+       }
 
-       myself.classId = RelOid_pg_type;
+       myself.classId = TypeRelationId;
        myself.objectId = typeObjectId;
        myself.objectSubId = 0;
 
@@ -343,36 +386,65 @@ GenerateTypeDependencies(Oid typeNamespace,
        /* skip for relation rowtype, since we have indirect dependency */
        if (!OidIsValid(relationOid))
        {
-               referenced.classId = get_system_catalog_relid(NamespaceRelationName);
+               referenced.classId = NamespaceRelationId;
                referenced.objectId = typeNamespace;
                referenced.objectSubId = 0;
                recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
        }
 
        /* Normal dependencies on the I/O functions */
-       referenced.classId = RelOid_pg_proc;
-       referenced.objectId = inputProcedure;
-       referenced.objectSubId = 0;
-       recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+       if (OidIsValid(inputProcedure))
+       {
+               referenced.classId = ProcedureRelationId;
+               referenced.objectId = inputProcedure;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+       }
+
+       if (OidIsValid(outputProcedure))
+       {
+               referenced.classId = ProcedureRelationId;
+               referenced.objectId = outputProcedure;
+               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 (OidIsValid(receiveProcedure))
+       {
+               referenced.classId = ProcedureRelationId;
+               referenced.objectId = receiveProcedure;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+       }
+
+       if (OidIsValid(sendProcedure))
+       {
+               referenced.classId = ProcedureRelationId;
+               referenced.objectId = sendProcedure;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+       }
+
+       if (OidIsValid(analyzeProcedure))
+       {
+               referenced.classId = ProcedureRelationId;
+               referenced.objectId = analyzeProcedure;
+               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.
+        * 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.
+        * 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.classId = RelationRelationId;
                referenced.objectId = relationOid;
                referenced.objectSubId = 0;
 
@@ -383,15 +455,14 @@ GenerateTypeDependencies(Oid typeNamespace,
        }
 
        /*
-        * 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 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.classId = TypeRelationId;
                referenced.objectId = elementType;
                referenced.objectSubId = 0;
                recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
@@ -400,16 +471,18 @@ GenerateTypeDependencies(Oid typeNamespace,
        /* Normal dependency from a domain to its base type. */
        if (OidIsValid(baseType))
        {
-               referenced.classId = RelOid_pg_type;
+               referenced.classId = TypeRelationId;
                referenced.objectId = baseType;
                referenced.objectSubId = 0;
                recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
        }
 
-       /* Dependency on the default expression */
-       if (defaultTypeBin)
-               recordDependencyOnExpr(&myself, stringToNode(defaultTypeBin),
-                                                          NIL, DEPENDENCY_NORMAL);
+       /* Normal dependency on the default expression. */
+       if (defaultExpr)
+               recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);
+
+       /* Shared dependency on owner. */
+       recordDependencyOnOwner(TypeRelationId, typeObjectId, owner);
 }
 
 /*
@@ -427,20 +500,24 @@ TypeRename(const char *oldTypeName, Oid typeNamespace,
        Relation        pg_type_desc;
        HeapTuple       tuple;
 
-       pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
+       pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);
 
        tuple = SearchSysCacheCopy(TYPENAMENSP,
                                                           CStringGetDatum(oldTypeName),
                                                           ObjectIdGetDatum(typeNamespace),
                                                           0, 0);
        if (!HeapTupleIsValid(tuple))
-               elog(ERROR, "type %s does not exist", oldTypeName);
+               ereport(ERROR,
+                               (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                errmsg("type \"%s\" does not exist", oldTypeName)));
 
        if (SearchSysCacheExists(TYPENAMENSP,
                                                         CStringGetDatum(newTypeName),
                                                         ObjectIdGetDatum(typeNamespace),
                                                         0, 0))
-               elog(ERROR, "type named %s already exists", newTypeName);
+               ereport(ERROR,
+                               (errcode(ERRCODE_DUPLICATE_OBJECT),
+                                errmsg("type \"%s\" already exists", newTypeName)));
 
        namestrcpy(&(((Form_pg_type) GETSTRUCT(tuple))->typname), newTypeName);