On Sun, 23 Sep 2001, Tom Lane wrote:
> 
> Note: I'm not convinced that relfilenode and pg_class.oid are each
> used in exactly the right spots.  Once we have cases where they can
> differ, we may well find some bugs to flush out.  But that needs to
> happen anyway, so don't let it dissuade you from doing CLUSTER the
> right way.

I think I may have broken stuff. I'm not sure. I've fiddled a fair bit but
I'm still segfaulting in the storage manager. It might be because I'm
heap_creating and then just stealing relfilenode - I don't know.

Anyway, a patch is attached which clusters and then recreates the indexes
- but then segfaults.

Am I going about this all wrong?

Thanks

Gavin
*** src/backend/commands/cluster.c      Mon Sep 24 16:01:31 2001
--- src/backend/commands/cluster.c.orig Sun Sep 23 16:37:35 2001
***************
*** 24,33 ****
  
  #include "access/genam.h"
  #include "access/heapam.h"
- #include "catalog/catname.h"
  #include "catalog/heap.h"
  #include "catalog/index.h"
- #include "catalog/indexing.h"
  #include "catalog/pg_index.h"
  #include "catalog/pg_proc.h"
  #include "commands/cluster.h"
--- 24,31 ----
***************
*** 37,46 ****
  #include "utils/builtins.h"
  #include "utils/syscache.h"
  #include "utils/temprel.h"
! #include "utils/relcache.h"           // for RelationGetIndexList()
  
  static Oid    copy_heap(Oid OIDOldHeap, char *NewName, bool istemp);
! static void new_index(Oid OIDOldIndex, Oid OIDHeap, char *NewIndexName);
  static void rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex);
  
  /*
--- 35,44 ----
  #include "utils/builtins.h"
  #include "utils/syscache.h"
  #include "utils/temprel.h"
! 
  
  static Oid    copy_heap(Oid OIDOldHeap, char *NewName, bool istemp);
! static void copy_index(Oid OIDOldIndex, Oid OIDNewHeap, char *NewIndexName);
  static void rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex);
  
  /*
***************
*** 62,93 ****
                                OIDOldIndex,
                                OIDNewHeap;
        Relation        OldHeap,
!                               OldIndex,
!                               NewHeap,
!                               relrelation;                    
        HeapTuple       tuple;
-       TupleDesc       tupdesc;
- 
        bool            istemp;
        char            NewHeapName[NAMEDATALEN];
        char            NewIndexName[NAMEDATALEN];
        char            saveoldrelname[NAMEDATALEN];
        char            saveoldindexname[NAMEDATALEN];
-       List            *OldIndexOids;
- 
-       Relation        irelations[Num_pg_class_indices];
- 
-       /* put the details of index name/oid of the OldHeap
-        * in here to speed things up and make it all cleaner
-        */
-       
-       struct OldIndexData {
-                       char oldindname[NAMEDATALEN];
-                       char newindname[NAMEDATALEN];
-       };      
- 
-       List *OldIndices = NULL;
-       List *ltmp;     
  
        /*
         * Copy the arguments into local storage, just to be safe.
--- 60,72 ----
                                OIDOldIndex,
                                OIDNewHeap;
        Relation        OldHeap,
!                               OldIndex;
        HeapTuple       tuple;
        bool            istemp;
        char            NewHeapName[NAMEDATALEN];
        char            NewIndexName[NAMEDATALEN];
        char            saveoldrelname[NAMEDATALEN];
        char            saveoldindexname[NAMEDATALEN];
  
        /*
         * Copy the arguments into local storage, just to be safe.
***************
*** 100,109 ****
         * duration of the transaction.
         */
        OldHeap = heap_openr(saveoldrelname, AccessExclusiveLock);
- 
-       /* Preserve all indices. - gavin */
-       OldIndexOids = RelationGetIndexList(OldHeap);
- 
        OIDOldHeap = RelationGetRelid(OldHeap);
  
        OldIndex = index_openr(saveoldindexname);
--- 79,84 ----
***************
*** 135,213 ****
         */
        snprintf(NewHeapName, NAMEDATALEN, "temp_%u", OIDOldHeap);
  
        /*
!        * heap_create needs this. Unsure if I can just give it a 
!        * zero'd structure. Lets use the current one instead
         */
  
!       tupdesc = CreateTupleDescCopyConstr(RelationGetDescr(OldHeap));
  
-       
-       NewHeap = heap_create(NewHeapName,tupdesc,istemp,true,
-                                       allowSystemTableMods);
-       
-       /* Is this required here ? */
        CommandCounterIncrement();
  
!       OIDNewHeap = RelationGetRelid(NewHeap);
        /*
!        * Copy the heap data into the new table in the desired order.
         */
!       rebuildheap(OIDNewHeap, OIDOldHeap, OIDOldIndex);
  
  
!       heap_close(NewHeap,NoLock);
!       /* To make the new heap's data visible. */
        CommandCounterIncrement();
  
!       /* Update OldHeap to have new relfilenode */
  
!       relrelation = heap_openr(RelationRelationName,RowExclusiveLock);
!       tuple = SearchSysCacheCopy(RELOID,
!                                                  ObjectIdGetDatum(OIDOldHeap),
!                                                  0, 0, 0);
  
!       Assert(HeapTupleIsValid(tuple));
!       
!       ((Form_pg_class) GETSTRUCT(tuple))->relfilenode = 
!                       NewHeap->rd_rel->relfilenode;
! 
!       simple_heap_update(relrelation,&tuple->t_self,tuple);
! 
!       /* update catalogue indices */
!       CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, irelations);
!       CatalogIndexInsert(irelations, Num_pg_class_indices, relrelation, tuple);
!       CatalogCloseIndices(Num_pg_class_indices, irelations);
!       
!       heap_close(relrelation,NoLock);
! 
!       /* Reindex */
!       /* copy to a new index, drop the old and rename */
! 
!       foreach(ltmp,OldIndexOids) {
!               Relation rel;
!               char OldIndexName[NAMEDATALEN];
! 
!               rel = RelationIdGetRelation((Oid)lfirst(ltmp));
!               StrNCpy(OldIndexName,RelationGetRelationName(rel),NAMEDATALEN);
! 
!               snprintf(NewIndexName,NAMEDATALEN,"temp_%u",(Oid)lfirst(ltmp));
! 
!               new_index((Oid)lfirst(ltmp),OIDOldHeap,NewIndexName);
! 
!               index_drop((Oid)lfirst(ltmp));
!               CommandCounterIncrement();
! 
!               renamerel(NewIndexName,OldIndexName);
!               /* decrement the count to keep everyone happy */
!               RelationClose(rel);
!       }
!       FreeTupleDesc(tupdesc);
!       heap_freetuple(tuple);
  }
  
  static void
! new_index(Oid OIDOldIndex, Oid OIDHeap, char *NewIndexName)
  {
        Relation        OldIndex,
                                NewHeap;
--- 110,188 ----
         */
        snprintf(NewHeapName, NAMEDATALEN, "temp_%u", OIDOldHeap);
  
+       OIDNewHeap = copy_heap(OIDOldHeap, NewHeapName, istemp);
+ 
+       /* We do not need CommandCounterIncrement() because copy_heap did it. */
+ 
        /*
!        * Copy the heap data into the new table in the desired order.
         */
+       rebuildheap(OIDNewHeap, OIDOldHeap, OIDOldIndex);
+ 
+       /* To make the new heap's data visible. */
+       CommandCounterIncrement();
+ 
+       /* Create new index over the tuples of the new heap. */
+       snprintf(NewIndexName, NAMEDATALEN, "temp_%u", OIDOldIndex);
+ 
+       copy_index(OIDOldIndex, OIDNewHeap, NewIndexName);
+ 
+       CommandCounterIncrement();
  
!       /* Destroy old heap (along with its index) and rename new. */
!       heap_drop_with_catalog(saveoldrelname, allowSystemTableMods);
  
        CommandCounterIncrement();
  
!       renamerel(NewHeapName, saveoldrelname);
! 
!       /* This one might be unnecessary, but let's be safe. */
!       CommandCounterIncrement();
! 
!       renamerel(NewIndexName, saveoldindexname);
! }
! 
! static Oid
! copy_heap(Oid OIDOldHeap, char *NewName, bool istemp)
! {
!       TupleDesc       OldHeapDesc,
!                               tupdesc;
!       Oid                     OIDNewHeap;
!       Relation        OldHeap;
! 
!       OldHeap = heap_open(OIDOldHeap, AccessExclusiveLock);
!       OldHeapDesc = RelationGetDescr(OldHeap);
! 
        /*
!        * Need to make a copy of the tuple descriptor, since
!        * heap_create_with_catalog modifies it.
         */
!       tupdesc = CreateTupleDescCopyConstr(OldHeapDesc);
  
+       OIDNewHeap = heap_create_with_catalog(NewName, tupdesc,
+                                                                                 
+RELKIND_RELATION, istemp,
+                                                                                 
+allowSystemTableMods);
  
!       /*
!        * Advance command counter so that the newly-created relation's
!        * catalog tuples will be visible to heap_open.
!        */
        CommandCounterIncrement();
  
!       /*
!        * If necessary, create a TOAST table for the new relation. Note that
!        * AlterTableCreateToastTable ends with CommandCounterIncrement(), so
!        * that the TOAST table will be visible for insertion.
!        */
!       AlterTableCreateToastTable(NewName, true);
  
!       heap_close(OldHeap, NoLock);
  
!       return OIDNewHeap;
  }
  
  static void
! copy_index(Oid OIDOldIndex, Oid OIDNewHeap, char *NewIndexName)
  {
        Relation        OldIndex,
                                NewHeap;
***************
*** 217,223 ****
        Form_pg_class Old_pg_index_relation_Form;
        IndexInfo  *indexInfo;
  
!       NewHeap = heap_open(OIDHeap, AccessExclusiveLock);
        OldIndex = index_open(OIDOldIndex);
  
        /*
--- 192,198 ----
        Form_pg_class Old_pg_index_relation_Form;
        IndexInfo  *indexInfo;
  
!       NewHeap = heap_open(OIDNewHeap, AccessExclusiveLock);
        OldIndex = index_open(OIDOldIndex);
  
        /*
***************
*** 242,247 ****
--- 217,223 ----
                                                                                       
          0, 0, 0);
        Assert(Old_pg_index_relation_Tuple);
        Old_pg_index_relation_Form = (Form_pg_class) 
GETSTRUCT(Old_pg_index_relation_Tuple);
+ 
        index_create(RelationGetRelationName(NewHeap),
                                 NewIndexName,
                                 indexInfo,
***************
*** 251,259 ****
                                 Old_pg_index_Form->indisprimary,
                                 allowSystemTableMods);
  
!       /* handled by index_drop */
!       
!       //      setRelhasindex(OIDHeap, true);
  
        ReleaseSysCache(Old_pg_index_Tuple);
        ReleaseSysCache(Old_pg_index_relation_Tuple);
--- 227,233 ----
                                 Old_pg_index_Form->indisprimary,
                                 allowSystemTableMods);
  
!       setRelhasindex(OIDNewHeap, true);
  
        ReleaseSysCache(Old_pg_index_Tuple);
        ReleaseSysCache(Old_pg_index_relation_Tuple);

---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?

http://www.postgresql.org/users-lounge/docs/faq.html

Reply via email to