Prevent loss of init fork when truncating an unlogged table.
authorRobert Haas
Fri, 11 May 2012 13:46:42 +0000 (09:46 -0400)
committerRobert Haas
Fri, 11 May 2012 13:48:56 +0000 (09:48 -0400)
Fixes bug #6635, reported by Akira Kurosawa.

src/backend/catalog/heap.c
src/backend/commands/tablecmds.c
src/include/catalog/heap.h

index d029a25c11a375e71afa4a6bfbc0fe04445c0b43..2734ec865823a1501b7fc0dfcc0699f8c38f98ee 100644 (file)
@@ -1306,24 +1306,10 @@ heap_create_with_catalog(const char *relname,
    if (oncommit != ONCOMMIT_NOOP)
        register_on_commit_action(relid, oncommit);
 
-   /*
-    * If this is an unlogged relation, it needs an init fork so that it can
-    * be correctly reinitialized on restart.  Since we're going to do an
-    * immediate sync, we only need to xlog this if archiving or streaming is
-    * enabled.  And the immediate sync is required, because otherwise there's
-    * no guarantee that this will hit the disk before the next checkpoint
-    * moves the redo pointer.
-    */
    if (relpersistence == RELPERSISTENCE_UNLOGGED)
    {
        Assert(relkind == RELKIND_RELATION || relkind == RELKIND_TOASTVALUE);
-
-       RelationOpenSmgr(new_rel_desc);
-       smgrcreate(new_rel_desc->rd_smgr, INIT_FORKNUM, false);
-       if (XLogIsNeeded())
-           log_smgrcreate(&new_rel_desc->rd_smgr->smgr_rnode.node,
-                          INIT_FORKNUM);
-       smgrimmedsync(new_rel_desc->rd_smgr, INIT_FORKNUM);
+       heap_create_init_fork(new_rel_desc);
    }
 
    /*
@@ -1336,6 +1322,22 @@ heap_create_with_catalog(const char *relname,
    return relid;
 }
 
+/*
+ * Set up an init fork for an unlogged table so that it can be correctly
+ * reinitialized on restart.  Since we're going to do an immediate sync, we
+ * only need to xlog this if archiving or streaming is enabled.  And the
+ * immediate sync is required, because otherwise there's no guarantee that
+ * this will hit the disk before the next checkpoint moves the redo pointer.
+ */
+void
+heap_create_init_fork(Relation rel)
+{
+   RelationOpenSmgr(rel);
+   smgrcreate(rel->rd_smgr, INIT_FORKNUM, false);
+   if (XLogIsNeeded())
+       log_smgrcreate(&rel->rd_smgr->smgr_rnode.node, INIT_FORKNUM);
+   smgrimmedsync(rel->rd_smgr, INIT_FORKNUM);
+}
 
 /*
  *     RelationRemoveInheritance
index c94d9457223431c7419034fa53a63df03f668d2c..e23a3dab3cd0eceb9fe7e62373b71c0cfe607495 100644 (file)
@@ -1155,6 +1155,8 @@ ExecuteTruncate(TruncateStmt *stmt)
             * deletion at commit.
             */
            RelationSetNewRelfilenode(rel, RecentXmin);
+           if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
+               heap_create_init_fork(rel);
 
            heap_relid = RelationGetRelid(rel);
            toast_relid = rel->rd_rel->reltoastrelid;
@@ -1166,6 +1168,8 @@ ExecuteTruncate(TruncateStmt *stmt)
            {
                rel = relation_open(toast_relid, AccessExclusiveLock);
                RelationSetNewRelfilenode(rel, RecentXmin);
+               if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
+                   heap_create_init_fork(rel);
                heap_close(rel, NoLock);
            }
 
index c0deab73ae616a9ba82add7590f3776fc0bbedfc..bc98d5d6fc1e789619ee04a4237f3e272a431eca 100644 (file)
@@ -69,6 +69,8 @@ extern Oid heap_create_with_catalog(const char *relname,
                         bool use_user_acl,
                         bool allow_system_table_mods);
 
+extern void heap_create_init_fork(Relation rel);
+
 extern void heap_drop_with_catalog(Oid relid);
 
 extern void heap_truncate(List *relids);