11
11
*
12
12
*
13
13
* IDENTIFICATION
14
- * $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.131 2004/12/31 21:59:41 pgsql Exp $
14
+ * $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.132 2005/02/06 20:19:08 tgl Exp $
15
15
*
16
16
*-------------------------------------------------------------------------
17
17
*/
@@ -605,32 +605,80 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
605
605
Relation NewHeap ,
606
606
OldHeap ,
607
607
OldIndex ;
608
+ TupleDesc oldTupDesc ;
609
+ TupleDesc newTupDesc ;
610
+ int natts ;
611
+ Datum * values ;
612
+ char * nulls ;
608
613
IndexScanDesc scan ;
609
614
HeapTuple tuple ;
610
615
611
616
/*
612
- * Open the relations I need. Scan through the OldHeap on the OldIndex
613
- * and insert each tuple into the NewHeap.
617
+ * Open the relations we need.
614
618
*/
615
619
NewHeap = heap_open (OIDNewHeap , AccessExclusiveLock );
616
620
OldHeap = heap_open (OIDOldHeap , AccessExclusiveLock );
617
621
OldIndex = index_open (OIDOldIndex );
618
622
623
+ /*
624
+ * Their tuple descriptors should be exactly alike, but here we only
625
+ * need assume that they have the same number of columns.
626
+ */
627
+ oldTupDesc = RelationGetDescr (OldHeap );
628
+ newTupDesc = RelationGetDescr (NewHeap );
629
+ Assert (newTupDesc -> natts == oldTupDesc -> natts );
630
+
631
+ /* Preallocate values/nulls arrays */
632
+ natts = newTupDesc -> natts ;
633
+ values = (Datum * ) palloc0 (natts * sizeof (Datum ));
634
+ nulls = (char * ) palloc (natts * sizeof (char ));
635
+ memset (nulls , 'n' , natts * sizeof (char ));
636
+
637
+ /*
638
+ * Scan through the OldHeap on the OldIndex and copy each tuple into the
639
+ * NewHeap.
640
+ */
619
641
scan = index_beginscan (OldHeap , OldIndex , SnapshotNow , 0 , (ScanKey ) NULL );
620
642
621
643
while ((tuple = index_getnext (scan , ForwardScanDirection )) != NULL )
622
644
{
623
645
/*
624
- * We must copy the tuple because heap_insert() will overwrite the
625
- * commit-status fields of the tuple it's handed, and the
626
- * retrieved tuple will actually be in a disk buffer! Thus, the
627
- * source relation would get trashed, which is bad news if we
628
- * abort later on. (This was a bug in releases thru 7.0)
646
+ * We cannot simply pass the tuple to heap_insert(), for several
647
+ * reasons:
648
+ *
649
+ * 1. heap_insert() will overwrite the commit-status fields of the
650
+ * tuple it's handed. This would trash the source relation, which is
651
+ * bad news if we abort later on. (This was a bug in releases thru
652
+ * 7.0)
653
+ *
654
+ * 2. We'd like to squeeze out the values of any dropped columns,
655
+ * both to save space and to ensure we have no corner-case failures.
656
+ * (It's possible for example that the new table hasn't got a TOAST
657
+ * table and so is unable to store any large values of dropped cols.)
629
658
*
630
- * Note that the copied tuple will have the original OID, if any, so
631
- * this does preserve OIDs.
659
+ * 3. The tuple might not even be legal for the new table; this is
660
+ * currently only known to happen as an after-effect of ALTER TABLE
661
+ * SET WITHOUT OIDS.
662
+ *
663
+ * So, we must reconstruct the tuple from component Datums.
632
664
*/
633
- HeapTuple copiedTuple = heap_copytuple (tuple );
665
+ HeapTuple copiedTuple ;
666
+ int i ;
667
+
668
+ heap_deformtuple (tuple , oldTupDesc , values , nulls );
669
+
670
+ /* Be sure to null out any dropped columns */
671
+ for (i = 0 ; i < natts ; i ++ )
672
+ {
673
+ if (newTupDesc -> attrs [i ]-> attisdropped )
674
+ nulls [i ] = 'n' ;
675
+ }
676
+
677
+ copiedTuple = heap_formtuple (newTupDesc , values , nulls );
678
+
679
+ /* Preserve OID, if any */
680
+ if (NewHeap -> rd_rel -> relhasoids )
681
+ HeapTupleSetOid (copiedTuple , HeapTupleGetOid (tuple ));
634
682
635
683
simple_heap_insert (NewHeap , copiedTuple );
636
684
@@ -641,6 +689,9 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
641
689
642
690
index_endscan (scan );
643
691
692
+ pfree (values );
693
+ pfree (nulls );
694
+
644
695
index_close (OldIndex );
645
696
heap_close (OldHeap , NoLock );
646
697
heap_close (NewHeap , NoLock );
0 commit comments