Header And Logo

PostgreSQL
| The world's most advanced open source database.

heaptuple.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * heaptuple.c
00004  *    This file contains heap tuple accessor and mutator routines, as well
00005  *    as various tuple utilities.
00006  *
00007  * Some notes about varlenas and this code:
00008  *
00009  * Before Postgres 8.3 varlenas always had a 4-byte length header, and
00010  * therefore always needed 4-byte alignment (at least).  This wasted space
00011  * for short varlenas, for example CHAR(1) took 5 bytes and could need up to
00012  * 3 additional padding bytes for alignment.
00013  *
00014  * Now, a short varlena (up to 126 data bytes) is reduced to a 1-byte header
00015  * and we don't align it.  To hide this from datatype-specific functions that
00016  * don't want to deal with it, such a datum is considered "toasted" and will
00017  * be expanded back to the normal 4-byte-header format by pg_detoast_datum.
00018  * (In performance-critical code paths we can use pg_detoast_datum_packed
00019  * and the appropriate access macros to avoid that overhead.)  Note that this
00020  * conversion is performed directly in heap_form_tuple, without invoking
00021  * tuptoaster.c.
00022  *
00023  * This change will break any code that assumes it needn't detoast values
00024  * that have been put into a tuple but never sent to disk.  Hopefully there
00025  * are few such places.
00026  *
00027  * Varlenas still have alignment 'i' (or 'd') in pg_type/pg_attribute, since
00028  * that's the normal requirement for the untoasted format.  But we ignore that
00029  * for the 1-byte-header format.  This means that the actual start position
00030  * of a varlena datum may vary depending on which format it has.  To determine
00031  * what is stored, we have to require that alignment padding bytes be zero.
00032  * (Postgres actually has always zeroed them, but now it's required!)  Since
00033  * the first byte of a 1-byte-header varlena can never be zero, we can examine
00034  * the first byte after the previous datum to tell if it's a pad byte or the
00035  * start of a 1-byte-header varlena.
00036  *
00037  * Note that while formerly we could rely on the first varlena column of a
00038  * system catalog to be at the offset suggested by the C struct for the
00039  * catalog, this is now risky: it's only safe if the preceding field is
00040  * word-aligned, so that there will never be any padding.
00041  *
00042  * We don't pack varlenas whose attstorage is 'p', since the data type
00043  * isn't expecting to have to detoast values.  This is used in particular
00044  * by oidvector and int2vector, which are used in the system catalogs
00045  * and we'd like to still refer to them via C struct offsets.
00046  *
00047  *
00048  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00049  * Portions Copyright (c) 1994, Regents of the University of California
00050  *
00051  *
00052  * IDENTIFICATION
00053  *    src/backend/access/common/heaptuple.c
00054  *
00055  *-------------------------------------------------------------------------
00056  */
00057 
00058 #include "postgres.h"
00059 
00060 #include "access/sysattr.h"
00061 #include "access/tuptoaster.h"
00062 #include "executor/tuptable.h"
00063 
00064 
00065 /* Does att's datatype allow packing into the 1-byte-header varlena format? */
00066 #define ATT_IS_PACKABLE(att) \
00067     ((att)->attlen == -1 && (att)->attstorage != 'p')
00068 /* Use this if it's already known varlena */
00069 #define VARLENA_ATT_IS_PACKABLE(att) \
00070     ((att)->attstorage != 'p')
00071 
00072 
00073 /* ----------------------------------------------------------------
00074  *                      misc support routines
00075  * ----------------------------------------------------------------
00076  */
00077 
00078 
00079 /*
00080  * heap_compute_data_size
00081  *      Determine size of the data area of a tuple to be constructed
00082  */
00083 Size
00084 heap_compute_data_size(TupleDesc tupleDesc,
00085                        Datum *values,
00086                        bool *isnull)
00087 {
00088     Size        data_length = 0;
00089     int         i;
00090     int         numberOfAttributes = tupleDesc->natts;
00091     Form_pg_attribute *att = tupleDesc->attrs;
00092 
00093     for (i = 0; i < numberOfAttributes; i++)
00094     {
00095         Datum       val;
00096 
00097         if (isnull[i])
00098             continue;
00099 
00100         val = values[i];
00101 
00102         if (ATT_IS_PACKABLE(att[i]) &&
00103             VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
00104         {
00105             /*
00106              * we're anticipating converting to a short varlena header, so
00107              * adjust length and don't count any alignment
00108              */
00109             data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
00110         }
00111         else
00112         {
00113             data_length = att_align_datum(data_length, att[i]->attalign,
00114                                           att[i]->attlen, val);
00115             data_length = att_addlength_datum(data_length, att[i]->attlen,
00116                                               val);
00117         }
00118     }
00119 
00120     return data_length;
00121 }
00122 
00123 /*
00124  * heap_fill_tuple
00125  *      Load data portion of a tuple from values/isnull arrays
00126  *
00127  * We also fill the null bitmap (if any) and set the infomask bits
00128  * that reflect the tuple's data contents.
00129  *
00130  * NOTE: it is now REQUIRED that the caller have pre-zeroed the data area.
00131  */
00132 void
00133 heap_fill_tuple(TupleDesc tupleDesc,
00134                 Datum *values, bool *isnull,
00135                 char *data, Size data_size,
00136                 uint16 *infomask, bits8 *bit)
00137 {
00138     bits8      *bitP;
00139     int         bitmask;
00140     int         i;
00141     int         numberOfAttributes = tupleDesc->natts;
00142     Form_pg_attribute *att = tupleDesc->attrs;
00143 
00144 #ifdef USE_ASSERT_CHECKING
00145     char       *start = data;
00146 #endif
00147 
00148     if (bit != NULL)
00149     {
00150         bitP = &bit[-1];
00151         bitmask = HIGHBIT;
00152     }
00153     else
00154     {
00155         /* just to keep compiler quiet */
00156         bitP = NULL;
00157         bitmask = 0;
00158     }
00159 
00160     *infomask &= ~(HEAP_HASNULL | HEAP_HASVARWIDTH | HEAP_HASEXTERNAL);
00161 
00162     for (i = 0; i < numberOfAttributes; i++)
00163     {
00164         Size        data_length;
00165 
00166         if (bit != NULL)
00167         {
00168             if (bitmask != HIGHBIT)
00169                 bitmask <<= 1;
00170             else
00171             {
00172                 bitP += 1;
00173                 *bitP = 0x0;
00174                 bitmask = 1;
00175             }
00176 
00177             if (isnull[i])
00178             {
00179                 *infomask |= HEAP_HASNULL;
00180                 continue;
00181             }
00182 
00183             *bitP |= bitmask;
00184         }
00185 
00186         /*
00187          * XXX we use the att_align macros on the pointer value itself, not on
00188          * an offset.  This is a bit of a hack.
00189          */
00190 
00191         if (att[i]->attbyval)
00192         {
00193             /* pass-by-value */
00194             data = (char *) att_align_nominal(data, att[i]->attalign);
00195             store_att_byval(data, values[i], att[i]->attlen);
00196             data_length = att[i]->attlen;
00197         }
00198         else if (att[i]->attlen == -1)
00199         {
00200             /* varlena */
00201             Pointer     val = DatumGetPointer(values[i]);
00202 
00203             *infomask |= HEAP_HASVARWIDTH;
00204             if (VARATT_IS_EXTERNAL(val))
00205             {
00206                 *infomask |= HEAP_HASEXTERNAL;
00207                 /* no alignment, since it's short by definition */
00208                 data_length = VARSIZE_EXTERNAL(val);
00209                 memcpy(data, val, data_length);
00210             }
00211             else if (VARATT_IS_SHORT(val))
00212             {
00213                 /* no alignment for short varlenas */
00214                 data_length = VARSIZE_SHORT(val);
00215                 memcpy(data, val, data_length);
00216             }
00217             else if (VARLENA_ATT_IS_PACKABLE(att[i]) &&
00218                      VARATT_CAN_MAKE_SHORT(val))
00219             {
00220                 /* convert to short varlena -- no alignment */
00221                 data_length = VARATT_CONVERTED_SHORT_SIZE(val);
00222                 SET_VARSIZE_SHORT(data, data_length);
00223                 memcpy(data + 1, VARDATA(val), data_length - 1);
00224             }
00225             else
00226             {
00227                 /* full 4-byte header varlena */
00228                 data = (char *) att_align_nominal(data,
00229                                                   att[i]->attalign);
00230                 data_length = VARSIZE(val);
00231                 memcpy(data, val, data_length);
00232             }
00233         }
00234         else if (att[i]->attlen == -2)
00235         {
00236             /* cstring ... never needs alignment */
00237             *infomask |= HEAP_HASVARWIDTH;
00238             Assert(att[i]->attalign == 'c');
00239             data_length = strlen(DatumGetCString(values[i])) + 1;
00240             memcpy(data, DatumGetPointer(values[i]), data_length);
00241         }
00242         else
00243         {
00244             /* fixed-length pass-by-reference */
00245             data = (char *) att_align_nominal(data, att[i]->attalign);
00246             Assert(att[i]->attlen > 0);
00247             data_length = att[i]->attlen;
00248             memcpy(data, DatumGetPointer(values[i]), data_length);
00249         }
00250 
00251         data += data_length;
00252     }
00253 
00254     Assert((data - start) == data_size);
00255 }
00256 
00257 
00258 /* ----------------------------------------------------------------
00259  *                      heap tuple interface
00260  * ----------------------------------------------------------------
00261  */
00262 
00263 /* ----------------
00264  *      heap_attisnull  - returns TRUE iff tuple attribute is not present
00265  * ----------------
00266  */
00267 bool
00268 heap_attisnull(HeapTuple tup, int attnum)
00269 {
00270     if (attnum > (int) HeapTupleHeaderGetNatts(tup->t_data))
00271         return true;
00272 
00273     if (attnum > 0)
00274     {
00275         if (HeapTupleNoNulls(tup))
00276             return false;
00277         return att_isnull(attnum - 1, tup->t_data->t_bits);
00278     }
00279 
00280     switch (attnum)
00281     {
00282         case TableOidAttributeNumber:
00283         case SelfItemPointerAttributeNumber:
00284         case ObjectIdAttributeNumber:
00285         case MinTransactionIdAttributeNumber:
00286         case MinCommandIdAttributeNumber:
00287         case MaxTransactionIdAttributeNumber:
00288         case MaxCommandIdAttributeNumber:
00289             /* these are never null */
00290             break;
00291 
00292         default:
00293             elog(ERROR, "invalid attnum: %d", attnum);
00294     }
00295 
00296     return false;
00297 }
00298 
00299 /* ----------------
00300  *      nocachegetattr
00301  *
00302  *      This only gets called from fastgetattr() macro, in cases where
00303  *      we can't use a cacheoffset and the value is not null.
00304  *
00305  *      This caches attribute offsets in the attribute descriptor.
00306  *
00307  *      An alternative way to speed things up would be to cache offsets
00308  *      with the tuple, but that seems more difficult unless you take
00309  *      the storage hit of actually putting those offsets into the
00310  *      tuple you send to disk.  Yuck.
00311  *
00312  *      This scheme will be slightly slower than that, but should
00313  *      perform well for queries which hit large #'s of tuples.  After
00314  *      you cache the offsets once, examining all the other tuples using
00315  *      the same attribute descriptor will go much quicker. -cim 5/4/91
00316  *
00317  *      NOTE: if you need to change this code, see also heap_deform_tuple.
00318  *      Also see nocache_index_getattr, which is the same code for index
00319  *      tuples.
00320  * ----------------
00321  */
00322 Datum
00323 nocachegetattr(HeapTuple tuple,
00324                int attnum,
00325                TupleDesc tupleDesc)
00326 {
00327     HeapTupleHeader tup = tuple->t_data;
00328     Form_pg_attribute *att = tupleDesc->attrs;
00329     char       *tp;             /* ptr to data part of tuple */
00330     bits8      *bp = tup->t_bits;       /* ptr to null bitmap in tuple */
00331     bool        slow = false;   /* do we have to walk attrs? */
00332     int         off;            /* current offset within data */
00333 
00334     /* ----------------
00335      *   Three cases:
00336      *
00337      *   1: No nulls and no variable-width attributes.
00338      *   2: Has a null or a var-width AFTER att.
00339      *   3: Has nulls or var-widths BEFORE att.
00340      * ----------------
00341      */
00342 
00343     attnum--;
00344 
00345     if (!HeapTupleNoNulls(tuple))
00346     {
00347         /*
00348          * there's a null somewhere in the tuple
00349          *
00350          * check to see if any preceding bits are null...
00351          */
00352         int         byte = attnum >> 3;
00353         int         finalbit = attnum & 0x07;
00354 
00355         /* check for nulls "before" final bit of last byte */
00356         if ((~bp[byte]) & ((1 << finalbit) - 1))
00357             slow = true;
00358         else
00359         {
00360             /* check for nulls in any "earlier" bytes */
00361             int         i;
00362 
00363             for (i = 0; i < byte; i++)
00364             {
00365                 if (bp[i] != 0xFF)
00366                 {
00367                     slow = true;
00368                     break;
00369                 }
00370             }
00371         }
00372     }
00373 
00374     tp = (char *) tup + tup->t_hoff;
00375 
00376     if (!slow)
00377     {
00378         /*
00379          * If we get here, there are no nulls up to and including the target
00380          * attribute.  If we have a cached offset, we can use it.
00381          */
00382         if (att[attnum]->attcacheoff >= 0)
00383         {
00384             return fetchatt(att[attnum],
00385                             tp + att[attnum]->attcacheoff);
00386         }
00387 
00388         /*
00389          * Otherwise, check for non-fixed-length attrs up to and including
00390          * target.  If there aren't any, it's safe to cheaply initialize the
00391          * cached offsets for these attrs.
00392          */
00393         if (HeapTupleHasVarWidth(tuple))
00394         {
00395             int         j;
00396 
00397             for (j = 0; j <= attnum; j++)
00398             {
00399                 if (att[j]->attlen <= 0)
00400                 {
00401                     slow = true;
00402                     break;
00403                 }
00404             }
00405         }
00406     }
00407 
00408     if (!slow)
00409     {
00410         int         natts = tupleDesc->natts;
00411         int         j = 1;
00412 
00413         /*
00414          * If we get here, we have a tuple with no nulls or var-widths up to
00415          * and including the target attribute, so we can use the cached offset
00416          * ... only we don't have it yet, or we'd not have got here.  Since
00417          * it's cheap to compute offsets for fixed-width columns, we take the
00418          * opportunity to initialize the cached offsets for *all* the leading
00419          * fixed-width columns, in hope of avoiding future visits to this
00420          * routine.
00421          */
00422         att[0]->attcacheoff = 0;
00423 
00424         /* we might have set some offsets in the slow path previously */
00425         while (j < natts && att[j]->attcacheoff > 0)
00426             j++;
00427 
00428         off = att[j - 1]->attcacheoff + att[j - 1]->attlen;
00429 
00430         for (; j < natts; j++)
00431         {
00432             if (att[j]->attlen <= 0)
00433                 break;
00434 
00435             off = att_align_nominal(off, att[j]->attalign);
00436 
00437             att[j]->attcacheoff = off;
00438 
00439             off += att[j]->attlen;
00440         }
00441 
00442         Assert(j > attnum);
00443 
00444         off = att[attnum]->attcacheoff;
00445     }
00446     else
00447     {
00448         bool        usecache = true;
00449         int         i;
00450 
00451         /*
00452          * Now we know that we have to walk the tuple CAREFULLY.  But we still
00453          * might be able to cache some offsets for next time.
00454          *
00455          * Note - This loop is a little tricky.  For each non-null attribute,
00456          * we have to first account for alignment padding before the attr,
00457          * then advance over the attr based on its length.  Nulls have no
00458          * storage and no alignment padding either.  We can use/set
00459          * attcacheoff until we reach either a null or a var-width attribute.
00460          */
00461         off = 0;
00462         for (i = 0;; i++)       /* loop exit is at "break" */
00463         {
00464             if (HeapTupleHasNulls(tuple) && att_isnull(i, bp))
00465             {
00466                 usecache = false;
00467                 continue;       /* this cannot be the target att */
00468             }
00469 
00470             /* If we know the next offset, we can skip the rest */
00471             if (usecache && att[i]->attcacheoff >= 0)
00472                 off = att[i]->attcacheoff;
00473             else if (att[i]->attlen == -1)
00474             {
00475                 /*
00476                  * We can only cache the offset for a varlena attribute if the
00477                  * offset is already suitably aligned, so that there would be
00478                  * no pad bytes in any case: then the offset will be valid for
00479                  * either an aligned or unaligned value.
00480                  */
00481                 if (usecache &&
00482                     off == att_align_nominal(off, att[i]->attalign))
00483                     att[i]->attcacheoff = off;
00484                 else
00485                 {
00486                     off = att_align_pointer(off, att[i]->attalign, -1,
00487                                             tp + off);
00488                     usecache = false;
00489                 }
00490             }
00491             else
00492             {
00493                 /* not varlena, so safe to use att_align_nominal */
00494                 off = att_align_nominal(off, att[i]->attalign);
00495 
00496                 if (usecache)
00497                     att[i]->attcacheoff = off;
00498             }
00499 
00500             if (i == attnum)
00501                 break;
00502 
00503             off = att_addlength_pointer(off, att[i]->attlen, tp + off);
00504 
00505             if (usecache && att[i]->attlen <= 0)
00506                 usecache = false;
00507         }
00508     }
00509 
00510     return fetchatt(att[attnum], tp + off);
00511 }
00512 
00513 /* ----------------
00514  *      heap_getsysattr
00515  *
00516  *      Fetch the value of a system attribute for a tuple.
00517  *
00518  * This is a support routine for the heap_getattr macro.  The macro
00519  * has already determined that the attnum refers to a system attribute.
00520  * ----------------
00521  */
00522 Datum
00523 heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
00524 {
00525     Datum       result;
00526 
00527     Assert(tup);
00528 
00529     /* Currently, no sys attribute ever reads as NULL. */
00530     *isnull = false;
00531 
00532     switch (attnum)
00533     {
00534         case SelfItemPointerAttributeNumber:
00535             /* pass-by-reference datatype */
00536             result = PointerGetDatum(&(tup->t_self));
00537             break;
00538         case ObjectIdAttributeNumber:
00539             result = ObjectIdGetDatum(HeapTupleGetOid(tup));
00540             break;
00541         case MinTransactionIdAttributeNumber:
00542             result = TransactionIdGetDatum(HeapTupleHeaderGetXmin(tup->t_data));
00543             break;
00544         case MaxTransactionIdAttributeNumber:
00545             result = TransactionIdGetDatum(HeapTupleHeaderGetRawXmax(tup->t_data));
00546             break;
00547         case MinCommandIdAttributeNumber:
00548         case MaxCommandIdAttributeNumber:
00549 
00550             /*
00551              * cmin and cmax are now both aliases for the same field, which
00552              * can in fact also be a combo command id.  XXX perhaps we should
00553              * return the "real" cmin or cmax if possible, that is if we are
00554              * inside the originating transaction?
00555              */
00556             result = CommandIdGetDatum(HeapTupleHeaderGetRawCommandId(tup->t_data));
00557             break;
00558         case TableOidAttributeNumber:
00559             result = ObjectIdGetDatum(tup->t_tableOid);
00560             break;
00561         default:
00562             elog(ERROR, "invalid attnum: %d", attnum);
00563             result = 0;         /* keep compiler quiet */
00564             break;
00565     }
00566     return result;
00567 }
00568 
00569 /* ----------------
00570  *      heap_copytuple
00571  *
00572  *      returns a copy of an entire tuple
00573  *
00574  * The HeapTuple struct, tuple header, and tuple data are all allocated
00575  * as a single palloc() block.
00576  * ----------------
00577  */
00578 HeapTuple
00579 heap_copytuple(HeapTuple tuple)
00580 {
00581     HeapTuple   newTuple;
00582 
00583     if (!HeapTupleIsValid(tuple) || tuple->t_data == NULL)
00584         return NULL;
00585 
00586     newTuple = (HeapTuple) palloc(HEAPTUPLESIZE + tuple->t_len);
00587     newTuple->t_len = tuple->t_len;
00588     newTuple->t_self = tuple->t_self;
00589     newTuple->t_tableOid = tuple->t_tableOid;
00590     newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE);
00591     memcpy((char *) newTuple->t_data, (char *) tuple->t_data, tuple->t_len);
00592     return newTuple;
00593 }
00594 
00595 /* ----------------
00596  *      heap_copytuple_with_tuple
00597  *
00598  *      copy a tuple into a caller-supplied HeapTuple management struct
00599  *
00600  * Note that after calling this function, the "dest" HeapTuple will not be
00601  * allocated as a single palloc() block (unlike with heap_copytuple()).
00602  * ----------------
00603  */
00604 void
00605 heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
00606 {
00607     if (!HeapTupleIsValid(src) || src->t_data == NULL)
00608     {
00609         dest->t_data = NULL;
00610         return;
00611     }
00612 
00613     dest->t_len = src->t_len;
00614     dest->t_self = src->t_self;
00615     dest->t_tableOid = src->t_tableOid;
00616     dest->t_data = (HeapTupleHeader) palloc(src->t_len);
00617     memcpy((char *) dest->t_data, (char *) src->t_data, src->t_len);
00618 }
00619 
00620 /*
00621  * heap_form_tuple
00622  *      construct a tuple from the given values[] and isnull[] arrays,
00623  *      which are of the length indicated by tupleDescriptor->natts
00624  *
00625  * The result is allocated in the current memory context.
00626  */
00627 HeapTuple
00628 heap_form_tuple(TupleDesc tupleDescriptor,
00629                 Datum *values,
00630                 bool *isnull)
00631 {
00632     HeapTuple   tuple;          /* return tuple */
00633     HeapTupleHeader td;         /* tuple data */
00634     Size        len,
00635                 data_len;
00636     int         hoff;
00637     bool        hasnull = false;
00638     Form_pg_attribute *att = tupleDescriptor->attrs;
00639     int         numberOfAttributes = tupleDescriptor->natts;
00640     int         i;
00641 
00642     if (numberOfAttributes > MaxTupleAttributeNumber)
00643         ereport(ERROR,
00644                 (errcode(ERRCODE_TOO_MANY_COLUMNS),
00645                  errmsg("number of columns (%d) exceeds limit (%d)",
00646                         numberOfAttributes, MaxTupleAttributeNumber)));
00647 
00648     /*
00649      * Check for nulls and embedded tuples; expand any toasted attributes in
00650      * embedded tuples.  This preserves the invariant that toasting can only
00651      * go one level deep.
00652      *
00653      * We can skip calling toast_flatten_tuple_attribute() if the attribute
00654      * couldn't possibly be of composite type.  All composite datums are
00655      * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
00656      * if an attribute is already toasted, it must have been sent to disk
00657      * already and so cannot contain toasted attributes.
00658      */
00659     for (i = 0; i < numberOfAttributes; i++)
00660     {
00661         if (isnull[i])
00662             hasnull = true;
00663         else if (att[i]->attlen == -1 &&
00664                  att[i]->attalign == 'd' &&
00665                  att[i]->attndims == 0 &&
00666                  !VARATT_IS_EXTENDED(DatumGetPointer(values[i])))
00667         {
00668             values[i] = toast_flatten_tuple_attribute(values[i],
00669                                                       att[i]->atttypid,
00670                                                       att[i]->atttypmod);
00671         }
00672     }
00673 
00674     /*
00675      * Determine total space needed
00676      */
00677     len = offsetof(HeapTupleHeaderData, t_bits);
00678 
00679     if (hasnull)
00680         len += BITMAPLEN(numberOfAttributes);
00681 
00682     if (tupleDescriptor->tdhasoid)
00683         len += sizeof(Oid);
00684 
00685     hoff = len = MAXALIGN(len); /* align user data safely */
00686 
00687     data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
00688 
00689     len += data_len;
00690 
00691     /*
00692      * Allocate and zero the space needed.  Note that the tuple body and
00693      * HeapTupleData management structure are allocated in one chunk.
00694      */
00695     tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
00696     tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
00697 
00698     /*
00699      * And fill in the information.  Note we fill the Datum fields even though
00700      * this tuple may never become a Datum.
00701      */
00702     tuple->t_len = len;
00703     ItemPointerSetInvalid(&(tuple->t_self));
00704     tuple->t_tableOid = InvalidOid;
00705 
00706     HeapTupleHeaderSetDatumLength(td, len);
00707     HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);
00708     HeapTupleHeaderSetTypMod(td, tupleDescriptor->tdtypmod);
00709 
00710     HeapTupleHeaderSetNatts(td, numberOfAttributes);
00711     td->t_hoff = hoff;
00712 
00713     if (tupleDescriptor->tdhasoid)      /* else leave infomask = 0 */
00714         td->t_infomask = HEAP_HASOID;
00715 
00716     heap_fill_tuple(tupleDescriptor,
00717                     values,
00718                     isnull,
00719                     (char *) td + hoff,
00720                     data_len,
00721                     &td->t_infomask,
00722                     (hasnull ? td->t_bits : NULL));
00723 
00724     return tuple;
00725 }
00726 
00727 /*
00728  *      heap_formtuple
00729  *
00730  *      construct a tuple from the given values[] and nulls[] arrays
00731  *
00732  *      Null attributes are indicated by a 'n' in the appropriate byte
00733  *      of nulls[]. Non-null attributes are indicated by a ' ' (space).
00734  *
00735  * OLD API with char 'n'/' ' convention for indicating nulls.
00736  * This is deprecated and should not be used in new code, but we keep it
00737  * around for use by old add-on modules.
00738  */
00739 HeapTuple
00740 heap_formtuple(TupleDesc tupleDescriptor,
00741                Datum *values,
00742                char *nulls)
00743 {
00744     HeapTuple   tuple;          /* return tuple */
00745     int         numberOfAttributes = tupleDescriptor->natts;
00746     bool       *boolNulls = (bool *) palloc(numberOfAttributes * sizeof(bool));
00747     int         i;
00748 
00749     for (i = 0; i < numberOfAttributes; i++)
00750         boolNulls[i] = (nulls[i] == 'n');
00751 
00752     tuple = heap_form_tuple(tupleDescriptor, values, boolNulls);
00753 
00754     pfree(boolNulls);
00755 
00756     return tuple;
00757 }
00758 
00759 
00760 /*
00761  * heap_modify_tuple
00762  *      form a new tuple from an old tuple and a set of replacement values.
00763  *
00764  * The replValues, replIsnull, and doReplace arrays must be of the length
00765  * indicated by tupleDesc->natts.  The new tuple is constructed using the data
00766  * from replValues/replIsnull at columns where doReplace is true, and using
00767  * the data from the old tuple at columns where doReplace is false.
00768  *
00769  * The result is allocated in the current memory context.
00770  */
00771 HeapTuple
00772 heap_modify_tuple(HeapTuple tuple,
00773                   TupleDesc tupleDesc,
00774                   Datum *replValues,
00775                   bool *replIsnull,
00776                   bool *doReplace)
00777 {
00778     int         numberOfAttributes = tupleDesc->natts;
00779     int         attoff;
00780     Datum      *values;
00781     bool       *isnull;
00782     HeapTuple   newTuple;
00783 
00784     /*
00785      * allocate and fill values and isnull arrays from either the tuple or the
00786      * repl information, as appropriate.
00787      *
00788      * NOTE: it's debatable whether to use heap_deform_tuple() here or just
00789      * heap_getattr() only the non-replaced colums.  The latter could win if
00790      * there are many replaced columns and few non-replaced ones. However,
00791      * heap_deform_tuple costs only O(N) while the heap_getattr way would cost
00792      * O(N^2) if there are many non-replaced columns, so it seems better to
00793      * err on the side of linear cost.
00794      */
00795     values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
00796     isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
00797 
00798     heap_deform_tuple(tuple, tupleDesc, values, isnull);
00799 
00800     for (attoff = 0; attoff < numberOfAttributes; attoff++)
00801     {
00802         if (doReplace[attoff])
00803         {
00804             values[attoff] = replValues[attoff];
00805             isnull[attoff] = replIsnull[attoff];
00806         }
00807     }
00808 
00809     /*
00810      * create a new tuple from the values and isnull arrays
00811      */
00812     newTuple = heap_form_tuple(tupleDesc, values, isnull);
00813 
00814     pfree(values);
00815     pfree(isnull);
00816 
00817     /*
00818      * copy the identification info of the old tuple: t_ctid, t_self, and OID
00819      * (if any)
00820      */
00821     newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
00822     newTuple->t_self = tuple->t_self;
00823     newTuple->t_tableOid = tuple->t_tableOid;
00824     if (tupleDesc->tdhasoid)
00825         HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple));
00826 
00827     return newTuple;
00828 }
00829 
00830 /*
00831  *      heap_modifytuple
00832  *
00833  *      forms a new tuple from an old tuple and a set of replacement values.
00834  *      returns a new palloc'ed tuple.
00835  *
00836  * OLD API with char 'n'/' ' convention for indicating nulls, and
00837  * char 'r'/' ' convention for indicating whether to replace columns.
00838  * This is deprecated and should not be used in new code, but we keep it
00839  * around for use by old add-on modules.
00840  */
00841 HeapTuple
00842 heap_modifytuple(HeapTuple tuple,
00843                  TupleDesc tupleDesc,
00844                  Datum *replValues,
00845                  char *replNulls,
00846                  char *replActions)
00847 {
00848     HeapTuple   result;
00849     int         numberOfAttributes = tupleDesc->natts;
00850     bool       *boolNulls = (bool *) palloc(numberOfAttributes * sizeof(bool));
00851     bool       *boolActions = (bool *) palloc(numberOfAttributes * sizeof(bool));
00852     int         attnum;
00853 
00854     for (attnum = 0; attnum < numberOfAttributes; attnum++)
00855     {
00856         boolNulls[attnum] = (replNulls[attnum] == 'n');
00857         boolActions[attnum] = (replActions[attnum] == 'r');
00858     }
00859 
00860     result = heap_modify_tuple(tuple, tupleDesc, replValues, boolNulls, boolActions);
00861 
00862     pfree(boolNulls);
00863     pfree(boolActions);
00864 
00865     return result;
00866 }
00867 
00868 /*
00869  * heap_deform_tuple
00870  *      Given a tuple, extract data into values/isnull arrays; this is
00871  *      the inverse of heap_form_tuple.
00872  *
00873  *      Storage for the values/isnull arrays is provided by the caller;
00874  *      it should be sized according to tupleDesc->natts not
00875  *      HeapTupleHeaderGetNatts(tuple->t_data).
00876  *
00877  *      Note that for pass-by-reference datatypes, the pointer placed
00878  *      in the Datum will point into the given tuple.
00879  *
00880  *      When all or most of a tuple's fields need to be extracted,
00881  *      this routine will be significantly quicker than a loop around
00882  *      heap_getattr; the loop will become O(N^2) as soon as any
00883  *      noncacheable attribute offsets are involved.
00884  */
00885 void
00886 heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
00887                   Datum *values, bool *isnull)
00888 {
00889     HeapTupleHeader tup = tuple->t_data;
00890     bool        hasnulls = HeapTupleHasNulls(tuple);
00891     Form_pg_attribute *att = tupleDesc->attrs;
00892     int         tdesc_natts = tupleDesc->natts;
00893     int         natts;          /* number of atts to extract */
00894     int         attnum;
00895     char       *tp;             /* ptr to tuple data */
00896     long        off;            /* offset in tuple data */
00897     bits8      *bp = tup->t_bits;       /* ptr to null bitmap in tuple */
00898     bool        slow = false;   /* can we use/set attcacheoff? */
00899 
00900     natts = HeapTupleHeaderGetNatts(tup);
00901 
00902     /*
00903      * In inheritance situations, it is possible that the given tuple actually
00904      * has more fields than the caller is expecting.  Don't run off the end of
00905      * the caller's arrays.
00906      */
00907     natts = Min(natts, tdesc_natts);
00908 
00909     tp = (char *) tup + tup->t_hoff;
00910 
00911     off = 0;
00912 
00913     for (attnum = 0; attnum < natts; attnum++)
00914     {
00915         Form_pg_attribute thisatt = att[attnum];
00916 
00917         if (hasnulls && att_isnull(attnum, bp))
00918         {
00919             values[attnum] = (Datum) 0;
00920             isnull[attnum] = true;
00921             slow = true;        /* can't use attcacheoff anymore */
00922             continue;
00923         }
00924 
00925         isnull[attnum] = false;
00926 
00927         if (!slow && thisatt->attcacheoff >= 0)
00928             off = thisatt->attcacheoff;
00929         else if (thisatt->attlen == -1)
00930         {
00931             /*
00932              * We can only cache the offset for a varlena attribute if the
00933              * offset is already suitably aligned, so that there would be no
00934              * pad bytes in any case: then the offset will be valid for either
00935              * an aligned or unaligned value.
00936              */
00937             if (!slow &&
00938                 off == att_align_nominal(off, thisatt->attalign))
00939                 thisatt->attcacheoff = off;
00940             else
00941             {
00942                 off = att_align_pointer(off, thisatt->attalign, -1,
00943                                         tp + off);
00944                 slow = true;
00945             }
00946         }
00947         else
00948         {
00949             /* not varlena, so safe to use att_align_nominal */
00950             off = att_align_nominal(off, thisatt->attalign);
00951 
00952             if (!slow)
00953                 thisatt->attcacheoff = off;
00954         }
00955 
00956         values[attnum] = fetchatt(thisatt, tp + off);
00957 
00958         off = att_addlength_pointer(off, thisatt->attlen, tp + off);
00959 
00960         if (thisatt->attlen <= 0)
00961             slow = true;        /* can't use attcacheoff anymore */
00962     }
00963 
00964     /*
00965      * If tuple doesn't have all the atts indicated by tupleDesc, read the
00966      * rest as null
00967      */
00968     for (; attnum < tdesc_natts; attnum++)
00969     {
00970         values[attnum] = (Datum) 0;
00971         isnull[attnum] = true;
00972     }
00973 }
00974 
00975 /*
00976  *      heap_deformtuple
00977  *
00978  *      Given a tuple, extract data into values/nulls arrays; this is
00979  *      the inverse of heap_formtuple.
00980  *
00981  *      Storage for the values/nulls arrays is provided by the caller;
00982  *      it should be sized according to tupleDesc->natts not
00983  *      HeapTupleHeaderGetNatts(tuple->t_data).
00984  *
00985  *      Note that for pass-by-reference datatypes, the pointer placed
00986  *      in the Datum will point into the given tuple.
00987  *
00988  *      When all or most of a tuple's fields need to be extracted,
00989  *      this routine will be significantly quicker than a loop around
00990  *      heap_getattr; the loop will become O(N^2) as soon as any
00991  *      noncacheable attribute offsets are involved.
00992  *
00993  * OLD API with char 'n'/' ' convention for indicating nulls.
00994  * This is deprecated and should not be used in new code, but we keep it
00995  * around for use by old add-on modules.
00996  */
00997 void
00998 heap_deformtuple(HeapTuple tuple,
00999                  TupleDesc tupleDesc,
01000                  Datum *values,
01001                  char *nulls)
01002 {
01003     int         natts = tupleDesc->natts;
01004     bool       *boolNulls = (bool *) palloc(natts * sizeof(bool));
01005     int         attnum;
01006 
01007     heap_deform_tuple(tuple, tupleDesc, values, boolNulls);
01008 
01009     for (attnum = 0; attnum < natts; attnum++)
01010         nulls[attnum] = (boolNulls[attnum] ? 'n' : ' ');
01011 
01012     pfree(boolNulls);
01013 }
01014 
01015 /*
01016  * slot_deform_tuple
01017  *      Given a TupleTableSlot, extract data from the slot's physical tuple
01018  *      into its Datum/isnull arrays.  Data is extracted up through the
01019  *      natts'th column (caller must ensure this is a legal column number).
01020  *
01021  *      This is essentially an incremental version of heap_deform_tuple:
01022  *      on each call we extract attributes up to the one needed, without
01023  *      re-computing information about previously extracted attributes.
01024  *      slot->tts_nvalid is the number of attributes already extracted.
01025  */
01026 static void
01027 slot_deform_tuple(TupleTableSlot *slot, int natts)
01028 {
01029     HeapTuple   tuple = slot->tts_tuple;
01030     TupleDesc   tupleDesc = slot->tts_tupleDescriptor;
01031     Datum      *values = slot->tts_values;
01032     bool       *isnull = slot->tts_isnull;
01033     HeapTupleHeader tup = tuple->t_data;
01034     bool        hasnulls = HeapTupleHasNulls(tuple);
01035     Form_pg_attribute *att = tupleDesc->attrs;
01036     int         attnum;
01037     char       *tp;             /* ptr to tuple data */
01038     long        off;            /* offset in tuple data */
01039     bits8      *bp = tup->t_bits;       /* ptr to null bitmap in tuple */
01040     bool        slow;           /* can we use/set attcacheoff? */
01041 
01042     /*
01043      * Check whether the first call for this tuple, and initialize or restore
01044      * loop state.
01045      */
01046     attnum = slot->tts_nvalid;
01047     if (attnum == 0)
01048     {
01049         /* Start from the first attribute */
01050         off = 0;
01051         slow = false;
01052     }
01053     else
01054     {
01055         /* Restore state from previous execution */
01056         off = slot->tts_off;
01057         slow = slot->tts_slow;
01058     }
01059 
01060     tp = (char *) tup + tup->t_hoff;
01061 
01062     for (; attnum < natts; attnum++)
01063     {
01064         Form_pg_attribute thisatt = att[attnum];
01065 
01066         if (hasnulls && att_isnull(attnum, bp))
01067         {
01068             values[attnum] = (Datum) 0;
01069             isnull[attnum] = true;
01070             slow = true;        /* can't use attcacheoff anymore */
01071             continue;
01072         }
01073 
01074         isnull[attnum] = false;
01075 
01076         if (!slow && thisatt->attcacheoff >= 0)
01077             off = thisatt->attcacheoff;
01078         else if (thisatt->attlen == -1)
01079         {
01080             /*
01081              * We can only cache the offset for a varlena attribute if the
01082              * offset is already suitably aligned, so that there would be no
01083              * pad bytes in any case: then the offset will be valid for either
01084              * an aligned or unaligned value.
01085              */
01086             if (!slow &&
01087                 off == att_align_nominal(off, thisatt->attalign))
01088                 thisatt->attcacheoff = off;
01089             else
01090             {
01091                 off = att_align_pointer(off, thisatt->attalign, -1,
01092                                         tp + off);
01093                 slow = true;
01094             }
01095         }
01096         else
01097         {
01098             /* not varlena, so safe to use att_align_nominal */
01099             off = att_align_nominal(off, thisatt->attalign);
01100 
01101             if (!slow)
01102                 thisatt->attcacheoff = off;
01103         }
01104 
01105         values[attnum] = fetchatt(thisatt, tp + off);
01106 
01107         off = att_addlength_pointer(off, thisatt->attlen, tp + off);
01108 
01109         if (thisatt->attlen <= 0)
01110             slow = true;        /* can't use attcacheoff anymore */
01111     }
01112 
01113     /*
01114      * Save state for next execution
01115      */
01116     slot->tts_nvalid = attnum;
01117     slot->tts_off = off;
01118     slot->tts_slow = slow;
01119 }
01120 
01121 /*
01122  * slot_getattr
01123  *      This function fetches an attribute of the slot's current tuple.
01124  *      It is functionally equivalent to heap_getattr, but fetches of
01125  *      multiple attributes of the same tuple will be optimized better,
01126  *      because we avoid O(N^2) behavior from multiple calls of
01127  *      nocachegetattr(), even when attcacheoff isn't usable.
01128  *
01129  *      A difference from raw heap_getattr is that attnums beyond the
01130  *      slot's tupdesc's last attribute will be considered NULL even
01131  *      when the physical tuple is longer than the tupdesc.
01132  */
01133 Datum
01134 slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
01135 {
01136     HeapTuple   tuple = slot->tts_tuple;
01137     TupleDesc   tupleDesc = slot->tts_tupleDescriptor;
01138     HeapTupleHeader tup;
01139 
01140     /*
01141      * system attributes are handled by heap_getsysattr
01142      */
01143     if (attnum <= 0)
01144     {
01145         if (tuple == NULL)      /* internal error */
01146             elog(ERROR, "cannot extract system attribute from virtual tuple");
01147         if (tuple == &(slot->tts_minhdr))       /* internal error */
01148             elog(ERROR, "cannot extract system attribute from minimal tuple");
01149         return heap_getsysattr(tuple, attnum, tupleDesc, isnull);
01150     }
01151 
01152     /*
01153      * fast path if desired attribute already cached
01154      */
01155     if (attnum <= slot->tts_nvalid)
01156     {
01157         *isnull = slot->tts_isnull[attnum - 1];
01158         return slot->tts_values[attnum - 1];
01159     }
01160 
01161     /*
01162      * return NULL if attnum is out of range according to the tupdesc
01163      */
01164     if (attnum > tupleDesc->natts)
01165     {
01166         *isnull = true;
01167         return (Datum) 0;
01168     }
01169 
01170     /*
01171      * otherwise we had better have a physical tuple (tts_nvalid should equal
01172      * natts in all virtual-tuple cases)
01173      */
01174     if (tuple == NULL)          /* internal error */
01175         elog(ERROR, "cannot extract attribute from empty tuple slot");
01176 
01177     /*
01178      * return NULL if attnum is out of range according to the tuple
01179      *
01180      * (We have to check this separately because of various inheritance and
01181      * table-alteration scenarios: the tuple could be either longer or shorter
01182      * than the tupdesc.)
01183      */
01184     tup = tuple->t_data;
01185     if (attnum > HeapTupleHeaderGetNatts(tup))
01186     {
01187         *isnull = true;
01188         return (Datum) 0;
01189     }
01190 
01191     /*
01192      * check if target attribute is null: no point in groveling through tuple
01193      */
01194     if (HeapTupleHasNulls(tuple) && att_isnull(attnum - 1, tup->t_bits))
01195     {
01196         *isnull = true;
01197         return (Datum) 0;
01198     }
01199 
01200     /*
01201      * If the attribute's column has been dropped, we force a NULL result.
01202      * This case should not happen in normal use, but it could happen if we
01203      * are executing a plan cached before the column was dropped.
01204      */
01205     if (tupleDesc->attrs[attnum - 1]->attisdropped)
01206     {
01207         *isnull = true;
01208         return (Datum) 0;
01209     }
01210 
01211     /*
01212      * Extract the attribute, along with any preceding attributes.
01213      */
01214     slot_deform_tuple(slot, attnum);
01215 
01216     /*
01217      * The result is acquired from tts_values array.
01218      */
01219     *isnull = slot->tts_isnull[attnum - 1];
01220     return slot->tts_values[attnum - 1];
01221 }
01222 
01223 /*
01224  * slot_getallattrs
01225  *      This function forces all the entries of the slot's Datum/isnull
01226  *      arrays to be valid.  The caller may then extract data directly
01227  *      from those arrays instead of using slot_getattr.
01228  */
01229 void
01230 slot_getallattrs(TupleTableSlot *slot)
01231 {
01232     int         tdesc_natts = slot->tts_tupleDescriptor->natts;
01233     int         attnum;
01234     HeapTuple   tuple;
01235 
01236     /* Quick out if we have 'em all already */
01237     if (slot->tts_nvalid == tdesc_natts)
01238         return;
01239 
01240     /*
01241      * otherwise we had better have a physical tuple (tts_nvalid should equal
01242      * natts in all virtual-tuple cases)
01243      */
01244     tuple = slot->tts_tuple;
01245     if (tuple == NULL)          /* internal error */
01246         elog(ERROR, "cannot extract attribute from empty tuple slot");
01247 
01248     /*
01249      * load up any slots available from physical tuple
01250      */
01251     attnum = HeapTupleHeaderGetNatts(tuple->t_data);
01252     attnum = Min(attnum, tdesc_natts);
01253 
01254     slot_deform_tuple(slot, attnum);
01255 
01256     /*
01257      * If tuple doesn't have all the atts indicated by tupleDesc, read the
01258      * rest as null
01259      */
01260     for (; attnum < tdesc_natts; attnum++)
01261     {
01262         slot->tts_values[attnum] = (Datum) 0;
01263         slot->tts_isnull[attnum] = true;
01264     }
01265     slot->tts_nvalid = tdesc_natts;
01266 }
01267 
01268 /*
01269  * slot_getsomeattrs
01270  *      This function forces the entries of the slot's Datum/isnull
01271  *      arrays to be valid at least up through the attnum'th entry.
01272  */
01273 void
01274 slot_getsomeattrs(TupleTableSlot *slot, int attnum)
01275 {
01276     HeapTuple   tuple;
01277     int         attno;
01278 
01279     /* Quick out if we have 'em all already */
01280     if (slot->tts_nvalid >= attnum)
01281         return;
01282 
01283     /* Check for caller error */
01284     if (attnum <= 0 || attnum > slot->tts_tupleDescriptor->natts)
01285         elog(ERROR, "invalid attribute number %d", attnum);
01286 
01287     /*
01288      * otherwise we had better have a physical tuple (tts_nvalid should equal
01289      * natts in all virtual-tuple cases)
01290      */
01291     tuple = slot->tts_tuple;
01292     if (tuple == NULL)          /* internal error */
01293         elog(ERROR, "cannot extract attribute from empty tuple slot");
01294 
01295     /*
01296      * load up any slots available from physical tuple
01297      */
01298     attno = HeapTupleHeaderGetNatts(tuple->t_data);
01299     attno = Min(attno, attnum);
01300 
01301     slot_deform_tuple(slot, attno);
01302 
01303     /*
01304      * If tuple doesn't have all the atts indicated by tupleDesc, read the
01305      * rest as null
01306      */
01307     for (; attno < attnum; attno++)
01308     {
01309         slot->tts_values[attno] = (Datum) 0;
01310         slot->tts_isnull[attno] = true;
01311     }
01312     slot->tts_nvalid = attnum;
01313 }
01314 
01315 /*
01316  * slot_attisnull
01317  *      Detect whether an attribute of the slot is null, without
01318  *      actually fetching it.
01319  */
01320 bool
01321 slot_attisnull(TupleTableSlot *slot, int attnum)
01322 {
01323     HeapTuple   tuple = slot->tts_tuple;
01324     TupleDesc   tupleDesc = slot->tts_tupleDescriptor;
01325 
01326     /*
01327      * system attributes are handled by heap_attisnull
01328      */
01329     if (attnum <= 0)
01330     {
01331         if (tuple == NULL)      /* internal error */
01332             elog(ERROR, "cannot extract system attribute from virtual tuple");
01333         if (tuple == &(slot->tts_minhdr))       /* internal error */
01334             elog(ERROR, "cannot extract system attribute from minimal tuple");
01335         return heap_attisnull(tuple, attnum);
01336     }
01337 
01338     /*
01339      * fast path if desired attribute already cached
01340      */
01341     if (attnum <= slot->tts_nvalid)
01342         return slot->tts_isnull[attnum - 1];
01343 
01344     /*
01345      * return NULL if attnum is out of range according to the tupdesc
01346      */
01347     if (attnum > tupleDesc->natts)
01348         return true;
01349 
01350     /*
01351      * otherwise we had better have a physical tuple (tts_nvalid should equal
01352      * natts in all virtual-tuple cases)
01353      */
01354     if (tuple == NULL)          /* internal error */
01355         elog(ERROR, "cannot extract attribute from empty tuple slot");
01356 
01357     /* and let the tuple tell it */
01358     return heap_attisnull(tuple, attnum);
01359 }
01360 
01361 /*
01362  * heap_freetuple
01363  */
01364 void
01365 heap_freetuple(HeapTuple htup)
01366 {
01367     pfree(htup);
01368 }
01369 
01370 
01371 /*
01372  * heap_form_minimal_tuple
01373  *      construct a MinimalTuple from the given values[] and isnull[] arrays,
01374  *      which are of the length indicated by tupleDescriptor->natts
01375  *
01376  * This is exactly like heap_form_tuple() except that the result is a
01377  * "minimal" tuple lacking a HeapTupleData header as well as room for system
01378  * columns.
01379  *
01380  * The result is allocated in the current memory context.
01381  */
01382 MinimalTuple
01383 heap_form_minimal_tuple(TupleDesc tupleDescriptor,
01384                         Datum *values,
01385                         bool *isnull)
01386 {
01387     MinimalTuple tuple;         /* return tuple */
01388     Size        len,
01389                 data_len;
01390     int         hoff;
01391     bool        hasnull = false;
01392     Form_pg_attribute *att = tupleDescriptor->attrs;
01393     int         numberOfAttributes = tupleDescriptor->natts;
01394     int         i;
01395 
01396     if (numberOfAttributes > MaxTupleAttributeNumber)
01397         ereport(ERROR,
01398                 (errcode(ERRCODE_TOO_MANY_COLUMNS),
01399                  errmsg("number of columns (%d) exceeds limit (%d)",
01400                         numberOfAttributes, MaxTupleAttributeNumber)));
01401 
01402     /*
01403      * Check for nulls and embedded tuples; expand any toasted attributes in
01404      * embedded tuples.  This preserves the invariant that toasting can only
01405      * go one level deep.
01406      *
01407      * We can skip calling toast_flatten_tuple_attribute() if the attribute
01408      * couldn't possibly be of composite type.  All composite datums are
01409      * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
01410      * if an attribute is already toasted, it must have been sent to disk
01411      * already and so cannot contain toasted attributes.
01412      */
01413     for (i = 0; i < numberOfAttributes; i++)
01414     {
01415         if (isnull[i])
01416             hasnull = true;
01417         else if (att[i]->attlen == -1 &&
01418                  att[i]->attalign == 'd' &&
01419                  att[i]->attndims == 0 &&
01420                  !VARATT_IS_EXTENDED(values[i]))
01421         {
01422             values[i] = toast_flatten_tuple_attribute(values[i],
01423                                                       att[i]->atttypid,
01424                                                       att[i]->atttypmod);
01425         }
01426     }
01427 
01428     /*
01429      * Determine total space needed
01430      */
01431     len = offsetof(MinimalTupleData, t_bits);
01432 
01433     if (hasnull)
01434         len += BITMAPLEN(numberOfAttributes);
01435 
01436     if (tupleDescriptor->tdhasoid)
01437         len += sizeof(Oid);
01438 
01439     hoff = len = MAXALIGN(len); /* align user data safely */
01440 
01441     data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
01442 
01443     len += data_len;
01444 
01445     /*
01446      * Allocate and zero the space needed.
01447      */
01448     tuple = (MinimalTuple) palloc0(len);
01449 
01450     /*
01451      * And fill in the information.
01452      */
01453     tuple->t_len = len;
01454     HeapTupleHeaderSetNatts(tuple, numberOfAttributes);
01455     tuple->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
01456 
01457     if (tupleDescriptor->tdhasoid)      /* else leave infomask = 0 */
01458         tuple->t_infomask = HEAP_HASOID;
01459 
01460     heap_fill_tuple(tupleDescriptor,
01461                     values,
01462                     isnull,
01463                     (char *) tuple + hoff,
01464                     data_len,
01465                     &tuple->t_infomask,
01466                     (hasnull ? tuple->t_bits : NULL));
01467 
01468     return tuple;
01469 }
01470 
01471 /*
01472  * heap_free_minimal_tuple
01473  */
01474 void
01475 heap_free_minimal_tuple(MinimalTuple mtup)
01476 {
01477     pfree(mtup);
01478 }
01479 
01480 /*
01481  * heap_copy_minimal_tuple
01482  *      copy a MinimalTuple
01483  *
01484  * The result is allocated in the current memory context.
01485  */
01486 MinimalTuple
01487 heap_copy_minimal_tuple(MinimalTuple mtup)
01488 {
01489     MinimalTuple result;
01490 
01491     result = (MinimalTuple) palloc(mtup->t_len);
01492     memcpy(result, mtup, mtup->t_len);
01493     return result;
01494 }
01495 
01496 /*
01497  * heap_tuple_from_minimal_tuple
01498  *      create a HeapTuple by copying from a MinimalTuple;
01499  *      system columns are filled with zeroes
01500  *
01501  * The result is allocated in the current memory context.
01502  * The HeapTuple struct, tuple header, and tuple data are all allocated
01503  * as a single palloc() block.
01504  */
01505 HeapTuple
01506 heap_tuple_from_minimal_tuple(MinimalTuple mtup)
01507 {
01508     HeapTuple   result;
01509     uint32      len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
01510 
01511     result = (HeapTuple) palloc(HEAPTUPLESIZE + len);
01512     result->t_len = len;
01513     ItemPointerSetInvalid(&(result->t_self));
01514     result->t_tableOid = InvalidOid;
01515     result->t_data = (HeapTupleHeader) ((char *) result + HEAPTUPLESIZE);
01516     memcpy((char *) result->t_data + MINIMAL_TUPLE_OFFSET, mtup, mtup->t_len);
01517     memset(result->t_data, 0, offsetof(HeapTupleHeaderData, t_infomask2));
01518     return result;
01519 }
01520 
01521 /*
01522  * minimal_tuple_from_heap_tuple
01523  *      create a MinimalTuple by copying from a HeapTuple
01524  *
01525  * The result is allocated in the current memory context.
01526  */
01527 MinimalTuple
01528 minimal_tuple_from_heap_tuple(HeapTuple htup)
01529 {
01530     MinimalTuple result;
01531     uint32      len;
01532 
01533     Assert(htup->t_len > MINIMAL_TUPLE_OFFSET);
01534     len = htup->t_len - MINIMAL_TUPLE_OFFSET;
01535     result = (MinimalTuple) palloc(len);
01536     memcpy(result, (char *) htup->t_data + MINIMAL_TUPLE_OFFSET, len);
01537     result->t_len = len;
01538     return result;
01539 }