Back-port heap_deformtuple() into 7.4 branch; needed for planned fix for
authorTom Lane <[email protected]>
Sun, 6 Feb 2005 20:15:32 +0000 (20:15 +0000)
committerTom Lane <[email protected]>
Sun, 6 Feb 2005 20:15:32 +0000 (20:15 +0000)
CLUSTER failure after ALTER TABLE SET WITHOUT OIDS.

src/backend/access/common/heaptuple.c
src/include/access/heapam.h

index dad99b0059d32656aeaaceb127b7fc8e0331f04d..cd4e853fa6468ca4e84291df93b6f666343b88af 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.87 2003/09/25 06:57:56 petere Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.87.2.1 2005/02/06 20:15:32 tgl Exp $
  *
  * NOTES
  *   The old interface functions have been converted to macros
@@ -512,41 +512,6 @@ heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
    memcpy((char *) dest->t_data, (char *) src->t_data, src->t_len);
 }
 
-#ifdef NOT_USED
-/* ----------------
- *     heap_deformtuple
- *
- *     the inverse of heap_formtuple (see below)
- * ----------------
- */
-void
-heap_deformtuple(HeapTuple tuple,
-                TupleDesc tdesc,
-                Datum *values,
-                char *nulls)
-{
-   int         i;
-   int         natts;
-
-   Assert(HeapTupleIsValid(tuple));
-
-   natts = tuple->t_natts;
-   for (i = 0; i < natts; i++)
-   {
-       bool        isnull;
-
-       values[i] = heap_getattr(tuple,
-                                i + 1,
-                                tdesc,
-                                &isnull);
-       if (isnull)
-           nulls[i] = 'n';
-       else
-           nulls[i] = ' ';
-   }
-}
-#endif
-
 /* ----------------
  *     heap_formtuple
  *
@@ -712,6 +677,93 @@ heap_modifytuple(HeapTuple tuple,
    return newTuple;
 }
 
+/* ----------------
+ *     heap_deformtuple
+ *
+ *     Given a tuple, extract data into values/nulls arrays; this is
+ *     the inverse of heap_formtuple.
+ *
+ *     Storage for the values/nulls arrays is provided by the caller;
+ *     it should be sized according to tupleDesc->natts not tuple->t_natts.
+ *
+ *     Note that for pass-by-reference datatypes, the pointer placed
+ *     in the Datum will point into the given tuple.
+ *
+ *     When all or most of a tuple's fields need to be extracted,
+ *     this routine will be significantly quicker than a loop around
+ *     heap_getattr; the loop will become O(N^2) as soon as any
+ *     noncacheable attribute offsets are involved.
+ * ----------------
+ */
+void
+heap_deformtuple(HeapTuple tuple,
+                TupleDesc tupleDesc,
+                Datum *values,
+                char *nulls)
+{
+   HeapTupleHeader tup = tuple->t_data;
+   Form_pg_attribute *att = tupleDesc->attrs;
+   int         tdesc_natts = tupleDesc->natts;
+   int         natts;          /* number of atts to extract */
+   int         attnum;
+   char       *tp;             /* ptr to tuple data */
+   long        off;            /* offset in tuple data */
+   bits8      *bp = tup->t_bits;       /* ptr to null bitmask in tuple */
+   bool        slow = false;   /* can we use/set attcacheoff? */
+
+   natts = tup->t_natts;
+
+   /*
+    * In inheritance situations, it is possible that the given tuple
+    * actually has more fields than the caller is expecting.  Don't run
+    * off the end of the caller's arrays.
+    */
+   natts = Min(natts, tdesc_natts);
+
+   tp = (char *) tup + tup->t_hoff;
+
+   off = 0;
+
+   for (attnum = 0; attnum < natts; attnum++)
+   {
+       if (!HeapTupleNoNulls(tuple) && att_isnull(attnum, bp))
+       {
+           values[attnum] = (Datum) 0;
+           nulls[attnum] = 'n';
+           slow = true;        /* can't use attcacheoff anymore */
+           continue;
+       }
+
+       nulls[attnum] = ' ';
+
+       if (!slow && att[attnum]->attcacheoff >= 0)
+           off = att[attnum]->attcacheoff;
+       else
+       {
+           off = att_align(off, att[attnum]->attalign);
+
+           if (!slow)
+               att[attnum]->attcacheoff = off;
+       }
+
+       values[attnum] = fetchatt(att[attnum], tp + off);
+
+       off = att_addlength(off, att[attnum]->attlen, tp + off);
+
+       if (att[attnum]->attlen <= 0)
+           slow = true;        /* can't use attcacheoff anymore */
+   }
+
+   /*
+    * If tuple doesn't have all the atts indicated by tupleDesc, read the
+    * rest as null
+    */
+   for (; attnum < tdesc_natts; attnum++)
+   {
+       values[attnum] = (Datum) 0;
+       nulls[attnum] = 'n';
+   }
+}
 
 /* ----------------
  *     heap_freetuple
index ed46894d3a59ce6c9254cd6a489d63cceb03b358..2df812ef0073743d1a0c876ff8762dc858d0dca8 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: heapam.h,v 1.85 2003/10/01 21:30:52 tgl Exp $
+ * $Id: heapam.h,v 1.85.2.1 2005/02/06 20:15:29 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -192,6 +192,8 @@ extern HeapTuple heap_formtuple(TupleDesc tupleDescriptor,
               Datum *value, char *nulls);
 extern HeapTuple heap_modifytuple(HeapTuple tuple,
        Relation relation, Datum *replValue, char *replNull, char *repl);
+extern void heap_deformtuple(HeapTuple tuple, TupleDesc tupleDesc,
+                            Datum *values, char *nulls);
 extern void heap_freetuple(HeapTuple tuple);
 extern HeapTuple heap_addheader(int natts, bool withoid, Size structlen, void *structure);