aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/tablecmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/tablecmds.c')
-rw-r--r--src/backend/commands/tablecmds.c67
1 files changed, 45 insertions, 22 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 07bc3932003..a36cbc51aff 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
@@ -775,6 +775,7 @@ ExecuteTruncate(TruncateStmt *stmt)
EState *estate;
ResultRelInfo *resultRelInfos;
ResultRelInfo *resultRelInfo;
+ SubTransactionId mySubid;
ListCell *cell;
/*
@@ -944,36 +945,58 @@ ExecuteTruncate(TruncateStmt *stmt)
/*
* 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);
+ }
}
/*