]> granicus.if.org Git - postgresql/commitdiff
Rearrange order of operations in heap_create_with_catalog so that if
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 12 Feb 2001 20:07:21 +0000 (20:07 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 12 Feb 2001 20:07:21 +0000 (20:07 +0000)
two transactions create the same table name concurrently, the one that
fails will complain about unique index pg_class_relname_index, rather than
about pg_type_typname_index which'll confuse most people.  Free side
benefit: pg_class.reltype is correctly linked to the pg_type entry now.
It's been zero in all but the preloaded pg_class entries since who knows
when.

src/backend/catalog/heap.c
src/backend/catalog/pg_type.c
src/backend/commands/define.c
src/include/catalog/pg_type.h

index bdb32b5dccffb23c1c9e62e136170131f3dbf759..c67f7f35436827a0bfc0038976b88b66214fa6c3 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.158 2001/01/24 19:42:51 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.159 2001/02/12 20:07:21 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
 
 
 static void AddNewRelationTuple(Relation pg_class_desc,
-                                       Relation new_rel_desc, Oid new_rel_oid,
-                                       int natts,
-                                       char relkind, char *temp_relname);
+                                       Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid,
+                                       int natts, char relkind, char *temp_relname);
 static void DeleteAttributeTuples(Relation rel);
 static void DeleteRelationTuple(Relation rel);
 static void DeleteTypeTuple(Relation rel);
 static void RelationRemoveIndexes(Relation relation);
 static void RelationRemoveInheritance(Relation relation);
-static void AddNewRelationType(char *typeName, Oid new_rel_oid);
+static void AddNewRelationType(char *typeName, Oid new_rel_oid,
+                                                          Oid new_type_oid);
 static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin,
                                 bool updatePgAttribute);
 static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
@@ -317,6 +317,7 @@ heap_create(char *relname,
        strcpy(RelationGetPhysicalRelationName(rel), relname);
        rel->rd_rel->relkind = RELKIND_UNCATALOGED;
        rel->rd_rel->relnatts = natts;
+       rel->rd_rel->reltype = InvalidOid;
        if (tupDesc->constr)
                rel->rd_rel->relchecks = tupDesc->constr->num_check;
 
@@ -325,12 +326,6 @@ heap_create(char *relname,
 
        RelationGetRelid(rel) = relid;
 
-       if (nailme)
-       {
-               /* for system relations, set the reltype field here */
-               rel->rd_rel->reltype = relid;
-       }
-
        rel->rd_node.tblNode = tblNode;
        rel->rd_node.relNode = relid;
        rel->rd_rel->relfilenode = relid;
@@ -373,18 +368,17 @@ heap_storage_create(Relation rel)
  *                performs a scan to ensure that no relation with the
  *                same name already exists.
  *
- *             3) heap_create_with_catalog() is called to create the new relation
- *                on disk.
+ *             3) heap_create() is called to create the new relation on disk.
  *
- *             4) TypeDefine() is called to define a new type corresponding
+ *             4) AddNewRelationTuple() is called to register the
+ *                relation in pg_class.
+ *
+ *             5) TypeCreate() is called to define a new type corresponding
  *                to the new relation.
  *
- *             5) AddNewAttributeTuples() is called to register the
+ *             6) AddNewAttributeTuples() is called to register the
  *                new relation's schema in pg_attribute.
  *
- *             6) AddNewRelationTuple() is called to register the
- *                relation itself in the catalogs.
- *
  *             7) StoreConstraints is called ()                - vadim 08/22/97
  *
  *             8) the relations are closed and the new relation's oid
@@ -656,6 +650,7 @@ static void
 AddNewRelationTuple(Relation pg_class_desc,
                                        Relation new_rel_desc,
                                        Oid new_rel_oid,
+                                       Oid new_type_oid,
                                        int natts,
                                        char relkind,
                                        char *temp_relname)
@@ -665,7 +660,7 @@ AddNewRelationTuple(Relation pg_class_desc,
        Relation        idescs[Num_pg_class_indices];
 
        /* ----------------
-        *      first we munge some of the information in our
+        *      first we update some of the information in our
         *      uncataloged relation's relation descriptor.
         * ----------------
         */
@@ -694,6 +689,7 @@ AddNewRelationTuple(Relation pg_class_desc,
        new_rel_reltup->reltuples = 1000;
 
        new_rel_reltup->relowner = GetUserId();
+       new_rel_reltup->reltype = new_type_oid;
        new_rel_reltup->relkind = relkind;
        new_rel_reltup->relnatts = natts;
 
@@ -705,6 +701,8 @@ AddNewRelationTuple(Relation pg_class_desc,
        tup = heap_addheader(Natts_pg_class_fixed,
                                                 CLASS_TUPLE_SIZE,
                                                 (char *) new_rel_reltup);
+
+       /* force tuple to have the desired OID */
        tup->t_data->t_oid = new_rel_oid;
 
        /*
@@ -738,10 +736,8 @@ AddNewRelationTuple(Relation pg_class_desc,
  * --------------------------------
  */
 static void
-AddNewRelationType(char *typeName, Oid new_rel_oid)
+AddNewRelationType(char *typeName, Oid new_rel_oid, Oid new_type_oid)
 {
-       Oid                     new_type_oid;
-
        /*
         * The sizes are set to oid size because it makes implementing sets
         * MUCH easier, and no one (we hope) uses these fields to figure out
@@ -750,23 +746,25 @@ AddNewRelationType(char *typeName, Oid new_rel_oid)
         * actually get is the oid of a tuple in the pg_proc catalog, so the
         * size of the "set" is the size of an oid. Similarly, byval being
         * true makes sets much easier, and it isn't used by anything else.
-        * Note the assumption that OIDs are the same size as int4s.
-        */
-       new_type_oid = TypeCreate(typeName, /* type name */
-                                                         new_rel_oid,          /* relation oid */
-                                                         sizeof(Oid),          /* internal size */
-                                                         sizeof(Oid),          /* external size */
-                                                         'c',          /* type-type (catalog) */
-                                                         ',',          /* default array delimiter */
-                                                         "int4in", /* input procedure */
-                                                         "int4out",            /* output procedure */
-                                                         "int4in", /* receive procedure */
-                                                         "int4out",            /* send procedure */
-                                                         NULL,         /* array element type - irrelevent */
-                                                         "-",          /* default type value */
-                                                         (bool) 1, /* passed by value */
-                                                         'i',          /* default alignment */
-                                                         'p');         /* Not TOASTable */
+        *
+        * XXX Note the assumption that OIDs are the same size as int4s.
+        */
+       TypeCreate(typeName,            /* type name */
+                          new_type_oid,        /* preassigned oid for type */
+                          new_rel_oid,         /* relation oid */
+                          sizeof(Oid),         /* internal size */
+                          sizeof(Oid),         /* external size */
+                          'c',                         /* type-type (catalog) */
+                          ',',                         /* default array delimiter */
+                          "int4in",            /* input procedure */
+                          "int4out",           /* output procedure */
+                          "int4in",            /* receive procedure */
+                          "int4out",           /* send procedure */
+                          NULL,                        /* array element type - irrelevant */
+                          "-",                         /* default type value */
+                          true,                        /* passed by value */
+                          'i',                         /* default alignment */
+                          'p');                        /* Not TOASTable */
 }
 
 /* --------------------------------
@@ -785,6 +783,7 @@ heap_create_with_catalog(char *relname,
        Relation        pg_class_desc;
        Relation        new_rel_desc;
        Oid                     new_rel_oid;
+       Oid                     new_type_oid;
        int                     natts = tupdesc->natts;
        char       *temp_relname = NULL;
 
@@ -814,18 +813,10 @@ heap_create_with_catalog(char *relname,
        }
 
        /* ----------------
-        *      RelnameFindRelid couldn't detect simultaneous
-        *      creation. Uniqueness will be really checked by unique
-        *      indexes of system tables but we couldn't check it here.
-        *      We have to postpone creating the disk file for this
-        *      relation.
-        *      Another boolean parameter "storage_create" was added
-        *      to heap_create() function. If the parameter is false
-        *      heap_create() only registers an uncataloged relation
-        *      to relation cache and heap_storage_create() should be
-        *      called later.
-        *      We could pull its relation oid from the newly formed
-        *      relation descriptor.
+        *      Tell heap_create not to create a physical file; we'll do that
+        *      below after all our catalog updates are done.  (This isn't really
+        *      necessary anymore, but we may as well avoid the cycles of creating
+        *      and deleting the file in case we fail.)
         *
         *      Note: The call to heap_create() changes relname for
         *      temp tables; it becomes the true physical relname.
@@ -836,24 +827,18 @@ heap_create_with_catalog(char *relname,
        new_rel_desc = heap_create(relname, tupdesc, istemp, false,
                                                           allow_system_table_mods);
 
+       /* Fetch the relation OID assigned by heap_create */
        new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid;
 
-       /* ----------------
-        *      since defining a relation also defines a complex type,
-        *      we add a new system type corresponding to the new relation.
-        * ----------------
-        */
-       AddNewRelationType(relname, new_rel_oid);
+       /* Assign an OID for the relation's tuple type */
+       new_type_oid = newoid();
 
        /* ----------------
-        *      now add tuples to pg_attribute for the attributes in
-        *      our new relation.
-        * ----------------
-        */
-       AddNewAttributeTuples(new_rel_oid, tupdesc);
-
-       /* ----------------
-        *      now update the information in pg_class.
+        *      now create an entry in pg_class for the relation.
+        *
+        *      NOTE: we could get a unique-index failure here, in case someone else
+        *      is creating the same relation name in parallel but hadn't committed
+        *      yet when we checked for a duplicate name above.
         * ----------------
         */
        pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
@@ -861,10 +846,28 @@ heap_create_with_catalog(char *relname,
        AddNewRelationTuple(pg_class_desc,
                                                new_rel_desc,
                                                new_rel_oid,
+                                               new_type_oid,
                                                natts,
                                                relkind,
                                                temp_relname);
 
+       /* ----------------
+        *      since defining a relation also defines a complex type,
+        *      we add a new system type corresponding to the new relation.
+        *
+        *      NOTE: we could get a unique-index failure here, in case the same name
+        *      has already been used for a type.
+        * ----------------
+        */
+       AddNewRelationType(relname, new_rel_oid, new_type_oid);
+
+       /* ----------------
+        *      now add tuples to pg_attribute for the attributes in
+        *      our new relation.
+        * ----------------
+        */
+       AddNewAttributeTuples(new_rel_oid, tupdesc);
+
        StoreConstraints(new_rel_desc);
 
        if (istemp)
@@ -912,7 +915,6 @@ heap_create_with_catalog(char *relname,
  *             attribute catalog (needed?).  (Anything else?)
  *
  *             get proper relation from relation catalog (if not arg)
- *             check if relation is vital (strcmp()/reltype?)
  *             scan attribute catalog deleting attributes of reldesc
  *                             (necessary?)
  *             delete relation from relation catalog
index f94171748553b8e28f31fa0232e5d5e2d6918764..714ea737aecb9f0866d780febd2edec8943154c1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.58 2001/01/24 19:42:52 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.59 2001/02/12 20:07:21 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -46,18 +46,17 @@ TypeGetWithOpenRelation(Relation pg_type_desc,
        HeapScanDesc scan;
        HeapTuple       tup;
        Oid                     typoid;
-
-       static ScanKeyData typeKey[1] = {
-               {0, Anum_pg_type_typname, F_NAMEEQ}
-       };
+       ScanKeyData typeKey[1];
 
        /* ----------------
         *      initialize the scan key and begin a scan of pg_type
         * ----------------
         */
-       fmgr_info(F_NAMEEQ, &typeKey[0].sk_func);
-       typeKey[0].sk_nargs = typeKey[0].sk_func.fn_nargs;
-       typeKey[0].sk_argument = PointerGetDatum(typeName);
+       ScanKeyEntryInitialize(typeKey,
+                                                  0,
+                                                  Anum_pg_type_typname,
+                                                  F_NAMEEQ,
+                                                  PointerGetDatum(typeName));
 
        scan = heap_beginscan(pg_type_desc,
                                                  0,
@@ -269,10 +268,16 @@ TypeShellMake(char *typeName)
  *             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 assignedTypeOid,
                   Oid relationOid,             /* only for 'c'atalog typeTypes */
                   int16 internalSize,
                   int16 externalSize,
@@ -292,35 +297,28 @@ TypeCreate(char *typeName,
                                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];
-
        char       *procname;
        char       *procs[4];
        bool            defined;
        NameData        name;
        TupleDesc       tupDesc;
        Oid                     argList[FUNC_MAX_ARGS];
-
-       static ScanKeyData typeKey[1] = {
-               {0, Anum_pg_type_typname, F_NAMEEQ}
-       };
-
-       fmgr_info(F_NAMEEQ, &typeKey[0].sk_func);
-       typeKey[0].sk_nargs = typeKey[0].sk_func.fn_nargs;
+       ScanKeyData typeKey[1];
 
        /* ----------------
-        *      check that the type is not already defined.
+        *      check that the type is not already defined.  It might exist as
+        *      a shell type, however (but only if assignedTypeOid is not given).
         * ----------------
         */
        typeObjectId = TypeGet(typeName, &defined);
-       if (OidIsValid(typeObjectId) && defined)
+       if (OidIsValid(typeObjectId) &&
+               (defined || assignedTypeOid != InvalidOid))
                elog(ERROR, "TypeCreate: type %s already defined", typeName);
 
        /* ----------------
@@ -468,7 +466,12 @@ TypeCreate(char *typeName,
         */
        pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
 
-       typeKey[0].sk_argument = PointerGetDatum(typeName);
+       ScanKeyEntryInitialize(typeKey,
+                                                  0,
+                                                  Anum_pg_type_typname,
+                                                  F_NAMEEQ,
+                                                  PointerGetDatum(typeName));
+
        pg_type_scan = heap_beginscan(pg_type_desc,
                                                                  0,
                                                                  SnapshotSelf, /* cache? */
@@ -484,6 +487,10 @@ TypeCreate(char *typeName,
        tup = heap_getnext(pg_type_scan, 0);
        if (HeapTupleIsValid(tup))
        {
+               /* should not happen given prior test? */
+               if (assignedTypeOid != InvalidOid)
+                       elog(ERROR, "TypeCreate: type %s already defined", typeName);
+
                tup = heap_modifytuple(tup,
                                                           pg_type_desc,
                                                           values,
@@ -502,6 +509,9 @@ TypeCreate(char *typeName,
                                                         values,
                                                         nulls);
 
+               /* preassign tuple Oid, if one was given */
+               tup->t_data->t_oid = assignedTypeOid;
+
                heap_insert(pg_type_desc, tup);
 
                typeObjectId = tup->t_data->t_oid;
index 01fd53a16a9111e3b7873ea17f4b0448634ed9f4..4f5f8a47f64edfdbccf109795fd70051b577ecda 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.51 2001/01/24 19:42:52 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.52 2001/02/12 20:07:21 tgl Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
@@ -640,6 +640,7 @@ DefineType(char *typeName, List *parameters)
         * ----------------
         */
        TypeCreate(typeName,            /* type name */
+                          InvalidOid,          /* preassigned type oid (not done here) */
                           InvalidOid,          /* relation oid (n/a here) */
                           internalLength,      /* internal size */
                           externalLength,      /* external size */
@@ -652,7 +653,7 @@ DefineType(char *typeName, List *parameters)
                           elemName,            /* element type name */
                           defaultValue,        /* default type value */
                           byValue,                     /* passed by value */
-                          alignment,
+                          alignment,           /* required alignment */
                           storage);            /* TOAST strategy */
 
        /* ----------------
@@ -663,6 +664,7 @@ DefineType(char *typeName, List *parameters)
        shadow_type = makeArrayTypeName(typeName);
 
        TypeCreate(shadow_type,         /* type name */
+                          InvalidOid,          /* preassigned type oid (not done here) */
                           InvalidOid,          /* relation oid (n/a here) */
                           -1,                          /* internal size */
                           -1,                          /* external size */
index 83af133d1bbf2759968b880ad74deef2bfcf268c..e429047542f2208c5559fedce1505f720dc3e146 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_type.h,v 1.100 2001/01/24 19:43:22 momjian Exp $
+ * $Id: pg_type.h,v 1.101 2001/02/12 20:07:20 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -420,6 +420,7 @@ DESCR("numeric(precision, decimal), arbitrary precision number");
 extern Oid     TypeGet(char *typeName, bool *defined);
 extern Oid     TypeShellMake(char *typeName);
 extern Oid TypeCreate(char *typeName,
+                  Oid assignedTypeOid,
                   Oid relationOid,
                   int16 internalSize,
                   int16 externalSize,
@@ -431,7 +432,8 @@ extern Oid TypeCreate(char *typeName,
                   char *sendProcedure,
                   char *elementTypeName,
                   char *defaultTypeValue,
-                  bool passedByValue, char alignment,
+                  bool passedByValue,
+                  char alignment,
                   char storage);
 extern void TypeRename(const char *oldTypeName, const char *newTypeName);
 extern char *makeArrayTypeName(char *typeName);