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