Small cleanup of temp-table handling. Disallow creation of a non-temp
authorTom Lane
Fri, 22 Dec 2000 23:12:07 +0000 (23:12 +0000)
committerTom Lane
Fri, 22 Dec 2000 23:12:07 +0000 (23:12 +0000)
table that inherits from a temp table.  Make sure the right things happen
if one creates a temp table, creates another temp that inherits from it,
then renames the first one.  (Previously, system would end up trying to
delete the temp tables in the wrong order.)

src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/commands/command.c
src/backend/commands/creatinh.c
src/backend/commands/vacuum.c
src/backend/utils/cache/relcache.c
src/backend/utils/cache/temprel.c
src/include/utils/temprel.h

index b2d2566bf3f290ea255c9310ac249129b9643b30..174b8ca85bb9308778ae22105451b6d453d5df1c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.153 2000/12/22 19:21:37 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.154 2000/12/22 23:12:03 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -801,7 +801,7 @@ heap_create_with_catalog(char *relname,
 
    /* temp tables can mask non-temp tables */
    if ((!istemp && RelnameFindRelid(relname)) ||
-       (istemp && get_temp_rel_by_username(relname) != NULL))
+       (istemp && is_temp_rel_name(relname)))
        elog(ERROR, "Relation '%s' already exists", relname);
 
    if (istemp)
@@ -813,7 +813,7 @@ heap_create_with_catalog(char *relname,
    }
 
    /* ----------------
-    *  get_temp_rel_by_username() couldn't check the simultaneous
+    *  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
@@ -1404,7 +1404,7 @@ heap_drop_with_catalog(const char *relname,
    Relation    rel;
    Oid         rid;
    bool        has_toasttable;
-   bool        istemp = (get_temp_rel_by_username(relname) != NULL);
+   bool        istemp = is_temp_rel_name(relname);
    int         i;
 
    /* ----------------
index 649e2300245e47ec7c4e9c88e2eb0574db690444..46f8abe7b312a0e967f27f0e0ecdeb0eb119f602 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.132 2000/12/09 20:31:43 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.133 2000/12/22 23:12:03 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -145,7 +145,7 @@ GetHeapRelationOid(char *heapRelationName, char *indexRelationName, bool istemp)
    indoid = RelnameFindRelid(indexRelationName);
 
    if ((!istemp && OidIsValid(indoid)) ||
-       (istemp && get_temp_rel_by_username(indexRelationName) != NULL))
+       (istemp && is_temp_rel_name(indexRelationName)))
        elog(ERROR, "Cannot create index: '%s' already exists",
             indexRelationName);
 
@@ -885,7 +885,7 @@ index_create(char *heapRelationName,
    TupleDesc   indexTupDesc;
    Oid         heapoid;
    Oid         indexoid;
-   bool        istemp = (get_temp_rel_by_username(heapRelationName) != NULL);
+   bool        istemp = is_temp_rel_name(heapRelationName);
    char       *temp_relname = NULL;
 
    SetReindexProcessing(false);
index 78a3d5e1a75fe198f4c5b19d39cd21cb1b35ffc8..035967f920960b34fd58daa260572abd20843e0d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.113 2000/12/05 19:57:55 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.114 2000/12/22 23:12:05 tgl Exp $
  *
  * NOTES
  *   The PerformAddAttribute() code, like most of the relation
@@ -1237,10 +1237,9 @@ AlterTableAddConstraint(char *relationName,
            int         i;
            bool        found = false;
 
-           if (get_temp_rel_by_username(fkconstraint->pktable_name)!=NULL &&
-               get_temp_rel_by_username(relationName)==NULL) {
+           if (is_temp_rel_name(fkconstraint->pktable_name) &&
+               !is_temp_rel_name(relationName))
                elog(ERROR, "ALTER TABLE / ADD CONSTRAINT: Unable to reference temporary table from permanent table constraint.");
-           }
 
            /*
             * Grab an exclusive lock on the pk table, so that someone
index 33022515cb6ca331492c82ff63dc2d4f7e972dfe..38e2c3a418ed87248dd5be8a45bdf50dfbe3a8c4 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.68 2000/12/14 00:41:09 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.69 2000/12/22 23:12:05 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -24,8 +24,9 @@
 #include "catalog/pg_type.h"
 #include "commands/creatinh.h"
 #include "miscadmin.h"
-#include "utils/syscache.h"
 #include "optimizer/clauses.h"
+#include "utils/syscache.h"
+#include "utils/temprel.h"
 
 /* ----------------
  *     local stuff
@@ -34,7 +35,7 @@
 
 static int checkAttrExists(const char *attributeName,
                const char *attributeType, List *schema);
-static List *MergeAttributes(List *schema, List *supers,
+static List *MergeAttributes(List *schema, List *supers, bool istemp,
                             List **supOids, List **supconstr);
 static void StoreCatalogInheritance(Oid relationId, List *supers);
 static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
@@ -71,7 +72,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
     *  including inherited attributes.
     * ----------------
     */
-   schema = MergeAttributes(schema, stmt->inhRelnames,
+   schema = MergeAttributes(schema, stmt->inhRelnames, stmt->istemp,
                             &inheritOids, &old_constraints);
 
    numberOfAttributes = length(schema);
@@ -283,6 +284,7 @@ change_varattnos_of_a_node(Node *node, const AttrNumber *newattno)
  * 'schema' is the column/attribute definition for the table. (It's a list
  *     of ColumnDef's.) It is destructively changed.
  * 'supers' is a list of names (as Value objects) of parent relations.
+ * 'istemp' is TRUE if we are creating a temp relation.
  *
  * Output arguments:
  * 'supOids' receives an integer list of the OIDs of the parent relations.
@@ -311,7 +313,7 @@ change_varattnos_of_a_node(Node *node, const AttrNumber *newattno)
  *                        stud_emp {7:percent}
  */
 static List *
-MergeAttributes(List *schema, List *supers,
+MergeAttributes(List *schema, List *supers, bool istemp,
                List **supOids, List **supconstr)
 {
    List       *entry;
@@ -378,6 +380,9 @@ MergeAttributes(List *schema, List *supers,
 
        if (relation->rd_rel->relkind != RELKIND_RELATION)
            elog(ERROR, "CREATE TABLE: inherited relation \"%s\" is not a table", name);
+       /* Permanent rels cannot inherit from temporary ones */
+       if (!istemp && is_temp_rel_name(name))
+           elog(ERROR, "CREATE TABLE: cannot inherit from temp relation \"%s\"", name);
 
        parentOids = lappendi(parentOids, relation->rd_id);
        setRelhassubclassInRelation(relation->rd_id, true);
index 0d4984cde6aa25b50f0180b68b59b35ea5f4d571..909c9cea732efc91959b7e47b9672fe1fa428ec4 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.178 2000/12/22 00:51:53 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.179 2000/12/22 23:12:05 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -274,8 +274,8 @@ getrels(NameData *VacRelP)
        char       *nontemp_relname;
 
        /* We must re-map temp table names bjm 2000-04-06 */
-       if ((nontemp_relname =
-            get_temp_rel_by_username(NameStr(*VacRelP))) == NULL)
+       nontemp_relname = get_temp_rel_by_username(NameStr(*VacRelP));
+       if (nontemp_relname == NULL)
            nontemp_relname = NameStr(*VacRelP);
 
        ScanKeyEntryInitialize(&key, 0x0, Anum_pg_class_relname,
index 4e9780462a5e619d1d03b5933287d432df43cf56..1b7ce6fe18c280f77c8b86824570dab34958cd60 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.120 2000/12/09 20:32:44 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.121 2000/12/22 23:12:06 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1526,7 +1526,7 @@ RelationNameGetRelation(const char *relationName)
     * ----------------
     */
    temprelname = get_temp_rel_by_username(relationName);
-   if (temprelname)
+   if (temprelname != NULL)
        relationName = temprelname;
 
    /* ----------------
index 0134b47a0f9d71bf45c311815e5bceee810e286d..a0066f2eaff4ed24e2027aa420f7f345755a4e65 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/temprel.c,v 1.31 2000/11/16 22:30:33 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/temprel.c,v 1.32 2000/12/22 23:12:07 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -152,13 +152,19 @@ rename_temp_relation(const char *oldname,
            continue;           /* ignore non-matching entries */
 
        /* We are renaming a temp table --- is it OK to do so? */
-       if (get_temp_rel_by_username(newname) != NULL)
+       if (is_temp_rel_name(newname))
            elog(ERROR, "Cannot rename temp table \"%s\": temp table \"%s\" already exists",
                 oldname, newname);
 
        /*
         * Create a new mapping entry and mark the old one deleted in this
         * xact.  One of these entries will be deleted at xact end.
+        *
+        * NOTE: the new mapping entry is inserted into the list just after
+        * the old one.  We could alternatively insert it before the old one,
+        * but that'd take more code.  It does need to be in one spot or the
+        * other, to ensure that deletion of temp rels happens in the right
+        * order during remove_all_temp_relations().
         */
        oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
@@ -168,7 +174,7 @@ rename_temp_relation(const char *oldname,
        StrNCpy(NameStr(new_temp_rel->user_relname), newname, NAMEDATALEN);
        new_temp_rel->created_in_cur_xact = true;
 
-       temp_rels = lcons(new_temp_rel, temp_rels);
+       lnext(l) = lcons(new_temp_rel, lnext(l));
 
        temp_rel->deleted_in_cur_xact = true;
 
@@ -178,7 +184,7 @@ rename_temp_relation(const char *oldname,
    }
 
    /* Old name does not match any temp table name, what about new? */
-   if (get_temp_rel_by_username(newname) != NULL)
+   if (is_temp_rel_name(newname))
        elog(ERROR, "Cannot rename \"%s\" to \"%s\": a temp table by that name already exists",
             oldname, newname);
 
@@ -205,7 +211,8 @@ remove_all_temp_relations(void)
     * Scan the list and delete all entries not already deleted.
     * We need not worry about list entries getting deleted from under us,
     * because remove_temp_rel_by_relid() doesn't remove entries, only
-    * mark them dead.
+    * mark them dead.  Note that entries will be deleted in reverse order
+    * of creation --- that's critical for cases involving inheritance.
     */
    foreach(l, temp_rels)
    {
@@ -286,7 +293,8 @@ AtEOXact_temp_relations(bool isCommit)
 /*
  * Map user name to physical name --- returns NULL if no entry.
  *
- * This is the normal way to test whether a name is a temp table name.
+ * This also supports testing whether a name is a temp table name;
+ * see is_temp_rel_name() macro.
  */
 char *
 get_temp_rel_by_username(const char *user_relname)
index 789d5058789e281ea11d4e7829f1259be3f9b849..8c19c8e127dfd296d08063d4fa4bb2569acb0474 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: temprel.h,v 1.12 2000/11/08 22:10:03 tgl Exp $
+ * $Id: temprel.h,v 1.13 2000/12/22 23:12:07 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,4 +28,6 @@ extern void AtEOXact_temp_relations(bool isCommit);
 extern char *get_temp_rel_by_username(const char *user_relname);
 extern char *get_temp_rel_by_physicalname(const char *relname);
 
+#define is_temp_rel_name(relname) (get_temp_rel_by_username(relname) != NULL)
+
 #endif  /* TEMPREL_H */