Index: src/backend/commands/cluster.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/commands/cluster.c,v
retrieving revision 1.160
diff -c -p -r1.160 cluster.c
*** src/backend/commands/cluster.c	17 May 2007 15:28:29 -0000	1.160
--- src/backend/commands/cluster.c	18 May 2007 01:01:45 -0000
*************** typedef struct
*** 55,61 ****
  
  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 List *get_tables_to_cluster(MemoryContext cluster_context);
  
  
--- 55,61 ----
  
  static void cluster_rel(RelToCluster *rv, bool recheck);
  static void rebuild_relation(Relation OldHeap, Oid indexOid);
! static TransactionId copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex);
  static List *get_tables_to_cluster(MemoryContext cluster_context);
  
  
*************** rebuild_relation(Relation OldHeap, Oid i
*** 513,518 ****
--- 513,519 ----
  	Oid			tableSpace = OldHeap->rd_rel->reltablespace;
  	Oid			OIDNewHeap;
  	char		NewHeapName[NAMEDATALEN];
+ 	TransactionId frozenXid;
  	ObjectAddress object;
  
  	/* Mark the correct index as clustered */
*************** rebuild_relation(Relation OldHeap, Oid i
*** 539,551 ****
  	/*
  	 * Copy the heap data into the new table in the desired order.
  	 */
! 	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);
  
  	CommandCounterIncrement();
  
--- 540,552 ----
  	/*
  	 * Copy the heap data into the new table in the desired order.
  	 */
! 	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, frozenXid);
  
  	CommandCounterIncrement();
  
*************** make_new_heap(Oid OIDOldHeap, const char
*** 641,649 ****
  }
  
  /*
!  * Do the physical copying of heap data.
   */
! static void
  copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
  {
  	Relation	NewHeap,
--- 642,651 ----
  }
  
  /*
!  * Do the physical copying of heap data.  Returns the TransactionId used as
!  * freeze cutoff point for the tuples.
   */
! static TransactionId
  copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
  {
  	Relation	NewHeap,
*************** copy_heap_data(Oid OIDNewHeap, Oid OIDOl
*** 816,821 ****
--- 818,825 ----
  	index_close(OldIndex, NoLock);
  	heap_close(OldHeap, NoLock);
  	heap_close(NewHeap, NoLock);
+ 
+ 	return FreezeXid;
  }
  
  /*
*************** copy_heap_data(Oid OIDNewHeap, Oid OIDOl
*** 826,834 ****
   *
   * Also swap any TOAST links, so that the toast data moves along with
   * the main-table data.
   */
  void
! swap_relation_files(Oid r1, Oid r2)
  {
  	Relation	relRelation;
  	HeapTuple	reltup1,
--- 830,845 ----
   *
   * 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, TransactionId frozenXid)
  {
  	Relation	relRelation;
  	HeapTuple	reltup1,
*************** swap_relation_files(Oid r1, Oid r2)
*** 872,877 ****
--- 883,891 ----
  
  	/* we should not swap reltoastidxid */
  
+ 	/* set rel1's frozen Xid */
+ 	relform1->relfrozenxid = frozenXid;
+ 
  	/* swap size statistics too, since new rel has freshly-updated stats */
  	{
  		int4		swap_pages;
Index: src/backend/commands/tablecmds.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/commands/tablecmds.c,v
retrieving revision 1.224
diff -c -p -r1.224 tablecmds.c
*** src/backend/commands/tablecmds.c	16 May 2007 17:28:20 -0000	1.224
--- src/backend/commands/tablecmds.c	18 May 2007 00:08:51 -0000
*************** ATRewriteTables(List **wqueue)
*** 2285,2292 ****
  			 */
  			ATRewriteTable(tab, OIDNewHeap);
  
! 			/* Swap the physical files of the old and new heaps. */
! 			swap_relation_files(tab->relid, OIDNewHeap);
  
  			CommandCounterIncrement();
  
--- 2285,2297 ----
  			 */
  			ATRewriteTable(tab, 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();
  
Index: src/include/commands/cluster.h
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/include/commands/cluster.h,v
retrieving revision 1.32
diff -c -p -r1.32 cluster.h
*** src/include/commands/cluster.h	13 Mar 2007 00:33:43 -0000	1.32
--- src/include/commands/cluster.h	18 May 2007 00:22:26 -0000
*************** extern void check_index_is_clusterable(R
*** 24,29 ****
  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);
  
  #endif   /* CLUSTER_H */
--- 24,29 ----
  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, TransactionId frozenXid);
  
  #endif   /* CLUSTER_H */
