Bugfix in ALTER TABLE CREATE TOAST TABLE
authorJan Wieck
Wed, 5 Jul 2000 12:45:31 +0000 (12:45 +0000)
committerJan Wieck
Wed, 5 Jul 2000 12:45:31 +0000 (12:45 +0000)
Automatically create toast table at CREATE TABLE if new table
has toastable attributes.

Jan

src/backend/commands/command.c
src/backend/tcop/utility.c
src/include/commands/command.h

index 19c87104299e4879fba0bac02b96956d536acb42..bb77fdf11fc74bd76ea6bcc31da8c63740d6a78b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.83 2000/07/04 06:11:27 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.84 2000/07/05 12:45:25 wieck Exp $
  *
  * NOTES
  *   The PerformAddAttribute() code, like most of the relation
@@ -1177,21 +1177,23 @@ AlterTableDropConstraint(const char *relationName,
  * ALTER TABLE CREATE TOAST TABLE
  */
 void
-AlterTableCreateToastTable(const char *relationName)
+AlterTableCreateToastTable(const char *relationName, bool silent)
 {
    Relation            rel;
    Oid                 myrelid;
    HeapTuple           reltup;
+   HeapTupleData       classtuple;
    TupleDesc           tupdesc;
    Form_pg_attribute  *att;
    Relation            class_rel;
+   Buffer              buffer;
    Relation            ridescs[Num_pg_class_indices];
    Oid                 toast_relid;
    Oid                 toast_idxid;
    bool                has_toastable_attrs = false;
    int                 i;
-   char                toast_relname[NAMEDATALEN];
-   char                toast_idxname[NAMEDATALEN];
+   char                toast_relname[NAMEDATALEN + 1];
+   char                toast_idxname[NAMEDATALEN + 1];
    Relation            toast_rel;
    AttrNumber          attNums[1];
    Oid                 classObjectId[1];
@@ -1199,16 +1201,33 @@ AlterTableCreateToastTable(const char *relationName)
    /*
     * permissions checking.  XXX exactly what is appropriate here?
     */
-/*
-   if (!allowSystemTableMods && IsSystemRelationName(relationName))
-       elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
-            relationName);
-*/
 #ifndef NO_SECURITY
    if (!pg_ownercheck(UserName, relationName, RELNAME))
        elog(ERROR, "ALTER TABLE: permission denied");
 #endif
 
+   /*
+    * lock the pg_class tuple for update
+    */
+   reltup = SearchSysCacheTuple(RELNAME, PointerGetDatum(relationName),
+                                0, 0, 0);
+
+   if (!HeapTupleIsValid(reltup))
+       elog(ERROR, "ALTER TABLE: relation \"%s\" not found",
+            relationName);
+   class_rel = heap_openr(RelationRelationName, RowExclusiveLock);
+   classtuple.t_self = reltup->t_self;
+   switch (heap_mark4update(class_rel, &classtuple, &buffer))
+   {
+       case HeapTupleSelfUpdated:
+       case HeapTupleMayBeUpdated:
+           break;
+       default:
+           elog(ERROR, "couldn't lock pg_class tuple");
+   }
+   reltup = heap_copytuple(&classtuple);
+   ReleaseBuffer(buffer);
+
    /*
     * Grab an exclusive lock on the target table, which we will NOT
     * release until end of transaction.
@@ -1231,22 +1250,24 @@ AlterTableCreateToastTable(const char *relationName)
    }
 
    if (!has_toastable_attrs)
+   {
+       if (silent)
+       {
+           heap_close(rel, NoLock);
+           heap_close(class_rel, NoLock);
+           return;
+       }
+
        elog(ERROR, "ALTER TABLE: relation \"%s\" has no toastable attributes",
                relationName);
+   }
 
-   /*
-    * Get the pg_class tuple for the relation
-    */
-   reltup = SearchSysCacheTuple(RELNAME,
-                                PointerGetDatum(relationName),
-                                0, 0, 0);
-
-   if (!HeapTupleIsValid(reltup))
-       elog(ERROR, "ALTER TABLE: relation \"%s\" not found",
-            relationName);
 
    /*
-    * XXX is the following check sufficient?
+    * XXX is the following check sufficient? At least it would
+    * allow to create TOAST tables for views. But why not - someone
+    * can insert into a view, so it shouldn't be impossible to hide
+    * huge data there :-)
     */
    if (((Form_pg_class) GETSTRUCT(reltup))->relkind != RELKIND_RELATION)
    {
@@ -1281,6 +1302,8 @@ AlterTableCreateToastTable(const char *relationName)
 
    /* XXX use RELKIND_TOASTVALUE here? */
    /* XXX what if owning relation is temp?  need we mark toasttable too? */
+   /* !!! No need to worry about temp. It'll go away when it's master    */
+   /*     table is deleted. Jan                                          */
    heap_create_with_catalog(toast_relname, tupdesc, RELKIND_RELATION,
                             false, true);
 
@@ -1307,18 +1330,6 @@ AlterTableCreateToastTable(const char *relationName)
    toast_idxid = RelationGetRelid(toast_rel);
    index_close(toast_rel);
 
-   /*
-    * Get the pg_class tuple for the relation
-    */
-   class_rel = heap_openr(RelationRelationName, RowExclusiveLock);
-
-   reltup = SearchSysCacheTupleCopy(RELNAME,
-                                    PointerGetDatum(relationName),
-                                    0, 0, 0);
-   if (!HeapTupleIsValid(reltup))
-       elog(ERROR, "ALTER TABLE: relation \"%s\" not found",
-            relationName);
-
    /*
     * Store the toast table- and index-Oid's in the relation tuple
     */
@@ -1326,14 +1337,16 @@ AlterTableCreateToastTable(const char *relationName)
    ((Form_pg_class) GETSTRUCT(reltup))->reltoastidxid = toast_idxid;
    heap_update(class_rel, &reltup->t_self, reltup, NULL);
 
-   /* keep catalog indices current */
+   /*
+    * Keep catalog indices current
+    */
    CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
-   CatalogIndexInsert(ridescs, Num_pg_class_indices, rel, reltup);
+   CatalogIndexInsert(ridescs, Num_pg_class_indices, class_rel, reltup);
    CatalogCloseIndices(Num_pg_class_indices, ridescs);
 
    heap_freetuple(reltup);
 
-   heap_close(class_rel, RowExclusiveLock);
+   heap_close(class_rel, NoLock);
    heap_close(rel, NoLock);
 }
 
index 17c77da8504b93190c7bb58a43dc548efc5fde10..409aca70adaf0b4e51fdab57d965322208726393 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.90 2000/07/03 23:09:46 wieck Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.91 2000/07/05 12:45:26 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -159,6 +159,15 @@ ProcessUtility(Node *parsetree,
            CHECK_IF_ABORTED();
 
            DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION);
+
+           /*
+            * Let AlterTableCreateToastTable decide if this
+            * one needs a secondary relation too.
+            *
+            */
+           CommandCounterIncrement();
+           AlterTableCreateToastTable(((CreateStmt *)parsetree)->relname,
+                                       true);
            break;
 
        case T_DropStmt:
@@ -361,7 +370,7 @@ ProcessUtility(Node *parsetree,
                        AlterTableDropConstraint(stmt->relname, stmt->inh, stmt->name, stmt->behavior);
                        break;
                    case 'E':   /* CREATE TOAST TABLE */
-                       AlterTableCreateToastTable(stmt->relname);
+                       AlterTableCreateToastTable(stmt->relname, false);
                        break;
                    default:    /* oops */
                        elog(ERROR, "T_AlterTableStmt: unknown subtype");
index e870126355754f38a8228b4e5748bd75b09f9d39..b2b3d6383fdd92b83c3e757fbffcfc4d83b2d832 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: command.h,v 1.20 2000/07/03 23:10:10 wieck Exp $
+ * $Id: command.h,v 1.21 2000/07/05 12:45:31 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -58,7 +58,8 @@ extern void AlterTableDropConstraint(const char *relationName,
                         bool inh, const char *constrName,
                         int behavior);
 
-extern void AlterTableCreateToastTable(const char *relationName);
+extern void AlterTableCreateToastTable(const char *relationName,
+                         bool silent);
 
 /*
  * LOCK