diff options
Diffstat (limited to 'src/backend/catalog/heap.c')
| -rw-r--r-- | src/backend/catalog/heap.c | 232 |
1 files changed, 231 insertions, 1 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 644f03eba8..e225a5834d 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.96 1999/09/18 19:06:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.97 1999/09/23 17:02:34 momjian Exp $ * * * INTERFACE ROUTINES @@ -30,6 +30,7 @@ #include "miscadmin.h" #include "access/heapam.h" +#include "access/genam.h" #include "access/xact.h" #include "catalog/catalog.h" #include "catalog/catname.h" @@ -40,6 +41,7 @@ #include "catalog/pg_index.h" #include "catalog/pg_inherits.h" #include "catalog/pg_ipl.h" +#include "catalog/pg_proc.h" #include "catalog/pg_relcheck.h" #include "commands/trigger.h" #include "optimizer/tlist.h" @@ -49,6 +51,7 @@ #include "storage/smgr.h" #include "tcop/tcopprot.h" #include "utils/builtins.h" +#include "utils/portal.h" #include "utils/relcache.h" #include "utils/syscache.h" #include "utils/temprel.h" @@ -1057,6 +1060,233 @@ DeleteRelationTuple(Relation rel) } /* -------------------------------- + * RelationTruncateIndexes - This routine is used to truncate all + * indices associated with the heap relation to zero tuples. + * The routine will truncate and then reconstruct the indices on + * the relation specified by the heapRelation parameter. + * -------------------------------- +*/ + +static void +RelationTruncateIndexes(Relation heapRelation) { + + Relation indexRelation, currentIndex; + ScanKeyData entry; + HeapScanDesc scan; + HeapTuple indexTuple, procTuple, classTuple; + Form_pg_index index; + Oid heapId, indexId, procId, accessMethodId; + Node *oldPred = NULL; + PredInfo *predInfo; + List *cnfPred = NULL; + AttrNumber *attributeNumberA; + FuncIndexInfo fInfo, *funcInfo = NULL; + int i, numberOfAttributes; + char *predString; + + /*** Save the id of the heap relation ***/ + + heapId = RelationGetRelid(heapRelation); + + /*** Open the System relation, pg_index ***/ + + indexRelation = heap_openr(IndexRelationName); + + /*** Scan pg_index For indexes related to heap relation ***/ + + ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_index_indrelid, F_OIDEQ, + ObjectIdGetDatum(heapId)); + + scan = heap_beginscan(indexRelation, false, SnapshotNow, 1, &entry); + while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0))) { + + /*** For each index, fetch index attributes ***/ + + index = (Form_pg_index) GETSTRUCT(indexTuple); + indexId = index->indexrelid; + procId = index->indproc; + + for (i = 0; i < INDEX_MAX_KEYS; i++) { + if (index->indkey[i] == InvalidAttrNumber) break; + } + numberOfAttributes = i; + + /*** If a valid where predicate, compute predicate Node ***/ + + if (VARSIZE(&index->indpred) != 0) { + predString = fmgr(F_TEXTOUT, &index->indpred); + oldPred = stringToNode(predString); + pfree(predString); + } + + predInfo = (PredInfo *) palloc(sizeof(PredInfo)); + predInfo->pred = (Node *) cnfPred; + /* predInfo->pred = (Node *) oldPred; */ + predInfo->oldPred = oldPred; + + /*** Assign Index keys to attributes array ***/ + + attributeNumberA = (AttrNumber *) palloc(numberOfAttributes * + sizeof(attributeNumberA[0])); + for (i = 0; i < numberOfAttributes; i++) { + attributeNumberA[i] = index->indkey[i]; + } + + /*** If this is a procedural index, initialize our FuncIndexInfo ***/ + + if (procId != InvalidOid) { + funcInfo = &fInfo; + FIsetnArgs(funcInfo, numberOfAttributes); + procTuple = SearchSysCacheTuple(PROOID, ObjectIdGetDatum(procId), + 0, 0, 0); + if (!HeapTupleIsValid(procTuple)) { + elog(ERROR, "RelationTruncateIndexes: index procedure not found"); + } + namecpy(&(funcInfo->funcName), + &(((Form_pg_proc) GETSTRUCT(procTuple))->proname)); + FIsetProcOid(funcInfo, procTuple->t_data->t_oid); + } + + /*** Fetch the classTuple associated with this index ***/ + + classTuple = SearchSysCacheTupleCopy(RELOID, ObjectIdGetDatum(indexId), + 0, 0, 0); + if (!HeapTupleIsValid(classTuple)) { + elog(ERROR, "RelationTruncateIndexes: index access method not found"); + } + accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam; + + /*** Open our index relation ***/ + + currentIndex = index_open(indexId); + if (currentIndex == NULL) { + elog(ERROR, "RelationTruncateIndexes: can't open index relation"); + } + + /*** Truncate the index before building ***/ + + smgrtruncate(DEFAULT_SMGR, currentIndex, 0); + currentIndex->rd_nblocks = 0; + + /*** Initialize the index and rebuild ***/ + + InitIndexStrategy(numberOfAttributes, currentIndex, accessMethodId); + index_build(heapRelation, currentIndex, numberOfAttributes, + attributeNumberA, 0, NULL, funcInfo, predInfo); + + /*** Re-open our heap relation and re-lock, since index_build ***/ + /*** will close and unlock the relation ***/ + + heapRelation = heap_open(heapId); + LockRelation(heapRelation, AccessExclusiveLock); + + /*** RelationUnsetLockForWrite(currentIndex); ***/ + + } + + /*** Complete the scan and close the Catalogueindex Relation ***/ + + heap_endscan(scan); + heap_close(indexRelation); + +} + +/* ---------------------------- + * heap_truncate + * + * This routine is used to truncate the data from the + * storange manager of any data within the relation handed + * to this routine. The routine assumes that the relation + * handed to this routine is an open relation. + * + * ---------------------------- + */ + +void +heap_truncate(char *relname) { + + Relation rel; + Oid rid; + Portal portal; + char *pname; + MemoryContext old; + PortalVariableMemory pmem; + NameData truncRel; + + /* + * Create a portal for safe memory across transctions. We need to + * palloc the name space for it because our hash function expects the + * name to be on a longword boundary. CreatePortal copies the name to + * safe storage for us. + */ + + pname = (char *) palloc(strlen(TRUNCPNAME) + 1); + strcpy(pname, TRUNCPNAME); + portal = CreatePortal(pname); + pfree(pname); + + /* relname gets de-allocated on transaction commit */ + + strcpy(truncRel.data, relname); + + pmem = PortalGetVariableMemory(portal); + old = MemoryContextSwitchTo((MemoryContext) pmem); + MemoryContextSwitchTo(old); + + /* Commit the current transaction */ + + CommitTransactionCommand(); + StartTransactionCommand(); + + /* Open relation for processing */ + + rel = heap_openr(truncRel.data); + if (rel == NULL) + elog(ERROR, "Relation %s Does Not Exist!", truncRel.data); + rid = rel->rd_id; + + LockRelation(rel, AccessExclusiveLock); + + /* Release any buffers associated with this relation */ + + ReleaseRelationBuffers(rel); + BlowawayRelationBuffers(rel, 0); + + /* Now truncate the actual data and set blocks to zero */ + + smgrtruncate(DEFAULT_SMGR, rel, 0); + rel->rd_nblocks = 0; + + /* If this relation has indexes, truncate the indexes, which */ + /* will unlock the relation as a result. Otherwise, unlock */ + /* the relation ourselves. */ + + if (rel->rd_rel->relhasindex) { + RelationTruncateIndexes(rel); + } else { + UnlockRelation(rel, AccessExclusiveLock); + } + + /* Close our relation */ + + heap_close(rel); + RelationForgetRelation(rid); + + /* Destoy cross-transaction memory */ + + PortalDestroy(&portal); + + /* Start new transaction */ + + CommitTransactionCommand(); + StartTransactionCommand(); + + return; + +} + + +/* -------------------------------- * DeleteAttributeTuples * * -------------------------------- |
