]> granicus.if.org Git - postgresql/commitdiff
Changed TOAST relations to have relkind RELKIND_TOASTVALUE.
authorJan Wieck <JanWieck@Yahoo.com>
Wed, 5 Jul 2000 16:17:43 +0000 (16:17 +0000)
committerJan Wieck <JanWieck@Yahoo.com>
Wed, 5 Jul 2000 16:17:43 +0000 (16:17 +0000)
Special handling of TOAST relations during VACUUM. TOAST relations
are vacuumed while the lock on the master table is still active.
The ANALYZE flag doesn't propagate to their vacuuming because the
toaster access routines allways use index access ignoring stats, so
why compute them at all.

Protection of TOAST relations against normal INSERT/UPDATE/DELETE
while offering SELECT for debugging purposes.

Jan

src/backend/catalog/index.c
src/backend/commands/command.c
src/backend/commands/vacuum.c
src/backend/executor/execMain.c

index a78f0fa3db9f33390ac89ea3aa864efce60885fc..bedb84e6d24d1e9d77fec072353dcd9e5f0d1d03 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.122 2000/07/04 06:11:23 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.123 2000/07/05 16:17:37 wieck Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1335,7 +1335,8 @@ IndexesAreActive(Oid relid, bool confirmCommitted)
 
        if (!LockClassinfoForUpdate(relid, &tuple, &buffer, confirmCommitted))
                elog(ERROR, "IndexesAreActive couldn't lock %u", relid);
-       if (((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_RELATION)
+       if (((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_RELATION &&
+           ((Form_pg_class) GETSTRUCT(&tuple))->relkind != RELKIND_TOASTVALUE)
                elog(ERROR, "relation %u isn't an relation", relid);
        isactive = ((Form_pg_class) GETSTRUCT(&tuple))->relhasindex;
        ReleaseBuffer(buffer);
index af5c49af5eb760419fe491f3ae2b3b81795363ad..e3847ab5f4d42eb8b5b587c3266c383d00a1b1ad 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.86 2000/07/05 13:50:59 wieck Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.87 2000/07/05 16:17:38 wieck Exp $
  *
  * NOTES
  *       The PerformAddAttribute() code, like most of the relation
@@ -1319,14 +1319,14 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
                                           -1, 0, false);
        TupleDescInitEntry(tupdesc, (AttrNumber) 3,
                                           "chunk_data",
-                                          TEXTOID,     /* XXX wouldn't BYTEAOID be better? */
+                                          BYTEAOID,
                                           -1, 0, false);
 
-       /* 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,
+       /* XXX How do we know? No naming collisions possible because names    */
+       /*     are OID based. And toast table disappears when master table    */
+       /*     is destroyed. So what is it good for anyway? Jan               */
+       heap_create_with_catalog(toast_relname, tupdesc, RELKIND_TOASTVALUE,
                                                         false, true);
 
        /* make the toast relation visible, else index creation will fail */
@@ -1368,6 +1368,39 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
 
        heap_freetuple(reltup);
 
+       /*
+        * Finally update the toast relations pg_class tuple to say
+        * it has an index.
+        */
+       reltup = SearchSysCacheTuple(RELNAME, PointerGetDatum(toast_relname),
+                                                                0, 0, 0);
+       if (!HeapTupleIsValid(reltup))
+               elog(ERROR, "ALTER TABLE: just created toast relation \"%s\" not found",
+                        toast_relname);
+       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);
+
+       ((Form_pg_class) GETSTRUCT(reltup))->relhasindex = true;
+       heap_update(class_rel, &reltup->t_self, reltup, NULL);
+
+       CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
+       CatalogIndexInsert(ridescs, Num_pg_class_indices, class_rel, reltup);
+       CatalogCloseIndices(Num_pg_class_indices, ridescs);
+
+       heap_freetuple(reltup);
+
+       /*
+        * Close relatons and make changes visible
+        */
        heap_close(class_rel, NoLock);
        heap_close(rel, NoLock);
 
index 01ed68b3b717b20b741b2933050a90e64d5c0a0a..71682baa8cd57df17b16d8a7a53c9caaa634bcd6 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.161 2000/06/28 03:31:28 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.162 2000/07/05 16:17:38 wieck Exp $
  *
 
  *-------------------------------------------------------------------------
@@ -58,7 +58,7 @@ static void vacuum_init(void);
 static void vacuum_shutdown(void);
 static void vac_vacuum(NameData *VacRelP, bool analyze, List *anal_cols2);
 static VRelList getrels(NameData *VacRelP);
-static void vacuum_rel(Oid relid, bool analyze);
+static void vacuum_rel(Oid relid, bool analyze, bool is_toastrel);
 static void scan_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages, VacPageList fraged_pages);
 static void repair_frag(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages, VacPageList fraged_pages, int nindices, Relation *Irel);
 static void vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacpagelist);
@@ -235,7 +235,7 @@ vac_vacuum(NameData *VacRelP, bool analyze, List *anal_cols2)
        /* vacuum each heap relation */
        for (cur = vrl; cur != (VRelList) NULL; cur = cur->vrl_next)
        {
-               vacuum_rel(cur->vrl_relid, analyze);
+               vacuum_rel(cur->vrl_relid, analyze, false);
                /* analyze separately so locking is minimized */
                if (analyze)
                        analyze_rel(cur->vrl_relid, anal_cols2, MESSAGE_LEVEL);
@@ -347,7 +347,7 @@ getrels(NameData *VacRelP)
  *             us to lock the entire database during one pass of the vacuum cleaner.
  */
 static void
-vacuum_rel(Oid relid, bool analyze)
+vacuum_rel(Oid relid, bool analyze, bool is_toastrel)
 {
        HeapTuple       tuple;
        Relation        onerel;
@@ -361,8 +361,10 @@ vacuum_rel(Oid relid, bool analyze)
                                i;
        VRelStats  *vacrelstats;
        bool            reindex = false;
+       Oid                     toast_relid;
 
-       StartTransactionCommand();
+       if (!is_toastrel)
+               StartTransactionCommand();
 
        /*
         * Check for user-requested abort.      Note we want this to be inside a
@@ -380,7 +382,8 @@ vacuum_rel(Oid relid, bool analyze)
                                                                0, 0, 0);
        if (!HeapTupleIsValid(tuple))
        {
-               CommitTransactionCommand();
+               if (!is_toastrel)
+                       CommitTransactionCommand();
                return;
        }
 
@@ -392,6 +395,12 @@ vacuum_rel(Oid relid, bool analyze)
         */
        onerel = heap_open(relid, AccessExclusiveLock);
 
+       /*
+        * Remember the relations TOAST relation for later
+        *
+        */
+       toast_relid = onerel->rd_rel->reltoastrelid;
+
 #ifndef NO_SECURITY
        if (!pg_ownercheck(GetPgUserName(), RelationGetRelationName(onerel),
                                           RELNAME))
@@ -399,7 +408,8 @@ vacuum_rel(Oid relid, bool analyze)
                elog(NOTICE, "Skipping \"%s\" --- only table owner can VACUUM it",
                         RelationGetRelationName(onerel));
                heap_close(onerel, AccessExclusiveLock);
-               CommitTransactionCommand();
+               if (!is_toastrel)
+                       CommitTransactionCommand();
                return;
        }
 #endif
@@ -488,8 +498,18 @@ vacuum_rel(Oid relid, bool analyze)
        update_relstats(vacrelstats->relid, vacrelstats->num_pages,
                        vacrelstats->num_tuples, vacrelstats->hasindex, vacrelstats);
 
+       /* If the relation has a secondary toast one, vacuum that too
+        * while we still hold the lock on the master table. We don't
+        * need to propagate "analyze" to it, because the toaster
+        * allways uses hardcoded index access and statistics are
+        * totally unimportant for toast relations
+        */
+       if (toast_relid != InvalidOid)
+               vacuum_rel(toast_relid, false, true);
+
        /* next command frees attribute stats */
-       CommitTransactionCommand();
+       if (!is_toastrel)
+               CommitTransactionCommand();
 }
 
 /*
index c707315081dede716d005f60288a6d54bba48e81..6f161d95c0fae07721b864cb9294b085911ecd3b 100644 (file)
@@ -27,7 +27,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.120 2000/07/05 13:22:25 wieck Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.121 2000/07/05 16:17:43 wieck Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -720,6 +720,10 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
                        elog(ERROR, "You can't change sequence relation %s",
                                 RelationGetRelationName(resultRelationDesc));
 
+               if (resultRelationDesc->rd_rel->relkind == RELKIND_TOASTVALUE)
+                       elog(ERROR, "You can't change toast relation %s",
+                                RelationGetRelationName(resultRelationDesc));
+
                resultRelationInfo = makeNode(RelationInfo);
                resultRelationInfo->ri_RangeTableIndex = resultRelationIndex;
                resultRelationInfo->ri_RelationDesc = resultRelationDesc;