*
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.160 2007/05/17 15:28:29 alvherre Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.161 2007/05/18 23:19:41 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 static void cluster_rel(RelToCluster *rv, bool recheck);
 static void rebuild_relation(Relation OldHeap, Oid indexOid);
-static void copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex);
+static TransactionId copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex);
 static List *get_tables_to_cluster(MemoryContext cluster_context);
 
 
    Oid         tableSpace = OldHeap->rd_rel->reltablespace;
    Oid         OIDNewHeap;
    char        NewHeapName[NAMEDATALEN];
+   TransactionId frozenXid;
    ObjectAddress object;
 
    /* Mark the correct index as clustered */
    /*
     * Copy the heap data into the new table in the desired order.
     */
-   copy_heap_data(OIDNewHeap, tableOid, indexOid);
+   frozenXid = copy_heap_data(OIDNewHeap, tableOid, indexOid);
 
    /* To make the new heap's data visible (probably not needed?). */
    CommandCounterIncrement();
 
    /* Swap the physical files of the old and new heaps. */
-   swap_relation_files(tableOid, OIDNewHeap);
+   swap_relation_files(tableOid, OIDNewHeap, frozenXid);
 
    CommandCounterIncrement();
 
 }
 
 /*
- * Do the physical copying of heap data.
+ * Do the physical copying of heap data.  Returns the TransactionId used as
+ * freeze cutoff point for the tuples.
  */
-static void
+static TransactionId
 copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
 {
    Relation    NewHeap,
    index_close(OldIndex, NoLock);
    heap_close(OldHeap, NoLock);
    heap_close(NewHeap, NoLock);
+
+   return FreezeXid;
 }
 
 /*
  *
  * Also swap any TOAST links, so that the toast data moves along with
  * the main-table data.
+ *
+ * Additionally, the first relation is marked with relfrozenxid set to
+ * frozenXid.  It seems a bit ugly to have this here, but all callers would
+ * have to do it anyway, so having it here saves a heap_update.  Note: the
+ * TOAST table needs no special handling, because since we swapped the links,
+ * the entry for the TOAST table will now contain RecentXmin in relfrozenxid,
+ * which is the correct value.
  */
 void
-swap_relation_files(Oid r1, Oid r2)
+swap_relation_files(Oid r1, Oid r2, TransactionId frozenXid)
 {
    Relation    relRelation;
    HeapTuple   reltup1,
 
    /* we should not swap reltoastidxid */
 
+   /* set rel1's frozen Xid */
+   Assert(TransactionIdIsNormal(frozenXid));
+   relform1->relfrozenxid = frozenXid;
+
    /* swap size statistics too, since new rel has freshly-updated stats */
    {
        int4        swap_pages;
 
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.224 2007/05/16 17:28:20 alvherre Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.225 2007/05/18 23:19:41 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
             */
            ATRewriteTable(tab, OIDNewHeap);
 
-           /* Swap the physical files of the old and new heaps. */
-           swap_relation_files(tab->relid, OIDNewHeap);
+           /*
+            * Swap the physical files of the old and new heaps.  Since we are
+            * generating a new heap, we can use RecentXmin for the table's new
+            * relfrozenxid because we rewrote all the tuples on
+            * ATRewriteTable, so no older Xid remains on the table.
+            */
+           swap_relation_files(tab->relid, OIDNewHeap, RecentXmin);
 
            CommandCounterIncrement();
 
 
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994-5, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/cluster.h,v 1.32 2007/03/13 00:33:43 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/commands/cluster.h,v 1.33 2007/05/18 23:19:42 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
 extern void mark_index_clustered(Relation rel, Oid indexOid);
 extern Oid make_new_heap(Oid OIDOldHeap, const char *NewName,
              Oid NewTableSpace);
-extern void swap_relation_files(Oid r1, Oid r2);
+extern void swap_relation_files(Oid r1, Oid r2, TransactionId frozenXid);
 
 #endif   /* CLUSTER_H */