diff options
author | Bruce Momjian <bruce@momjian.us> | 1999-09-23 17:03:39 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 1999-09-23 17:03:39 +0000 |
commit | e7cad7b0cbf88e2c0c5bf89957e60657561ffd70 (patch) | |
tree | 2d88ae4f0faeadd7796481f626364e81f116e956 /src/backend | |
parent | abd4bf13416e0dab832be4944d51de2f9e25f784 (diff) | |
download | postgresql-e7cad7b0cbf88e2c0c5bf89957e60657561ffd70.tar.gz postgresql-e7cad7b0cbf88e2c0c5bf89957e60657561ffd70.zip |
Add TRUNCATE command, with psql help and sgml additions.
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/heap.c | 232 | ||||
-rw-r--r-- | src/backend/commands/creatinh.c | 22 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 23 | ||||
-rw-r--r-- | src/backend/parser/keywords.c | 3 | ||||
-rw-r--r-- | src/backend/tcop/utility.c | 34 | ||||
-rw-r--r-- | src/backend/utils/mmgr/portalmem.c | 4 |
6 files changed, 309 insertions, 9 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 644f03eba87..e225a5834dc 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 * * -------------------------------- diff --git a/src/backend/commands/creatinh.c b/src/backend/commands/creatinh.c index c1069dd41e6..c146afa1db4 100644 --- a/src/backend/commands/creatinh.c +++ b/src/backend/commands/creatinh.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.46 1999/09/18 19:06:40 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.47 1999/09/23 17:02:40 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -157,6 +157,26 @@ RemoveRelation(char *name) heap_destroy_with_catalog(name); } +/* + * TruncateRelation -- + * Removes all the rows from a relation + * + * Exceptions: + * BadArg if name is invalid + * + * + * Note: + * Rows are removed, indices are truncated and reconstructed. + */ + +void +TruncateRelation(char *name) +{ + + AssertArg(name); + heap_truncate(name); + +} /* * MergeAttributes diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 20c33bc20c7..32c46e05d1c 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.98 1999/09/14 06:06:31 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.99 1999/09/23 17:02:46 momjian Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -122,6 +122,7 @@ Oid param_type(int t); /* used in parse_expr.c */ %type <node> stmt, AddAttrStmt, ClosePortalStmt, CopyStmt, CreateStmt, CreateAsStmt, CreateSeqStmt, DefineStmt, DestroyStmt, + TruncateStmt, ExtendStmt, FetchStmt, GrantStmt, CreateTrigStmt, DropTrigStmt, CreatePLangStmt, DropPLangStmt, IndexStmt, ListenStmt, UnlistenStmt, LockStmt, OptimizableStmt, @@ -318,7 +319,7 @@ Oid param_type(int t); /* used in parse_expr.c */ OFFSET, OIDS, OPERATOR, PASSWORD, PROCEDURAL, RENAME, RESET, RETURNS, ROW, RULE, SEQUENCE, SERIAL, SETOF, SHARE, SHOW, START, STATEMENT, STDIN, STDOUT, - TRUSTED, + TRUNCATE, TRUSTED, UNLISTEN, UNTIL, VACUUM, VALID, VERBOSE, VERSION /* Special keywords, not in the query language - see the "lex" file */ @@ -383,7 +384,8 @@ stmt : AddAttrStmt | CreateUserStmt | ClusterStmt | DefineStmt - | DestroyStmt + | DestroyStmt + | TruncateStmt | DropPLangStmt | DropTrigStmt | DropUserStmt @@ -1607,6 +1609,20 @@ DestroyStmt: DROP TABLE relation_name_list } ; +/***************************************************************************** + * + * QUERY: + * truncate table relname + * + *****************************************************************************/ + +TruncateStmt: TRUNCATE TABLE relation_name + { + TruncateStmt *n = makeNode(TruncateStmt); + n->relName = $3; + $$ = (Node *)n; + } + ; /***************************************************************************** * @@ -2371,7 +2387,6 @@ ClusterStmt: CLUSTER index_name ON relation_name } ; - /***************************************************************************** * * QUERY: diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c index bd5b43ad1fd..17a521337e4 100644 --- a/src/backend/parser/keywords.c +++ b/src/backend/parser/keywords.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.60 1999/07/17 20:17:22 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.61 1999/09/23 17:02:46 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -225,6 +225,7 @@ static ScanKeyword ScanKeywords[] = { {"trigger", TRIGGER}, {"trim", TRIM}, {"true", TRUE_P}, + {"truncate", TRUNCATE}, {"trusted", TRUSTED}, {"type", TYPE_P}, {"union", UNION}, diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 29b4fb527c6..26735a5d806 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.65 1999/09/18 19:07:44 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.66 1999/09/23 17:02:52 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -206,6 +206,38 @@ ProcessUtility(Node *parsetree, } break; + case T_TruncateStmt: + { + + Relation rel; + + PS_SET_STATUS(commandTag = "TRUNCATE"); + CHECK_IF_ABORTED(); + + relname = ((TruncateStmt *) parsetree)->relName; + if (!allowSystemTableMods && IsSystemRelationName(relname)) { + elog(ERROR, "TRUNCATE cannot be used on system tables. '%s' is a system table", + relname); + } + + rel = heap_openr(relname); + if (RelationIsValid(rel)) { + if (rel->rd_rel->relkind == RELKIND_SEQUENCE) { + elog(ERROR, "TRUNCATE cannot be used on sequences. '%s' is a sequence", + relname); + } + heap_close(rel); + } +#ifndef NO_SECURITY + if (!pg_ownercheck(userName, relname, RELNAME)) { + elog(ERROR, "you do not own class \"%s\"", relname); + } +#endif + TruncateRelation(((TruncateStmt *) parsetree)->relName); + + } + break; + case T_CopyStmt: { CopyStmt *stmt = (CopyStmt *) parsetree; diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c index d625d25d5bd..4120c24dd67 100644 --- a/src/backend/utils/mmgr/portalmem.c +++ b/src/backend/utils/mmgr/portalmem.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.29 1999/09/09 16:25:29 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.30 1999/09/23 17:02:58 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -410,6 +410,8 @@ PortalNameIsSpecial(char *pname) { if (strcmp(pname, VACPNAME) == 0) return true; + if (strcmp(pname, TRUNCPNAME) == 0) + return true; return false; } |