*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.357 2009/08/02 22:14:52 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.358 2009/08/23 19:23:40 tgl Exp $
*
*
* INTERFACE ROUTINES
{
Oid rid = lfirst_oid(cell);
Relation rel;
- Oid toastrelid;
rel = heap_open(rid, AccessExclusiveLock);
relations = lappend(relations, rel);
-
- /* If there is a toast table, add it to the list too */
- toastrelid = rel->rd_rel->reltoastrelid;
- if (OidIsValid(toastrelid))
- {
- rel = heap_open(toastrelid, AccessExclusiveLock);
- relations = lappend(relations, rel);
- }
}
/* Don't allow truncate on tables that are referenced by foreign keys */
{
Relation rel = lfirst(cell);
- /* Truncate the actual file (and discard buffers) */
- RelationTruncate(rel, 0);
+ /* Truncate the relation */
+ heap_truncate_one_rel(rel);
- /* If this relation has indexes, truncate the indexes too */
- RelationTruncateIndexes(rel);
-
- /*
- * Close the relation, but keep exclusive lock on it until commit.
- */
+ /* Close the relation, but keep exclusive lock on it until commit */
heap_close(rel, NoLock);
}
}
+/*
+ * heap_truncate_one_rel
+ *
+ * This routine deletes all data within the specified relation.
+ *
+ * This is not transaction-safe, because the truncation is done immediately
+ * and cannot be rolled back later. Caller is responsible for having
+ * checked permissions etc, and must have obtained AccessExclusiveLock.
+ */
+void
+heap_truncate_one_rel(Relation rel)
+{
+ Oid toastrelid;
+
+ /* Truncate the actual file (and discard buffers) */
+ RelationTruncate(rel, 0);
+
+ /* If the relation has indexes, truncate the indexes too */
+ RelationTruncateIndexes(rel);
+
+ /* If there is a toast table, truncate that too */
+ toastrelid = rel->rd_rel->reltoastrelid;
+ if (OidIsValid(toastrelid))
+ {
+ Relation toastrel = heap_open(toastrelid, AccessExclusiveLock);
+
+ RelationTruncate(toastrel, 0);
+ RelationTruncateIndexes(toastrel);
+ /* keep the lock... */
+ heap_close(toastrel, NoLock);
+ }
+}
+
/*
* heap_truncate_check_FKs
* Check for foreign keys referencing a list of relations that
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.297 2009/08/12 23:00:12 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.298 2009/08/23 19:23:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
EState *estate;
ResultRelInfo *resultRelInfos;
ResultRelInfo *resultRelInfo;
+ SubTransactionId mySubid;
ListCell *cell;
/*
/*
* OK, truncate each table.
*/
+ mySubid = GetCurrentSubTransactionId();
+
foreach(cell, rels)
{
Relation rel = (Relation) lfirst(cell);
- Oid heap_relid;
- Oid toast_relid;
/*
- * Create a new empty storage file for the relation, and assign it as
- * the relfilenode value. The old storage file is scheduled for
- * deletion at commit.
+ * Normally, we need a transaction-safe truncation here. However,
+ * if the table was either created in the current (sub)transaction
+ * or has a new relfilenode in the current (sub)transaction, then
+ * we can just truncate it in-place, because a rollback would
+ * cause the whole table or the current physical file to be
+ * thrown away anyway.
*/
- setNewRelfilenode(rel, RecentXmin);
-
- heap_relid = RelationGetRelid(rel);
- toast_relid = rel->rd_rel->reltoastrelid;
-
- /*
- * The same for the toast table, if any.
- */
- if (OidIsValid(toast_relid))
+ if (rel->rd_createSubid == mySubid ||
+ rel->rd_newRelfilenodeSubid == mySubid)
{
- rel = relation_open(toast_relid, AccessExclusiveLock);
- setNewRelfilenode(rel, RecentXmin);
- heap_close(rel, NoLock);
+ /* Immediate, non-rollbackable truncation is OK */
+ heap_truncate_one_rel(rel);
}
+ else
+ {
+ Oid heap_relid;
+ Oid toast_relid;
- /*
- * Reconstruct the indexes to match, and we're done.
- */
- reindex_relation(heap_relid, true);
+ /*
+ * Need the full transaction-safe pushups.
+ *
+ * Create a new empty storage file for the relation, and assign it
+ * as the relfilenode value. The old storage file is scheduled for
+ * deletion at commit.
+ */
+ setNewRelfilenode(rel, RecentXmin);
+
+ heap_relid = RelationGetRelid(rel);
+ toast_relid = rel->rd_rel->reltoastrelid;
+
+ /*
+ * The same for the toast table, if any.
+ */
+ if (OidIsValid(toast_relid))
+ {
+ rel = relation_open(toast_relid, AccessExclusiveLock);
+ setNewRelfilenode(rel, RecentXmin);
+ heap_close(rel, NoLock);
+ }
+
+ /*
+ * Reconstruct the indexes to match, and we're done.
+ */
+ reindex_relation(heap_relid, true);
+ }
}
/*
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/heap.h,v 1.91 2009/06/11 14:49:09 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/heap.h,v 1.92 2009/08/23 19:23:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern void heap_truncate(List *relids);
+extern void heap_truncate_one_rel(Relation rel);
+
extern void heap_truncate_check_FKs(List *relations, bool tempTables);
extern List *heap_truncate_find_FKs(List *relationIds);