mirror of
https://github.com/postgres/postgres.git
synced 2025-11-12 05:01:15 +03:00
Add TRUNCATE command, with psql help and sgml additions.
This commit is contained in:
@@ -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"
|
||||
@@ -1056,6 +1059,233 @@ DeleteRelationTuple(Relation rel)
|
||||
heap_close(pg_class_desc, RowExclusiveLock);
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
* 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
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user