Index: cluster.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/cluster.c,v retrieving revision 1.82 diff -c -c -r1.82 cluster.c *** cluster.c 2002/06/20 20:29:26 1.82 --- cluster.c 2002/07/05 02:33:40 *************** *** 26,69 **** #include "access/heapam.h" #include "catalog/heap.h" #include "catalog/index.h" #include "catalog/pg_index.h" #include "catalog/pg_proc.h" #include "commands/cluster.h" #include "commands/tablecmds.h" #include "miscadmin.h" #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/syscache.h" static Oid copy_heap(Oid OIDOldHeap, const char *NewName); - static Oid copy_index(Oid OIDOldIndex, Oid OIDNewHeap, - const char *NewIndexName); static void rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex); /* * cluster * * STILL TO DO: ! * Create a list of all the other indexes on this relation. Because ! * the cluster will wreck all the tids, I'll need to destroy bogus ! * indexes. The user will have to re-create them. Not nice, but ! * I'm not a nice guy. The alternative is to try some kind of post ! * destroy re-build. This may be possible. I'll check out what the ! * index create functiond want in the way of paramaters. On the other ! * hand, re-creating n indexes may blow out the space. */ void cluster(RangeVar *oldrelation, char *oldindexname) { Oid OIDOldHeap, OIDOldIndex, ! OIDNewHeap, ! OIDNewIndex; Relation OldHeap, ! OldIndex; char NewHeapName[NAMEDATALEN]; ! char NewIndexName[NAMEDATALEN]; /* * We grab exclusive access to the target rel and index for the --- 26,82 ---- #include "access/heapam.h" #include "catalog/heap.h" #include "catalog/index.h" + #include "catalog/catname.h" #include "catalog/pg_index.h" #include "catalog/pg_proc.h" #include "commands/cluster.h" #include "commands/tablecmds.h" #include "miscadmin.h" #include "utils/builtins.h" + #include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/syscache.h" static Oid copy_heap(Oid OIDOldHeap, const char *NewName); static void rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex); /* + * We need one of these structs for each index in the relation to be + * clustered. + */ + typedef struct + { + char *indexName; + IndexInfo *indexInfo; + Oid accessMethodOID; + Oid *classOID; + Oid indexOID; + bool isPrimary; + } IndexAttrs; + + /* * cluster * * STILL TO DO: ! * Keep foreign keys of the clustered table. */ void cluster(RangeVar *oldrelation, char *oldindexname) { Oid OIDOldHeap, OIDOldIndex, ! OIDNewHeap; Relation OldHeap, ! OldIndex, ! indexRelation; char NewHeapName[NAMEDATALEN]; ! HeapTuple indexTuple; ! ScanKeyData entry; ! HeapScanDesc scan; ! List *indexes=NIL; ! List *elem; ! IndexAttrs *attrs; /* * We grab exclusive access to the target rel and index for the *************** *** 95,100 **** --- 108,146 ---- index_close(OldIndex); /* + * Save the information of all indexes on the relation. + */ + indexRelation = heap_openr(IndexRelationName, AccessShareLock); + ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid, + F_OIDEQ, ObjectIdGetDatum(OIDOldHeap)); + scan = heap_beginscan(indexRelation, SnapshotNow, 1, &entry); + while ((indexTuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + { + Form_pg_index index = (Form_pg_index) GETSTRUCT(indexTuple); + HeapTuple tuple; + Form_pg_class class; + attrs = (IndexAttrs *) palloc(sizeof(IndexAttrs)); + attrs->indexInfo = BuildIndexInfo(index); + attrs->isPrimary = index->indisprimary; + attrs->indexOID = index->indexrelid; + attrs->classOID = (Oid *)palloc(sizeof(Oid) * + attrs->indexInfo->ii_NumIndexAttrs); + memcpy(attrs->classOID, index->indclass, + sizeof(Oid) * attrs->indexInfo->ii_NumIndexAttrs); + tuple = SearchSysCache(RELOID, ObjectIdGetDatum(attrs->indexOID), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + break; + class = (Form_pg_class) GETSTRUCT(tuple); + attrs->indexName = pstrdup(NameStr(class->relname)); + attrs->accessMethodOID = class->relam; + ReleaseSysCache(tuple); + indexes=lcons((void *)attrs, indexes); + } + heap_endscan(scan); + heap_close(indexRelation, AccessShareLock); + + /* * Create the new heap with a temporary name. */ snprintf(NewHeapName, NAMEDATALEN, "temp_%u", OIDOldHeap); *************** *** 111,123 **** /* 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); - - OIDNewIndex = copy_index(OIDOldIndex, OIDNewHeap, NewIndexName); - - CommandCounterIncrement(); - /* Destroy old heap (along with its index) and rename new. */ heap_drop_with_catalog(OIDOldHeap, allowSystemTableMods); --- 157,162 ---- *************** *** 128,134 **** /* This one might be unnecessary, but let's be safe. */ CommandCounterIncrement(); ! renamerel(OIDNewIndex, oldindexname); } static Oid --- 167,180 ---- /* This one might be unnecessary, but let's be safe. */ CommandCounterIncrement(); ! foreach (elem, indexes) ! { ! attrs=(IndexAttrs *) lfirst(elem); ! index_create(OIDNewHeap, attrs->indexName, attrs->indexInfo, ! attrs->accessMethodOID, attrs->classOID, attrs->isPrimary, ! allowSystemTableMods); ! setRelhasindex(OIDNewHeap, true, attrs->isPrimary, InvalidOid); ! } } static Oid *************** *** 173,214 **** return OIDNewHeap; } - - static Oid - copy_index(Oid OIDOldIndex, Oid OIDNewHeap, const char *NewIndexName) - { - Oid OIDNewIndex; - Relation OldIndex, - NewHeap; - IndexInfo *indexInfo; - - NewHeap = heap_open(OIDNewHeap, AccessExclusiveLock); - OldIndex = index_open(OIDOldIndex); - - /* - * Create a new index like the old one. To do this I get the info - * from pg_index, and add a new index with a temporary name (that will - * be changed later). - */ - indexInfo = BuildIndexInfo(OldIndex->rd_index); - - OIDNewIndex = index_create(OIDNewHeap, - NewIndexName, - indexInfo, - OldIndex->rd_rel->relam, - OldIndex->rd_index->indclass, - OldIndex->rd_index->indisprimary, - allowSystemTableMods); - - setRelhasindex(OIDNewHeap, true, - OldIndex->rd_index->indisprimary, InvalidOid); - - index_close(OldIndex); - heap_close(NewHeap, NoLock); - - return OIDNewIndex; - } - static void rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex) --- 219,224 ----