Rearrange order of operations in heap_create_with_catalog so that if
authorTom Lane
Mon, 12 Feb 2001 20:07:21 +0000 (20:07 +0000)
committerTom Lane
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);