Change StoreCatalogInheritance() to work from a list of parent relation
authorTom Lane
Thu, 14 Dec 2000 00:41:09 +0000 (00:41 +0000)
committerTom Lane
Thu, 14 Dec 2000 00:41:09 +0000 (00:41 +0000)
OIDs rather than names.  Aside from being simpler and faster, this way
doesn't blow up in the face of 'create temp table foo () inherits (foo)'.
Which is a rather odd thing to do, but it seems some people want to.

src/backend/commands/creatinh.c

index 970782d6da30b8574bf9e385272ac9c3cd758280..33022515cb6ca331492c82ff63dc2d4f7e972dfe 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.67 2000/11/16 22:30:18 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.68 2000/12/14 00:41:09 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 static int checkAttrExists(const char *attributeName,
                const char *attributeType, List *schema);
-static List *MergeAttributes(List *schema, List *supers, List **supconstr);
+static List *MergeAttributes(List *schema, List *supers,
+                            List **supOids, List **supconstr);
 static void StoreCatalogInheritance(Oid relationId, List *supers);
-static void
-setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
+static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
 
 
 /* ----------------------------------------------------------------
@@ -53,8 +53,8 @@ DefineRelation(CreateStmt *stmt, char relkind)
    int         numberOfAttributes;
    Oid         relationId;
    Relation    rel;
-   List       *inheritList;
    TupleDesc   descriptor;
+   List       *inheritOids;
    List       *old_constraints;
    List       *rawDefaults;
    List       *listptr;
@@ -67,24 +67,16 @@ DefineRelation(CreateStmt *stmt, char relkind)
    StrNCpy(relname, stmt->relname, NAMEDATALEN);
 
    /* ----------------
-    *  Handle parameters
-    *  XXX parameter handling missing below.
+    *  Look up inheritance ancestors and generate relation schema,
+    *  including inherited attributes.
     * ----------------
     */
-   inheritList = stmt->inhRelnames;
-
-   /* ----------------
-    *  generate relation schema, including inherited attributes.
-    * ----------------
-    */
-   schema = MergeAttributes(schema, inheritList, &old_constraints);
+   schema = MergeAttributes(schema, stmt->inhRelnames,
+                            &inheritOids, &old_constraints);
 
    numberOfAttributes = length(schema);
    if (numberOfAttributes <= 0)
-   {
-       elog(ERROR, "DefineRelation: %s",
-            "please inherit from a relation or define an attribute");
-   }
+       elog(ERROR, "DefineRelation: please inherit from a relation or define an attribute");
 
    /* ----------------
     *  create a relation descriptor from the relation schema
@@ -147,7 +139,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
                                          relkind, stmt->istemp,
                                          allowSystemTableMods);
 
-   StoreCatalogInheritance(relationId, inheritList);
+   StoreCatalogInheritance(relationId, inheritOids);
 
    /*
     * We must bump the command counter to make the newly-created relation
@@ -286,10 +278,15 @@ change_varattnos_of_a_node(Node *node, const AttrNumber *newattno)
  * MergeAttributes
  *     Returns new schema given initial schema and supers.
  *
+ * Input arguments:
  *
  * 'schema' is the column/attribute definition for the table. (It's a list
  *     of ColumnDef's.) It is destructively changed.
- * 'inheritList' is the list of inherited relations (a list of Value(str)'s).
+ * 'supers' is a list of names (as Value objects) of parent relations.
+ *
+ * Output arguments:
+ * 'supOids' receives an integer list of the OIDs of the parent relations.
+ * 'supconstr' receives a list of constraints belonging to the parents.
  *
  * Notes:
  *   The order in which the attributes are inherited is very important.
@@ -314,12 +311,14 @@ change_varattnos_of_a_node(Node *node, const AttrNumber *newattno)
  *                        stud_emp {7:percent}
  */
 static List *
-MergeAttributes(List *schema, List *supers, List **supconstr)
+MergeAttributes(List *schema, List *supers,
+               List **supOids, List **supconstr)
 {
    List       *entry;
    List       *inhSchema = NIL;
+   List       *parentOids = NIL;
    List       *constraints = NIL;
-   int     attnums;
+   int         attnums;
 
    /*
     * Validates that there are no duplications. Validity checking of
@@ -338,7 +337,7 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
             */
            ColumnDef  *restdef = lfirst(rest);
 
-           if (!strcmp(coldef->colname, restdef->colname))
+           if (strcmp(coldef->colname, restdef->colname) == 0)
            {
                elog(ERROR, "CREATE TABLE: attribute \"%s\" duplicated",
                     coldef->colname);
@@ -351,7 +350,7 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
 
        foreach(rest, lnext(entry))
        {
-           if (!strcmp(strVal(lfirst(entry)), strVal(lfirst(rest))))
+           if (strcmp(strVal(lfirst(entry)), strVal(lfirst(rest))) == 0)
            {
                elog(ERROR, "CREATE TABLE: inherited relation \"%s\" duplicated",
                     strVal(lfirst(entry)));
@@ -376,6 +375,11 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
        int     i, attidx, attno_exist;
 
        relation = heap_openr(name, AccessShareLock);
+
+       if (relation->rd_rel->relkind != RELKIND_RELATION)
+           elog(ERROR, "CREATE TABLE: inherited relation \"%s\" is not a table", name);
+
+       parentOids = lappendi(parentOids, relation->rd_id);
        setRelhassubclassInRelation(relation->rd_id, true);
        tupleDesc = RelationGetDescr(relation);
        /* allocate a new attribute number table and initialize */
@@ -391,9 +395,6 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
            partialAttidx [i] = 0;
        constr = tupleDesc->constr;
 
-       if (relation->rd_rel->relkind != RELKIND_RELATION)
-           elog(ERROR, "CREATE TABLE: inherited relation \"%s\" is not a table", name);
-
        attidx = 0;
        for (attrno = relation->rd_rel->relnatts - 1; attrno >= 0; attrno--)
        {
@@ -519,6 +520,8 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
     * put the inherited schema before our the schema for this table
     */
    schema = nconc(inhSchema, schema);
+
+   *supOids = parentOids;
    *supconstr = constraints;
    return schema;
 }
@@ -526,6 +529,9 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
 /*
  * StoreCatalogInheritance
  *     Updates the system catalogs with proper inheritance information.
+ *
+ * supers is an integer list of the OIDs of the new relation's direct
+ * ancestors.  NB: it is destructively changed to include indirect ancestors.
  */
 static void
 StoreCatalogInheritance(Oid relationId, List *supers)
@@ -534,7 +540,6 @@ StoreCatalogInheritance(Oid relationId, List *supers)
    TupleDesc   desc;
    int16       seqNumber;
    List       *entry;
-   List       *idList;
    HeapTuple   tuple;
 
    /* ----------------
@@ -547,32 +552,19 @@ StoreCatalogInheritance(Oid relationId, List *supers)
        return;
 
    /* ----------------
-    * Catalog INHERITS information.
+    * Catalog INHERITS information using direct ancestors only.
     * ----------------
     */
    relation = heap_openr(InheritsRelationName, RowExclusiveLock);
    desc = RelationGetDescr(relation);
 
    seqNumber = 1;
-   idList = NIL;
    foreach(entry, supers)
    {
-       Oid         entryOid;
+       Oid         entryOid = lfirsti(entry);
        Datum       datum[Natts_pg_inherits];
        char        nullarr[Natts_pg_inherits];
 
-       entryOid = GetSysCacheOid(RELNAME,
-                                 PointerGetDatum(strVal(lfirst(entry))),
-                                 0, 0, 0);
-       if (!OidIsValid(entryOid))
-           elog(ERROR, "StoreCatalogInheritance: cache lookup failed for relation \"%s\"",
-                strVal(lfirst(entry)));
-
-       /*
-        * build idList for use below
-        */
-       idList = lappendi(idList, entryOid);
-
        datum[0] = ObjectIdGetDatum(relationId);    /* inhrel */
        datum[1] = ObjectIdGetDatum(entryOid);      /* inhparent */
        datum[2] = Int16GetDatum(seqNumber);        /* inhseqno */
@@ -602,21 +594,20 @@ StoreCatalogInheritance(Oid relationId, List *supers)
    heap_close(relation, RowExclusiveLock);
 
    /* ----------------
-    * Catalog IPL information.
+    * Expand supers list to include indirect ancestors as well.
     *
     * Algorithm:
-    *  0. list superclasses (by Oid) in order given (see idList).
+    *  0. begin with list of direct superclasses.
     *  1. append after each relationId, its superclasses, recursively.
-    *  3. remove all but last of duplicates.
-    *  4. store result.
+    *  2. remove all but last of duplicates.
     * ----------------
     */
 
    /* ----------------
-    *  1.
+    *  1. append after each relationId, its superclasses, recursively.
     * ----------------
     */
-   foreach(entry, idList)
+   foreach(entry, supers)
    {
        HeapTuple   tuple;
        Oid         id;
@@ -649,20 +640,21 @@ StoreCatalogInheritance(Oid relationId, List *supers)
    }
 
    /* ----------------
-    *  2.
+    *  2. remove all but last of duplicates.
     * ----------------
     */
-   foreach(entry, idList)
+   foreach(entry, supers)
    {
-       Oid         name;
+       Oid         thisone;
+       bool        found;
        List       *rest;
-       bool        found = false;
 
 again:
-       name = lfirsti(entry);
+       thisone = lfirsti(entry);
+       found = false;
        foreach(rest, lnext(entry))
        {
-           if (name == lfirsti(rest))
+           if (thisone == lfirsti(rest))
            {
                found = true;
                break;
@@ -672,20 +664,17 @@ again:
        {
 
            /*
-            * entry list must be of length >= 2 or else no match
-            *
-            * so, remove this entry.
+            * found a later duplicate, so remove this entry.
             */
-           lfirst(entry) = lfirst(lnext(entry));
+           lfirsti(entry) = lfirsti(lnext(entry));
            lnext(entry) = lnext(lnext(entry));
 
-           found = false;
            goto again;
        }
    }
 
    /* ----------------
-    *  3.
+    * Catalog IPL information using expanded list.
     * ----------------
     */
    relation = heap_openr(InheritancePrecidenceListRelationName, RowExclusiveLock);
@@ -693,7 +682,7 @@ again:
 
    seqNumber = 1;
 
-   foreach(entry, idList)
+   foreach(entry, supers)
    {
        Datum       datum[Natts_pg_ipl];
        char        nullarr[Natts_pg_ipl];
@@ -721,10 +710,12 @@ again:
 
 
 /*
- * returns the index(star with 1) if attribute already exists in schema, 0 otherwise.
+ * returns the index (starting with 1) if attribute already exists in schema,
+ * 0 if it doesn't.
  */
 static int
-checkAttrExists(const char *attributeName, const char *attributeType, List *schema)
+checkAttrExists(const char *attributeName, const char *attributeType,
+               List *schema)
 {
    List       *s;
    int i = 0;