]> granicus.if.org Git - postgresql/commitdiff
Prevent loss of init fork when truncating an unlogged table.
authorRobert Haas <rhaas@postgresql.org>
Fri, 11 May 2012 13:46:42 +0000 (09:46 -0400)
committerRobert Haas <rhaas@postgresql.org>
Fri, 11 May 2012 13:48:54 +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 384e90de7c5ace7d89f7b6791f6e9da86559ce0e..8cb313ed8568396b7b8b0d57a94e4fc930506888 100644 (file)
@@ -1290,24 +1290,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);
        }
 
        /*
@@ -1320,6 +1306,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 8f569ed0bd63dbba59dd6ef55e39631b0befc49c..11f57b2758db86ba09b615bc449dab14b2e810f8 100644 (file)
@@ -1059,6 +1059,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;
@@ -1070,6 +1072,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 c95e91303b8873633a9460e9b85ce24df21b45b1..213441e4cc24d58f4766099539d27f4a7e9b5d4b 100644 (file)
@@ -65,6 +65,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);