LTP GCOV extension - code coverage report
Current view: directory - access/common - heaptuple.c
Test: unnamed
Date: 2008-07-03 Instrumented lines: 600
Code covered: 89.5 % Executed lines: 537
Legend: not executed executed

       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * heaptuple.c
       4                 :  *        This file contains heap tuple accessor and mutator routines, as well
       5                 :  *        as various tuple utilities.
       6                 :  *
       7                 :  * NOTE: there is massive duplication of code in this module to
       8                 :  * support both the convention that a null is marked by a bool TRUE,
       9                 :  * and the convention that a null is marked by a char 'n'.      The latter
      10                 :  * convention is deprecated but it'll probably be a long time before
      11                 :  * we can get rid of it entirely.
      12                 :  *
      13                 :  *
      14                 :  * Some notes about varlenas and this code:
      15                 :  *
      16                 :  * Before Postgres 8.3 varlenas always had a 4-byte length header, and
      17                 :  * therefore always needed 4-byte alignment (at least).  This wasted space
      18                 :  * for short varlenas, for example CHAR(1) took 5 bytes and could need up to
      19                 :  * 3 additional padding bytes for alignment.
      20                 :  *
      21                 :  * Now, a short varlena (up to 126 data bytes) is reduced to a 1-byte header
      22                 :  * and we don't align it.  To hide this from datatype-specific functions that
      23                 :  * don't want to deal with it, such a datum is considered "toasted" and will
      24                 :  * be expanded back to the normal 4-byte-header format by pg_detoast_datum.
      25                 :  * (In performance-critical code paths we can use pg_detoast_datum_packed
      26                 :  * and the appropriate access macros to avoid that overhead.)  Note that this
      27                 :  * conversion is performed directly in heap_form_tuple (or heap_formtuple),
      28                 :  * without explicitly invoking the toaster.
      29                 :  *
      30                 :  * This change will break any code that assumes it needn't detoast values
      31                 :  * that have been put into a tuple but never sent to disk.      Hopefully there
      32                 :  * are few such places.
      33                 :  *
      34                 :  * Varlenas still have alignment 'i' (or 'd') in pg_type/pg_attribute, since
      35                 :  * that's the normal requirement for the untoasted format.  But we ignore that
      36                 :  * for the 1-byte-header format.  This means that the actual start position
      37                 :  * of a varlena datum may vary depending on which format it has.  To determine
      38                 :  * what is stored, we have to require that alignment padding bytes be zero.
      39                 :  * (Postgres actually has always zeroed them, but now it's required!)  Since
      40                 :  * the first byte of a 1-byte-header varlena can never be zero, we can examine
      41                 :  * the first byte after the previous datum to tell if it's a pad byte or the
      42                 :  * start of a 1-byte-header varlena.
      43                 :  *
      44                 :  * Note that while formerly we could rely on the first varlena column of a
      45                 :  * system catalog to be at the offset suggested by the C struct for the
      46                 :  * catalog, this is now risky: it's only safe if the preceding field is
      47                 :  * word-aligned, so that there will never be any padding.
      48                 :  *
      49                 :  * We don't pack varlenas whose attstorage is 'p', since the data type
      50                 :  * isn't expecting to have to detoast values.  This is used in particular
      51                 :  * by oidvector and int2vector, which are used in the system catalogs
      52                 :  * and we'd like to still refer to them via C struct offsets.
      53                 :  *
      54                 :  *
      55                 :  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
      56                 :  * Portions Copyright (c) 1994, Regents of the University of California
      57                 :  *
      58                 :  *
      59                 :  * IDENTIFICATION
      60                 :  *        $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.119 2007/11/15 21:14:31 momjian Exp $
      61                 :  *
      62                 :  *-------------------------------------------------------------------------
      63                 :  */
      64                 : 
      65                 : #include "postgres.h"
      66                 : 
      67                 : #include "access/heapam.h"
      68                 : #include "access/tuptoaster.h"
      69                 : #include "executor/tuptable.h"
      70                 : 
      71                 : 
      72                 : /* Does att's datatype allow packing into the 1-byte-header varlena format? */
      73                 : #define ATT_IS_PACKABLE(att) \
      74                 :         ((att)->attlen == -1 && (att)->attstorage != 'p')
      75                 : /* Use this if it's already known varlena */
      76                 : #define VARLENA_ATT_IS_PACKABLE(att) \
      77                 :         ((att)->attstorage != 'p')
      78                 : 
      79                 : 
      80                 : /* ----------------------------------------------------------------
      81                 :  *                                              misc support routines
      82                 :  * ----------------------------------------------------------------
      83                 :  */
      84                 : 
      85                 : 
      86                 : /*
      87                 :  * heap_compute_data_size
      88                 :  *              Determine size of the data area of a tuple to be constructed
      89                 :  */
      90                 : Size
      91                 : heap_compute_data_size(TupleDesc tupleDesc,
      92                 :                                            Datum *values,
      93                 :                                            bool *isnull)
      94          572598 : {
      95          572598 :         Size            data_length = 0;
      96                 :         int                     i;
      97          572598 :         int                     numberOfAttributes = tupleDesc->natts;
      98          572598 :         Form_pg_attribute *att = tupleDesc->attrs;
      99                 : 
     100         1957845 :         for (i = 0; i < numberOfAttributes; i++)
     101                 :         {
     102                 :                 Datum           val;
     103                 : 
     104         1385247 :                 if (isnull[i])
     105          131527 :                         continue;
     106                 : 
     107         1253720 :                 val = values[i];
     108                 : 
     109         1265002 :                 if (ATT_IS_PACKABLE(att[i]) &&
     110                 :                         VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
     111                 :                 {
     112                 :                         /*
     113                 :                          * we're anticipating converting to a short varlena header, so
     114                 :                          * adjust length and don't count any alignment
     115                 :                          */
     116           11282 :                         data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
     117                 :                 }
     118                 :                 else
     119                 :                 {
     120         1242438 :                         data_length = att_align_datum(data_length, att[i]->attalign,
     121                 :                                                                                   att[i]->attlen, val);
     122         1242438 :                         data_length = att_addlength_datum(data_length, att[i]->attlen,
     123                 :                                                                                           val);
     124                 :                 }
     125                 :         }
     126                 : 
     127          572598 :         return data_length;
     128                 : }
     129                 : 
     130                 : /* ----------------
     131                 :  *              ComputeDataSize
     132                 :  *
     133                 :  * Determine size of the data area of a tuple to be constructed
     134                 :  *
     135                 :  * OLD API with char 'n'/' ' convention for indicating nulls
     136                 :  * ----------------
     137                 :  */
     138                 : static Size
     139                 : ComputeDataSize(TupleDesc tupleDesc,
     140                 :                                 Datum *values,
     141                 :                                 char *nulls)
     142          141966 : {
     143          141966 :         Size            data_length = 0;
     144                 :         int                     i;
     145          141966 :         int                     numberOfAttributes = tupleDesc->natts;
     146          141966 :         Form_pg_attribute *att = tupleDesc->attrs;
     147                 : 
     148         1061221 :         for (i = 0; i < numberOfAttributes; i++)
     149                 :         {
     150                 :                 Datum           val;
     151                 : 
     152          919255 :                 if (nulls[i] != ' ')
     153          245497 :                         continue;
     154                 : 
     155          673758 :                 val = values[i];
     156                 : 
     157          720922 :                 if (ATT_IS_PACKABLE(att[i]) &&
     158                 :                         VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
     159                 :                 {
     160                 :                         /*
     161                 :                          * we're anticipating converting to a short varlena header, so
     162                 :                          * adjust length and don't count any alignment
     163                 :                          */
     164           47164 :                         data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
     165                 :                 }
     166                 :                 else
     167                 :                 {
     168          626594 :                         data_length = att_align_datum(data_length, att[i]->attalign,
     169                 :                                                                                   att[i]->attlen, val);
     170          626594 :                         data_length = att_addlength_datum(data_length, att[i]->attlen,
     171                 :                                                                                           val);
     172                 :                 }
     173                 :         }
     174                 : 
     175          141966 :         return data_length;
     176                 : }
     177                 : 
     178                 : /*
     179                 :  * heap_fill_tuple
     180                 :  *              Load data portion of a tuple from values/isnull arrays
     181                 :  *
     182                 :  * We also fill the null bitmap (if any) and set the infomask bits
     183                 :  * that reflect the tuple's data contents.
     184                 :  *
     185                 :  * NOTE: it is now REQUIRED that the caller have pre-zeroed the data area.
     186                 :  */
     187                 : void
     188                 : heap_fill_tuple(TupleDesc tupleDesc,
     189                 :                                 Datum *values, bool *isnull,
     190                 :                                 char *data, Size data_size,
     191                 :                                 uint16 *infomask, bits8 *bit)
     192          568570 : {
     193                 :         bits8      *bitP;
     194                 :         int                     bitmask;
     195                 :         int                     i;
     196          568570 :         int                     numberOfAttributes = tupleDesc->natts;
     197          568570 :         Form_pg_attribute *att = tupleDesc->attrs;
     198                 : 
     199                 : #ifdef USE_ASSERT_CHECKING
     200                 :         char       *start = data;
     201                 : #endif
     202                 : 
     203          568570 :         if (bit != NULL)
     204                 :         {
     205           21216 :                 bitP = &bit[-1];
     206           21216 :                 bitmask = HIGHBIT;
     207                 :         }
     208                 :         else
     209                 :         {
     210                 :                 /* just to keep compiler quiet */
     211          547354 :                 bitP = NULL;
     212          547354 :                 bitmask = 0;
     213                 :         }
     214                 : 
     215          568570 :         *infomask &= ~(HEAP_HASNULL | HEAP_HASVARWIDTH | HEAP_HASEXTERNAL);
     216                 : 
     217         1938395 :         for (i = 0; i < numberOfAttributes; i++)
     218                 :         {
     219                 :                 Size            data_length;
     220                 : 
     221         1369825 :                 if (bit != NULL)
     222                 :                 {
     223          153771 :                         if (bitmask != HIGHBIT)
     224          132324 :                                 bitmask <<= 1;
     225                 :                         else
     226                 :                         {
     227           21447 :                                 bitP += 1;
     228           21447 :                                 *bitP = 0x0;
     229           21447 :                                 bitmask = 1;
     230                 :                         }
     231                 : 
     232          153771 :                         if (isnull[i])
     233                 :                         {
     234          131502 :                                 *infomask |= HEAP_HASNULL;
     235          131502 :                                 continue;
     236                 :                         }
     237                 : 
     238           22269 :                         *bitP |= bitmask;
     239                 :                 }
     240                 : 
     241                 :                 /*
     242                 :                  * XXX we use the att_align macros on the pointer value itself, not on
     243                 :                  * an offset.  This is a bit of a hack.
     244                 :                  */
     245                 : 
     246         1238323 :                 if (att[i]->attbyval)
     247                 :                 {
     248                 :                         /* pass-by-value */
     249          841693 :                         data = (char *) att_align_nominal((long) data, att[i]->attalign);
     250          841693 :                         store_att_byval(data, values[i], att[i]->attlen);
     251          841693 :                         data_length = att[i]->attlen;
     252                 :                 }
     253          396630 :                 else if (att[i]->attlen == -1)
     254                 :                 {
     255                 :                         /* varlena */
     256          152515 :                         Pointer         val = DatumGetPointer(values[i]);
     257                 : 
     258          152515 :                         *infomask |= HEAP_HASVARWIDTH;
     259          152515 :                         if (VARATT_IS_EXTERNAL(val))
     260                 :                         {
     261              44 :                                 *infomask |= HEAP_HASEXTERNAL;
     262                 :                                 /* no alignment, since it's short by definition */
     263              44 :                                 data_length = VARSIZE_EXTERNAL(val);
     264              44 :                                 memcpy(data, val, data_length);
     265                 :                         }
     266          152471 :                         else if (VARATT_IS_SHORT(val))
     267                 :                         {
     268                 :                                 /* no alignment for short varlenas */
     269           75581 :                                 data_length = VARSIZE_SHORT(val);
     270           75581 :                                 memcpy(data, val, data_length);
     271                 :                         }
     272           88172 :                         else if (VARLENA_ATT_IS_PACKABLE(att[i]) &&
     273                 :                                          VARATT_CAN_MAKE_SHORT(val))
     274                 :                         {
     275                 :                                 /* convert to short varlena -- no alignment */
     276           11282 :                                 data_length = VARATT_CONVERTED_SHORT_SIZE(val);
     277           11282 :                                 SET_VARSIZE_SHORT(data, data_length);
     278           11282 :                                 memcpy(data + 1, VARDATA(val), data_length - 1);
     279                 :                         }
     280                 :                         else
     281                 :                         {
     282                 :                                 /* full 4-byte header varlena */
     283           65608 :                                 data = (char *) att_align_nominal((long) data,
     284                 :                                                                                                   att[i]->attalign);
     285           65608 :                                 data_length = VARSIZE(val);
     286           65608 :                                 memcpy(data, val, data_length);
     287                 :                         }
     288                 :                 }
     289          244115 :                 else if (att[i]->attlen == -2)
     290                 :                 {
     291                 :                         /* cstring ... never needs alignment */
     292             957 :                         *infomask |= HEAP_HASVARWIDTH;
     293                 :                         Assert(att[i]->attalign == 'c');
     294             957 :                         data_length = strlen(DatumGetCString(values[i])) + 1;
     295             957 :                         memcpy(data, DatumGetPointer(values[i]), data_length);
     296                 :                 }
     297                 :                 else
     298                 :                 {
     299                 :                         /* fixed-length pass-by-reference */
     300          243158 :                         data = (char *) att_align_nominal((long) data, att[i]->attalign);
     301                 :                         Assert(att[i]->attlen > 0);
     302          243158 :                         data_length = att[i]->attlen;
     303          243158 :                         memcpy(data, DatumGetPointer(values[i]), data_length);
     304                 :                 }
     305                 : 
     306         1238323 :                 data += data_length;
     307                 :         }
     308                 : 
     309                 :         Assert((data - start) == data_size);
     310          568570 : }
     311                 : 
     312                 : /* ----------------
     313                 :  *              DataFill
     314                 :  *
     315                 :  * Load data portion of a tuple from values/nulls arrays
     316                 :  *
     317                 :  * OLD API with char 'n'/' ' convention for indicating nulls
     318                 :  * ----------------
     319                 :  */
     320                 : static void
     321                 : DataFill(TupleDesc tupleDesc,
     322                 :                  Datum *values, char *nulls,
     323                 :                  char *data, Size data_size,
     324                 :                  uint16 *infomask, bits8 *bit)
     325          141966 : {
     326                 :         bits8      *bitP;
     327                 :         int                     bitmask;
     328                 :         int                     i;
     329          141966 :         int                     numberOfAttributes = tupleDesc->natts;
     330          141966 :         Form_pg_attribute *att = tupleDesc->attrs;
     331                 : 
     332                 : #ifdef USE_ASSERT_CHECKING
     333                 :         char       *start = data;
     334                 : #endif
     335                 : 
     336          141966 :         if (bit != NULL)
     337                 :         {
     338           24287 :                 bitP = &bit[-1];
     339           24287 :                 bitmask = HIGHBIT;
     340                 :         }
     341                 :         else
     342                 :         {
     343                 :                 /* just to keep compiler quiet */
     344          117679 :                 bitP = NULL;
     345          117679 :                 bitmask = 0;
     346                 :         }
     347                 : 
     348          141966 :         *infomask &= ~(HEAP_HASNULL | HEAP_HASVARWIDTH | HEAP_HASEXTERNAL);
     349                 : 
     350         1061221 :         for (i = 0; i < numberOfAttributes; i++)
     351                 :         {
     352                 :                 Size            data_length;
     353                 : 
     354          919255 :                 if (bit != NULL)
     355                 :                 {
     356          428419 :                         if (bitmask != HIGHBIT)
     357          362700 :                                 bitmask <<= 1;
     358                 :                         else
     359                 :                         {
     360           65719 :                                 bitP += 1;
     361           65719 :                                 *bitP = 0x0;
     362           65719 :                                 bitmask = 1;
     363                 :                         }
     364                 : 
     365          428419 :                         if (nulls[i] == 'n')
     366                 :                         {
     367          245497 :                                 *infomask |= HEAP_HASNULL;
     368          245497 :                                 continue;
     369                 :                         }
     370                 : 
     371          182922 :                         *bitP |= bitmask;
     372                 :                 }
     373                 : 
     374                 :                 /*
     375                 :                  * XXX we use the att_align macros on the pointer value itself, not on
     376                 :                  * an offset.  This is a bit of a hack.
     377                 :                  */
     378                 : 
     379          673758 :                 if (att[i]->attbyval)
     380                 :                 {
     381                 :                         /* pass-by-value */
     382          508498 :                         data = (char *) att_align_nominal((long) data, att[i]->attalign);
     383          508498 :                         store_att_byval(data, values[i], att[i]->attlen);
     384          508498 :                         data_length = att[i]->attlen;
     385                 :                 }
     386          165260 :                 else if (att[i]->attlen == -1)
     387                 :                 {
     388                 :                         /* varlena */
     389           53731 :                         Pointer         val = DatumGetPointer(values[i]);
     390                 : 
     391           53731 :                         *infomask |= HEAP_HASVARWIDTH;
     392           53731 :                         if (VARATT_IS_EXTERNAL(val))
     393                 :                         {
     394               0 :                                 *infomask |= HEAP_HASEXTERNAL;
     395                 :                                 /* no alignment, since it's short by definition */
     396               0 :                                 data_length = VARSIZE_EXTERNAL(val);
     397               0 :                                 memcpy(data, val, data_length);
     398                 :                         }
     399           53731 :                         else if (VARATT_IS_SHORT(val))
     400                 :                         {
     401                 :                                 /* no alignment for short varlenas */
     402             108 :                                 data_length = VARSIZE_SHORT(val);
     403             108 :                                 memcpy(data, val, data_length);
     404                 :                         }
     405          100787 :                         else if (VARLENA_ATT_IS_PACKABLE(att[i]) &&
     406                 :                                          VARATT_CAN_MAKE_SHORT(val))
     407                 :                         {
     408                 :                                 /* convert to short varlena -- no alignment */
     409           47164 :                                 data_length = VARATT_CONVERTED_SHORT_SIZE(val);
     410           47164 :                                 SET_VARSIZE_SHORT(data, data_length);
     411           47164 :                                 memcpy(data + 1, VARDATA(val), data_length - 1);
     412                 :                         }
     413                 :                         else
     414                 :                         {
     415                 :                                 /* full 4-byte header varlena */
     416            6459 :                                 data = (char *) att_align_nominal((long) data,
     417                 :                                                                                                   att[i]->attalign);
     418            6459 :                                 data_length = VARSIZE(val);
     419            6459 :                                 memcpy(data, val, data_length);
     420                 :                         }
     421                 :                 }
     422          111529 :                 else if (att[i]->attlen == -2)
     423                 :                 {
     424                 :                         /* cstring ... never needs alignment */
     425               0 :                         *infomask |= HEAP_HASVARWIDTH;
     426                 :                         Assert(att[i]->attalign == 'c');
     427               0 :                         data_length = strlen(DatumGetCString(values[i])) + 1;
     428               0 :                         memcpy(data, DatumGetPointer(values[i]), data_length);
     429                 :                 }
     430                 :                 else
     431                 :                 {
     432                 :                         /* fixed-length pass-by-reference */
     433          111529 :                         data = (char *) att_align_nominal((long) data, att[i]->attalign);
     434                 :                         Assert(att[i]->attlen > 0);
     435          111529 :                         data_length = att[i]->attlen;
     436          111529 :                         memcpy(data, DatumGetPointer(values[i]), data_length);
     437                 :                 }
     438                 : 
     439          673758 :                 data += data_length;
     440                 :         }
     441                 : 
     442                 :         Assert((data - start) == data_size);
     443          141966 : }
     444                 : 
     445                 : /* ----------------------------------------------------------------
     446                 :  *                                              heap tuple interface
     447                 :  * ----------------------------------------------------------------
     448                 :  */
     449                 : 
     450                 : /* ----------------
     451                 :  *              heap_attisnull  - returns TRUE iff tuple attribute is not present
     452                 :  * ----------------
     453                 :  */
     454                 : bool
     455                 : heap_attisnull(HeapTuple tup, int attnum)
     456          113870 : {
     457          113870 :         if (attnum > (int) HeapTupleHeaderGetNatts(tup->t_data))
     458               0 :                 return true;
     459                 : 
     460          113870 :         if (attnum > 0)
     461                 :         {
     462          113870 :                 if (HeapTupleNoNulls(tup))
     463           34916 :                         return false;
     464           78954 :                 return att_isnull(attnum - 1, tup->t_data->t_bits);
     465                 :         }
     466                 : 
     467               0 :         switch (attnum)
     468                 :         {
     469                 :                 case TableOidAttributeNumber:
     470                 :                 case SelfItemPointerAttributeNumber:
     471                 :                 case ObjectIdAttributeNumber:
     472                 :                 case MinTransactionIdAttributeNumber:
     473                 :                 case MinCommandIdAttributeNumber:
     474                 :                 case MaxTransactionIdAttributeNumber:
     475                 :                 case MaxCommandIdAttributeNumber:
     476                 :                         /* these are never null */
     477                 :                         break;
     478                 : 
     479                 :                 default:
     480               0 :                         elog(ERROR, "invalid attnum: %d", attnum);
     481                 :         }
     482                 : 
     483               0 :         return false;
     484                 : }
     485                 : 
     486                 : /* ----------------
     487                 :  *              nocachegetattr
     488                 :  *
     489                 :  *              This only gets called from fastgetattr() macro, in cases where
     490                 :  *              we can't use a cacheoffset and the value is not null.
     491                 :  *
     492                 :  *              This caches attribute offsets in the attribute descriptor.
     493                 :  *
     494                 :  *              An alternative way to speed things up would be to cache offsets
     495                 :  *              with the tuple, but that seems more difficult unless you take
     496                 :  *              the storage hit of actually putting those offsets into the
     497                 :  *              tuple you send to disk.  Yuck.
     498                 :  *
     499                 :  *              This scheme will be slightly slower than that, but should
     500                 :  *              perform well for queries which hit large #'s of tuples.  After
     501                 :  *              you cache the offsets once, examining all the other tuples using
     502                 :  *              the same attribute descriptor will go much quicker. -cim 5/4/91
     503                 :  *
     504                 :  *              NOTE: if you need to change this code, see also heap_deform_tuple.
     505                 :  *              Also see nocache_index_getattr, which is the same code for index
     506                 :  *              tuples.
     507                 :  * ----------------
     508                 :  */
     509                 : Datum
     510                 : nocachegetattr(HeapTuple tuple,
     511                 :                            int attnum,
     512                 :                            TupleDesc tupleDesc,
     513                 :                            bool *isnull)
     514         5385459 : {
     515         5385459 :         HeapTupleHeader tup = tuple->t_data;
     516         5385459 :         Form_pg_attribute *att = tupleDesc->attrs;
     517                 :         char       *tp;                         /* ptr to data part of tuple */
     518         5385459 :         bits8      *bp = tup->t_bits;                /* ptr to null bitmap in tuple */
     519         5385459 :         bool            slow = false;   /* do we have to walk attrs? */
     520                 :         int                     off;                    /* current offset within data */
     521                 : 
     522                 :         (void) isnull;                          /* not used */
     523                 : 
     524                 :         /* ----------------
     525                 :          *       Three cases:
     526                 :          *
     527                 :          *       1: No nulls and no variable-width attributes.
     528                 :          *       2: Has a null or a var-width AFTER att.
     529                 :          *       3: Has nulls or var-widths BEFORE att.
     530                 :          * ----------------
     531                 :          */
     532                 : 
     533                 : #ifdef IN_MACRO
     534                 : /* This is handled in the macro */
     535                 :         Assert(attnum > 0);
     536                 : 
     537                 :         if (isnull)
     538                 :                 *isnull = false;
     539                 : #endif
     540                 : 
     541         5385459 :         attnum--;
     542                 : 
     543         5385459 :         if (HeapTupleNoNulls(tuple))
     544                 :         {
     545                 : #ifdef IN_MACRO
     546                 : /* This is handled in the macro */
     547                 :                 if (att[attnum]->attcacheoff >= 0)
     548                 :                 {
     549                 :                         return fetchatt(att[attnum],
     550                 :                                                         (char *) tup + tup->t_hoff +
     551                 :                                                         att[attnum]->attcacheoff);
     552                 :                 }
     553                 : #endif
     554                 :         }
     555                 :         else
     556                 :         {
     557                 :                 /*
     558                 :                  * there's a null somewhere in the tuple
     559                 :                  *
     560                 :                  * check to see if desired att is null
     561                 :                  */
     562                 : 
     563                 : #ifdef IN_MACRO
     564                 : /* This is handled in the macro */
     565                 :                 if (att_isnull(attnum, bp))
     566                 :                 {
     567                 :                         if (isnull)
     568                 :                                 *isnull = true;
     569                 :                         return (Datum) NULL;
     570                 :                 }
     571                 : #endif
     572                 : 
     573                 :                 /*
     574                 :                  * Now check to see if any preceding bits are null...
     575                 :                  */
     576                 :                 {
     577         5333347 :                         int                     byte = attnum >> 3;
     578         5333347 :                         int                     finalbit = attnum & 0x07;
     579                 : 
     580                 :                         /* check for nulls "before" final bit of last byte */
     581         5333347 :                         if ((~bp[byte]) & ((1 << finalbit) - 1))
     582           19285 :                                 slow = true;
     583                 :                         else
     584                 :                         {
     585                 :                                 /* check for nulls in any "earlier" bytes */
     586                 :                                 int                     i;
     587                 : 
     588         5550463 :                                 for (i = 0; i < byte; i++)
     589                 :                                 {
     590          236751 :                                         if (bp[i] != 0xFF)
     591                 :                                         {
     592             350 :                                                 slow = true;
     593             350 :                                                 break;
     594                 :                                         }
     595                 :                                 }
     596                 :                         }
     597                 :                 }
     598                 :         }
     599                 : 
     600         5385459 :         tp = (char *) tup + tup->t_hoff;
     601                 : 
     602         5385459 :         if (!slow)
     603                 :         {
     604                 :                 /*
     605                 :                  * If we get here, there are no nulls up to and including the target
     606                 :                  * attribute.  If we have a cached offset, we can use it.
     607                 :                  */
     608         5365824 :                 if (att[attnum]->attcacheoff >= 0)
     609                 :                 {
     610         5300716 :                         return fetchatt(att[attnum],
     611                 :                                                         tp + att[attnum]->attcacheoff);
     612                 :                 }
     613                 : 
     614                 :                 /*
     615                 :                  * Otherwise, check for non-fixed-length attrs up to and including
     616                 :                  * target.      If there aren't any, it's safe to cheaply initialize the
     617                 :                  * cached offsets for these attrs.
     618                 :                  */
     619           65108 :                 if (HeapTupleHasVarWidth(tuple))
     620                 :                 {
     621                 :                         int                     j;
     622                 : 
     623          180268 :                         for (j = 0; j <= attnum; j++)
     624                 :                         {
     625          179839 :                                 if (att[j]->attlen <= 0)
     626                 :                                 {
     627           63422 :                                         slow = true;
     628           63422 :                                         break;
     629                 :                                 }
     630                 :                         }
     631                 :                 }
     632                 :         }
     633                 : 
     634           84743 :         if (!slow)
     635                 :         {
     636            1686 :                 int                     natts = tupleDesc->natts;
     637            1686 :                 int                     j = 1;
     638                 : 
     639                 :                 /*
     640                 :                  * If we get here, we have a tuple with no nulls or var-widths up to
     641                 :                  * and including the target attribute, so we can use the cached offset
     642                 :                  * ... only we don't have it yet, or we'd not have got here.  Since
     643                 :                  * it's cheap to compute offsets for fixed-width columns, we take the
     644                 :                  * opportunity to initialize the cached offsets for *all* the leading
     645                 :                  * fixed-width columns, in hope of avoiding future visits to this
     646                 :                  * routine.
     647                 :                  */
     648            1686 :                 att[0]->attcacheoff = 0;
     649                 : 
     650                 :                 /* we might have set some offsets in the slow path previously */
     651            3372 :                 while (j < natts && att[j]->attcacheoff > 0)
     652               0 :                         j++;
     653                 : 
     654            1686 :                 off = att[j - 1]->attcacheoff + att[j - 1]->attlen;
     655                 : 
     656           16907 :                 for (; j < natts; j++)
     657                 :                 {
     658           16099 :                         if (att[j]->attlen <= 0)
     659             878 :                                 break;
     660                 : 
     661           15221 :                         off = att_align_nominal(off, att[j]->attalign);
     662                 : 
     663           15221 :                         att[j]->attcacheoff = off;
     664                 : 
     665           15221 :                         off += att[j]->attlen;
     666                 :                 }
     667                 : 
     668                 :                 Assert(j > attnum);
     669                 : 
     670            1686 :                 off = att[attnum]->attcacheoff;
     671                 :         }
     672                 :         else
     673                 :         {
     674           83057 :                 bool            usecache = true;
     675                 :                 int                     i;
     676                 : 
     677                 :                 /*
     678                 :                  * Now we know that we have to walk the tuple CAREFULLY.  But we still
     679                 :                  * might be able to cache some offsets for next time.
     680                 :                  *
     681                 :                  * Note - This loop is a little tricky.  For each non-null attribute,
     682                 :                  * we have to first account for alignment padding before the attr,
     683                 :                  * then advance over the attr based on its length.      Nulls have no
     684                 :                  * storage and no alignment padding either.  We can use/set
     685                 :                  * attcacheoff until we reach either a null or a var-width attribute.
     686                 :                  */
     687           83057 :                 off = 0;
     688          493077 :                 for (i = 0;; i++)               /* loop exit is at "break" */
     689                 :                 {
     690          493077 :                         if (HeapTupleHasNulls(tuple) && att_isnull(i, bp))
     691                 :                         {
     692           79060 :                                 usecache = false;
     693           79060 :                                 continue;               /* this cannot be the target att */
     694                 :                         }
     695                 : 
     696                 :                         /* If we know the next offset, we can skip the rest */
     697          685405 :                         if (usecache && att[i]->attcacheoff >= 0)
     698          271388 :                                 off = att[i]->attcacheoff;
     699          142629 :                         else if (att[i]->attlen == -1)
     700                 :                         {
     701                 :                                 /*
     702                 :                                  * We can only cache the offset for a varlena attribute if the
     703                 :                                  * offset is already suitably aligned, so that there would be
     704                 :                                  * no pad bytes in any case: then the offset will be valid for
     705                 :                                  * either an aligned or unaligned value.
     706                 :                                  */
     707           80936 :                                 if (usecache &&
     708                 :                                         off == att_align_nominal(off, att[i]->attalign))
     709            1049 :                                         att[i]->attcacheoff = off;
     710                 :                                 else
     711                 :                                 {
     712           78838 :                                         off = att_align_pointer(off, att[i]->attalign, -1,
     713                 :                                                                                         tp + off);
     714           78838 :                                         usecache = false;
     715                 :                                 }
     716                 :                         }
     717                 :                         else
     718                 :                         {
     719                 :                                 /* not varlena, so safe to use att_align_nominal */
     720           62742 :                                 off = att_align_nominal(off, att[i]->attalign);
     721                 : 
     722           62742 :                                 if (usecache)
     723            3287 :                                         att[i]->attcacheoff = off;
     724                 :                         }
     725                 : 
     726          414017 :                         if (i == attnum)
     727           83057 :                                 break;
     728                 : 
     729          330960 :                         off = att_addlength_pointer(off, att[i]->attlen, tp + off);
     730                 : 
     731          330960 :                         if (usecache && att[i]->attlen <= 0)
     732           64015 :                                 usecache = false;
     733          410020 :                 }
     734                 :         }
     735                 : 
     736           84743 :         return fetchatt(att[attnum], tp + off);
     737                 : }
     738                 : 
     739                 : /* ----------------
     740                 :  *              heap_getsysattr
     741                 :  *
     742                 :  *              Fetch the value of a system attribute for a tuple.
     743                 :  *
     744                 :  * This is a support routine for the heap_getattr macro.  The macro
     745                 :  * has already determined that the attnum refers to a system attribute.
     746                 :  * ----------------
     747                 :  */
     748                 : Datum
     749                 : heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
     750         1868618 : {
     751                 :         Datum           result;
     752                 : 
     753                 :         Assert(tup);
     754                 : 
     755                 :         /* Currently, no sys attribute ever reads as NULL. */
     756         1868618 :         if (isnull)
     757         1868618 :                 *isnull = false;
     758                 : 
     759         1868618 :         switch (attnum)
     760                 :         {
     761                 :                 case SelfItemPointerAttributeNumber:
     762                 :                         /* pass-by-reference datatype */
     763           11072 :                         result = PointerGetDatum(&(tup->t_self));
     764           11072 :                         break;
     765                 :                 case ObjectIdAttributeNumber:
     766         1853162 :                         result = ObjectIdGetDatum(HeapTupleGetOid(tup));
     767         1853162 :                         break;
     768                 :                 case MinTransactionIdAttributeNumber:
     769               6 :                         result = TransactionIdGetDatum(HeapTupleHeaderGetXmin(tup->t_data));
     770               6 :                         break;
     771                 :                 case MaxTransactionIdAttributeNumber:
     772               0 :                         result = TransactionIdGetDatum(HeapTupleHeaderGetXmax(tup->t_data));
     773               0 :                         break;
     774                 :                 case MinCommandIdAttributeNumber:
     775                 :                 case MaxCommandIdAttributeNumber:
     776                 : 
     777                 :                         /*
     778                 :                          * cmin and cmax are now both aliases for the same field, which
     779                 :                          * can in fact also be a combo command id.      XXX perhaps we should
     780                 :                          * return the "real" cmin or cmax if possible, that is if we are
     781                 :                          * inside the originating transaction?
     782                 :                          */
     783              31 :                         result = CommandIdGetDatum(HeapTupleHeaderGetRawCommandId(tup->t_data));
     784              31 :                         break;
     785                 :                 case TableOidAttributeNumber:
     786            4347 :                         result = ObjectIdGetDatum(tup->t_tableOid);
     787            4347 :                         break;
     788                 :                 default:
     789               0 :                         elog(ERROR, "invalid attnum: %d", attnum);
     790               0 :                         result = 0;                     /* keep compiler quiet */
     791                 :                         break;
     792                 :         }
     793         1868618 :         return result;
     794                 : }
     795                 : 
     796                 : /* ----------------
     797                 :  *              heap_copytuple
     798                 :  *
     799                 :  *              returns a copy of an entire tuple
     800                 :  *
     801                 :  * The HeapTuple struct, tuple header, and tuple data are all allocated
     802                 :  * as a single palloc() block.
     803                 :  * ----------------
     804                 :  */
     805                 : HeapTuple
     806                 : heap_copytuple(HeapTuple tuple)
     807           63819 : {
     808                 :         HeapTuple       newTuple;
     809                 : 
     810           63819 :         if (!HeapTupleIsValid(tuple) || tuple->t_data == NULL)
     811               0 :                 return NULL;
     812                 : 
     813           63819 :         newTuple = (HeapTuple) palloc(HEAPTUPLESIZE + tuple->t_len);
     814           63819 :         newTuple->t_len = tuple->t_len;
     815           63819 :         newTuple->t_self = tuple->t_self;
     816           63819 :         newTuple->t_tableOid = tuple->t_tableOid;
     817           63819 :         newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE);
     818           63819 :         memcpy((char *) newTuple->t_data, (char *) tuple->t_data, tuple->t_len);
     819           63819 :         return newTuple;
     820                 : }
     821                 : 
     822                 : /* ----------------
     823                 :  *              heap_copytuple_with_tuple
     824                 :  *
     825                 :  *              copy a tuple into a caller-supplied HeapTuple management struct
     826                 :  *
     827                 :  * Note that after calling this function, the "dest" HeapTuple will not be
     828                 :  * allocated as a single palloc() block (unlike with heap_copytuple()).
     829                 :  * ----------------
     830                 :  */
     831                 : void
     832                 : heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
     833           53213 : {
     834           53213 :         if (!HeapTupleIsValid(src) || src->t_data == NULL)
     835                 :         {
     836               0 :                 dest->t_data = NULL;
     837               0 :                 return;
     838                 :         }
     839                 : 
     840           53213 :         dest->t_len = src->t_len;
     841           53213 :         dest->t_self = src->t_self;
     842           53213 :         dest->t_tableOid = src->t_tableOid;
     843           53213 :         dest->t_data = (HeapTupleHeader) palloc(src->t_len);
     844           53213 :         memcpy((char *) dest->t_data, (char *) src->t_data, src->t_len);
     845                 : }
     846                 : 
     847                 : /*
     848                 :  * heap_form_tuple
     849                 :  *              construct a tuple from the given values[] and isnull[] arrays,
     850                 :  *              which are of the length indicated by tupleDescriptor->natts
     851                 :  *
     852                 :  * The result is allocated in the current memory context.
     853                 :  */
     854                 : HeapTuple
     855                 : heap_form_tuple(TupleDesc tupleDescriptor,
     856                 :                                 Datum *values,
     857                 :                                 bool *isnull)
     858           94244 : {
     859                 :         HeapTuple       tuple;                  /* return tuple */
     860                 :         HeapTupleHeader td;                     /* tuple data */
     861                 :         Size            len,
     862                 :                                 data_len;
     863                 :         int                     hoff;
     864           94244 :         bool            hasnull = false;
     865           94244 :         Form_pg_attribute *att = tupleDescriptor->attrs;
     866           94244 :         int                     numberOfAttributes = tupleDescriptor->natts;
     867                 :         int                     i;
     868                 : 
     869           94244 :         if (numberOfAttributes > MaxTupleAttributeNumber)
     870               0 :                 ereport(ERROR,
     871                 :                                 (errcode(ERRCODE_TOO_MANY_COLUMNS),
     872                 :                                  errmsg("number of columns (%d) exceeds limit (%d)",
     873                 :                                                 numberOfAttributes, MaxTupleAttributeNumber)));
     874                 : 
     875                 :         /*
     876                 :          * Check for nulls and embedded tuples; expand any toasted attributes in
     877                 :          * embedded tuples.  This preserves the invariant that toasting can only
     878                 :          * go one level deep.
     879                 :          *
     880                 :          * We can skip calling toast_flatten_tuple_attribute() if the attribute
     881                 :          * couldn't possibly be of composite type.  All composite datums are
     882                 :          * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
     883                 :          * if an attribute is already toasted, it must have been sent to disk
     884                 :          * already and so cannot contain toasted attributes.
     885                 :          */
     886          573190 :         for (i = 0; i < numberOfAttributes; i++)
     887                 :         {
     888          478946 :                 if (isnull[i])
     889          129507 :                         hasnull = true;
     890          349439 :                 else if (att[i]->attlen == -1 &&
     891                 :                                  att[i]->attalign == 'd' &&
     892                 :                                  att[i]->attndims == 0 &&
     893                 :                                  !VARATT_IS_EXTENDED(values[i]))
     894                 :                 {
     895            3216 :                         values[i] = toast_flatten_tuple_attribute(values[i],
     896                 :                                                                                                           att[i]->atttypid,
     897                 :                                                                                                           att[i]->atttypmod);
     898                 :                 }
     899                 :         }
     900                 : 
     901                 :         /*
     902                 :          * Determine total space needed
     903                 :          */
     904           94244 :         len = offsetof(HeapTupleHeaderData, t_bits);
     905                 : 
     906           94244 :         if (hasnull)
     907           19700 :                 len += BITMAPLEN(numberOfAttributes);
     908                 : 
     909           94244 :         if (tupleDescriptor->tdhasoid)
     910            9341 :                 len += sizeof(Oid);
     911                 : 
     912           94244 :         hoff = len = MAXALIGN(len); /* align user data safely */
     913                 : 
     914           94244 :         data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
     915                 : 
     916           94244 :         len += data_len;
     917                 : 
     918                 :         /*
     919                 :          * Allocate and zero the space needed.  Note that the tuple body and
     920                 :          * HeapTupleData management structure are allocated in one chunk.
     921                 :          */
     922           94244 :         tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
     923           94244 :         tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
     924                 : 
     925                 :         /*
     926                 :          * And fill in the information.  Note we fill the Datum fields even though
     927                 :          * this tuple may never become a Datum.
     928                 :          */
     929           94244 :         tuple->t_len = len;
     930           94244 :         ItemPointerSetInvalid(&(tuple->t_self));
     931           94244 :         tuple->t_tableOid = InvalidOid;
     932                 : 
     933           94244 :         HeapTupleHeaderSetDatumLength(td, len);
     934           94244 :         HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);
     935           94244 :         HeapTupleHeaderSetTypMod(td, tupleDescriptor->tdtypmod);
     936                 : 
     937           94244 :         HeapTupleHeaderSetNatts(td, numberOfAttributes);
     938           94244 :         td->t_hoff = hoff;
     939                 : 
     940           94244 :         if (tupleDescriptor->tdhasoid)               /* else leave infomask = 0 */
     941            9341 :                 td->t_infomask = HEAP_HASOID;
     942                 : 
     943           94244 :         heap_fill_tuple(tupleDescriptor,
     944                 :                                         values,
     945                 :                                         isnull,
     946                 :                                         (char *) td + hoff,
     947                 :                                         data_len,
     948                 :                                         &td->t_infomask,
     949                 :                                         (hasnull ? td->t_bits : NULL));
     950                 : 
     951           94244 :         return tuple;
     952                 : }
     953                 : 
     954                 : /* ----------------
     955                 :  *              heap_formtuple
     956                 :  *
     957                 :  *              construct a tuple from the given values[] and nulls[] arrays
     958                 :  *
     959                 :  *              Null attributes are indicated by a 'n' in the appropriate byte
     960                 :  *              of nulls[]. Non-null attributes are indicated by a ' ' (space).
     961                 :  *
     962                 :  * OLD API with char 'n'/' ' convention for indicating nulls
     963                 :  * ----------------
     964                 :  */
     965                 : HeapTuple
     966                 : heap_formtuple(TupleDesc tupleDescriptor,
     967                 :                            Datum *values,
     968                 :                            char *nulls)
     969          141966 : {
     970                 :         HeapTuple       tuple;                  /* return tuple */
     971                 :         HeapTupleHeader td;                     /* tuple data */
     972                 :         Size            len,
     973                 :                                 data_len;
     974                 :         int                     hoff;
     975          141966 :         bool            hasnull = false;
     976          141966 :         Form_pg_attribute *att = tupleDescriptor->attrs;
     977          141966 :         int                     numberOfAttributes = tupleDescriptor->natts;
     978                 :         int                     i;
     979                 : 
     980          141966 :         if (numberOfAttributes > MaxTupleAttributeNumber)
     981               0 :                 ereport(ERROR,
     982                 :                                 (errcode(ERRCODE_TOO_MANY_COLUMNS),
     983                 :                                  errmsg("number of columns (%d) exceeds limit (%d)",
     984                 :                                                 numberOfAttributes, MaxTupleAttributeNumber)));
     985                 : 
     986                 :         /*
     987                 :          * Check for nulls and embedded tuples; expand any toasted attributes in
     988                 :          * embedded tuples.  This preserves the invariant that toasting can only
     989                 :          * go one level deep.
     990                 :          *
     991                 :          * We can skip calling toast_flatten_tuple_attribute() if the attribute
     992                 :          * couldn't possibly be of composite type.  All composite datums are
     993                 :          * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
     994                 :          * if an attribute is already toasted, it must have been sent to disk
     995                 :          * already and so cannot contain toasted attributes.
     996                 :          */
     997         1061221 :         for (i = 0; i < numberOfAttributes; i++)
     998                 :         {
     999          919255 :                 if (nulls[i] != ' ')
    1000          245497 :                         hasnull = true;
    1001          673758 :                 else if (att[i]->attlen == -1 &&
    1002                 :                                  att[i]->attalign == 'd' &&
    1003                 :                                  att[i]->attndims == 0 &&
    1004                 :                                  !VARATT_IS_EXTENDED(values[i]))
    1005                 :                 {
    1006            5563 :                         values[i] = toast_flatten_tuple_attribute(values[i],
    1007                 :                                                                                                           att[i]->atttypid,
    1008                 :                                                                                                           att[i]->atttypmod);
    1009                 :                 }
    1010                 :         }
    1011                 : 
    1012                 :         /*
    1013                 :          * Determine total space needed
    1014                 :          */
    1015          141966 :         len = offsetof(HeapTupleHeaderData, t_bits);
    1016                 : 
    1017          141966 :         if (hasnull)
    1018           24287 :                 len += BITMAPLEN(numberOfAttributes);
    1019                 : 
    1020          141966 :         if (tupleDescriptor->tdhasoid)
    1021           32547 :                 len += sizeof(Oid);
    1022                 : 
    1023          141966 :         hoff = len = MAXALIGN(len); /* align user data safely */
    1024                 : 
    1025          141966 :         data_len = ComputeDataSize(tupleDescriptor, values, nulls);
    1026                 : 
    1027          141966 :         len += data_len;
    1028                 : 
    1029                 :         /*
    1030                 :          * Allocate and zero the space needed.  Note that the tuple body and
    1031                 :          * HeapTupleData management structure are allocated in one chunk.
    1032                 :          */
    1033          141966 :         tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
    1034          141966 :         tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
    1035                 : 
    1036                 :         /*
    1037                 :          * And fill in the information.  Note we fill the Datum fields even though
    1038                 :          * this tuple may never become a Datum.
    1039                 :          */
    1040          141966 :         tuple->t_len = len;
    1041          141966 :         ItemPointerSetInvalid(&(tuple->t_self));
    1042          141966 :         tuple->t_tableOid = InvalidOid;
    1043                 : 
    1044          141966 :         HeapTupleHeaderSetDatumLength(td, len);
    1045          141966 :         HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);
    1046          141966 :         HeapTupleHeaderSetTypMod(td, tupleDescriptor->tdtypmod);
    1047                 : 
    1048          141966 :         HeapTupleHeaderSetNatts(td, numberOfAttributes);
    1049          141966 :         td->t_hoff = hoff;
    1050                 : 
    1051          141966 :         if (tupleDescriptor->tdhasoid)               /* else leave infomask = 0 */
    1052           32547 :                 td->t_infomask = HEAP_HASOID;
    1053                 : 
    1054          141966 :         DataFill(tupleDescriptor,
    1055                 :                          values,
    1056                 :                          nulls,
    1057                 :                          (char *) td + hoff,
    1058                 :                          data_len,
    1059                 :                          &td->t_infomask,
    1060                 :                          (hasnull ? td->t_bits : NULL));
    1061                 : 
    1062          141966 :         return tuple;
    1063                 : }
    1064                 : 
    1065                 : 
    1066                 : /*
    1067                 :  * heap_modify_tuple
    1068                 :  *              form a new tuple from an old tuple and a set of replacement values.
    1069                 :  *
    1070                 :  * The replValues, replIsnull, and doReplace arrays must be of the length
    1071                 :  * indicated by tupleDesc->natts.  The new tuple is constructed using the data
    1072                 :  * from replValues/replIsnull at columns where doReplace is true, and using
    1073                 :  * the data from the old tuple at columns where doReplace is false.
    1074                 :  *
    1075                 :  * The result is allocated in the current memory context.
    1076                 :  */
    1077                 : HeapTuple
    1078                 : heap_modify_tuple(HeapTuple tuple,
    1079                 :                                   TupleDesc tupleDesc,
    1080                 :                                   Datum *replValues,
    1081                 :                                   bool *replIsnull,
    1082                 :                                   bool *doReplace)
    1083               0 : {
    1084               0 :         int                     numberOfAttributes = tupleDesc->natts;
    1085                 :         int                     attoff;
    1086                 :         Datum      *values;
    1087                 :         bool       *isnull;
    1088                 :         HeapTuple       newTuple;
    1089                 : 
    1090                 :         /*
    1091                 :          * allocate and fill values and isnull arrays from either the tuple or the
    1092                 :          * repl information, as appropriate.
    1093                 :          *
    1094                 :          * NOTE: it's debatable whether to use heap_deform_tuple() here or just
    1095                 :          * heap_getattr() only the non-replaced colums.  The latter could win if
    1096                 :          * there are many replaced columns and few non-replaced ones. However,
    1097                 :          * heap_deform_tuple costs only O(N) while the heap_getattr way would cost
    1098                 :          * O(N^2) if there are many non-replaced columns, so it seems better to
    1099                 :          * err on the side of linear cost.
    1100                 :          */
    1101               0 :         values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
    1102               0 :         isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
    1103                 : 
    1104               0 :         heap_deform_tuple(tuple, tupleDesc, values, isnull);
    1105                 : 
    1106               0 :         for (attoff = 0; attoff < numberOfAttributes; attoff++)
    1107                 :         {
    1108               0 :                 if (doReplace[attoff])
    1109                 :                 {
    1110               0 :                         values[attoff] = replValues[attoff];
    1111               0 :                         isnull[attoff] = replIsnull[attoff];
    1112                 :                 }
    1113                 :         }
    1114                 : 
    1115                 :         /*
    1116                 :          * create a new tuple from the values and isnull arrays
    1117                 :          */
    1118               0 :         newTuple = heap_form_tuple(tupleDesc, values, isnull);
    1119                 : 
    1120               0 :         pfree(values);
    1121               0 :         pfree(isnull);
    1122                 : 
    1123                 :         /*
    1124                 :          * copy the identification info of the old tuple: t_ctid, t_self, and OID
    1125                 :          * (if any)
    1126                 :          */
    1127               0 :         newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
    1128               0 :         newTuple->t_self = tuple->t_self;
    1129               0 :         newTuple->t_tableOid = tuple->t_tableOid;
    1130               0 :         if (tupleDesc->tdhasoid)
    1131               0 :                 HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple));
    1132                 : 
    1133               0 :         return newTuple;
    1134                 : }
    1135                 : 
    1136                 : /* ----------------
    1137                 :  *              heap_modifytuple
    1138                 :  *
    1139                 :  *              forms a new tuple from an old tuple and a set of replacement values.
    1140                 :  *              returns a new palloc'ed tuple.
    1141                 :  *
    1142                 :  * OLD API with char 'n'/' ' convention for indicating nulls, and
    1143                 :  * char 'r'/' ' convention for indicating whether to replace columns.
    1144                 :  * ----------------
    1145                 :  */
    1146                 : HeapTuple
    1147                 : heap_modifytuple(HeapTuple tuple,
    1148                 :                                  TupleDesc tupleDesc,
    1149                 :                                  Datum *replValues,
    1150                 :                                  char *replNulls,
    1151                 :                                  char *replActions)
    1152             226 : {
    1153             226 :         int                     numberOfAttributes = tupleDesc->natts;
    1154                 :         int                     attoff;
    1155                 :         Datum      *values;
    1156                 :         char       *nulls;
    1157                 :         HeapTuple       newTuple;
    1158                 : 
    1159                 :         /*
    1160                 :          * allocate and fill values and nulls arrays from either the tuple or the
    1161                 :          * repl information, as appropriate.
    1162                 :          *
    1163                 :          * NOTE: it's debatable whether to use heap_deformtuple() here or just
    1164                 :          * heap_getattr() only the non-replaced colums.  The latter could win if
    1165                 :          * there are many replaced columns and few non-replaced ones. However,
    1166                 :          * heap_deformtuple costs only O(N) while the heap_getattr way would cost
    1167                 :          * O(N^2) if there are many non-replaced columns, so it seems better to
    1168                 :          * err on the side of linear cost.
    1169                 :          */
    1170             226 :         values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
    1171             226 :         nulls = (char *) palloc(numberOfAttributes * sizeof(char));
    1172                 : 
    1173             226 :         heap_deformtuple(tuple, tupleDesc, values, nulls);
    1174                 : 
    1175            4959 :         for (attoff = 0; attoff < numberOfAttributes; attoff++)
    1176                 :         {
    1177            4733 :                 if (replActions[attoff] == 'r')
    1178                 :                 {
    1179            1577 :                         values[attoff] = replValues[attoff];
    1180            1577 :                         nulls[attoff] = replNulls[attoff];
    1181                 :                 }
    1182            3156 :                 else if (replActions[attoff] != ' ')
    1183               0 :                         elog(ERROR, "unrecognized replace flag: %d",
    1184                 :                                  (int) replActions[attoff]);
    1185                 :         }
    1186                 : 
    1187                 :         /*
    1188                 :          * create a new tuple from the values and nulls arrays
    1189                 :          */
    1190             226 :         newTuple = heap_formtuple(tupleDesc, values, nulls);
    1191                 : 
    1192             226 :         pfree(values);
    1193             226 :         pfree(nulls);
    1194                 : 
    1195                 :         /*
    1196                 :          * copy the identification info of the old tuple: t_ctid, t_self, and OID
    1197                 :          * (if any)
    1198                 :          */
    1199             226 :         newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
    1200             226 :         newTuple->t_self = tuple->t_self;
    1201             226 :         newTuple->t_tableOid = tuple->t_tableOid;
    1202             226 :         if (tupleDesc->tdhasoid)
    1203             210 :                 HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple));
    1204                 : 
    1205             226 :         return newTuple;
    1206                 : }
    1207                 : 
    1208                 : /*
    1209                 :  * heap_deform_tuple
    1210                 :  *              Given a tuple, extract data into values/isnull arrays; this is
    1211                 :  *              the inverse of heap_form_tuple.
    1212                 :  *
    1213                 :  *              Storage for the values/isnull arrays is provided by the caller;
    1214                 :  *              it should be sized according to tupleDesc->natts not tuple->t_natts.
    1215                 :  *
    1216                 :  *              Note that for pass-by-reference datatypes, the pointer placed
    1217                 :  *              in the Datum will point into the given tuple.
    1218                 :  *
    1219                 :  *              When all or most of a tuple's fields need to be extracted,
    1220                 :  *              this routine will be significantly quicker than a loop around
    1221                 :  *              heap_getattr; the loop will become O(N^2) as soon as any
    1222                 :  *              noncacheable attribute offsets are involved.
    1223                 :  */
    1224                 : void
    1225                 : heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
    1226                 :                                   Datum *values, bool *isnull)
    1227            3053 : {
    1228            3053 :         HeapTupleHeader tup = tuple->t_data;
    1229            3053 :         bool            hasnulls = HeapTupleHasNulls(tuple);
    1230            3053 :         Form_pg_attribute *att = tupleDesc->attrs;
    1231            3053 :         int                     tdesc_natts = tupleDesc->natts;
    1232                 :         int                     natts;                  /* number of atts to extract */
    1233                 :         int                     attnum;
    1234                 :         char       *tp;                         /* ptr to tuple data */
    1235                 :         long            off;                    /* offset in tuple data */
    1236            3053 :         bits8      *bp = tup->t_bits;                /* ptr to null bitmap in tuple */
    1237            3053 :         bool            slow = false;   /* can we use/set attcacheoff? */
    1238                 : 
    1239            3053 :         natts = HeapTupleHeaderGetNatts(tup);
    1240                 : 
    1241                 :         /*
    1242                 :          * In inheritance situations, it is possible that the given tuple actually
    1243                 :          * has more fields than the caller is expecting.  Don't run off the end of
    1244                 :          * the caller's arrays.
    1245                 :          */
    1246            3053 :         natts = Min(natts, tdesc_natts);
    1247                 : 
    1248            3053 :         tp = (char *) tup + tup->t_hoff;
    1249                 : 
    1250            3053 :         off = 0;
    1251                 : 
    1252           39033 :         for (attnum = 0; attnum < natts; attnum++)
    1253                 :         {
    1254           35980 :                 Form_pg_attribute thisatt = att[attnum];
    1255                 : 
    1256           35980 :                 if (hasnulls && att_isnull(attnum, bp))
    1257                 :                 {
    1258             111 :                         values[attnum] = (Datum) 0;
    1259             111 :                         isnull[attnum] = true;
    1260             111 :                         slow = true;            /* can't use attcacheoff anymore */
    1261             111 :                         continue;
    1262                 :                 }
    1263                 : 
    1264           35869 :                 isnull[attnum] = false;
    1265                 : 
    1266           71066 :                 if (!slow && thisatt->attcacheoff >= 0)
    1267           35197 :                         off = thisatt->attcacheoff;
    1268             672 :                 else if (thisatt->attlen == -1)
    1269                 :                 {
    1270                 :                         /*
    1271                 :                          * We can only cache the offset for a varlena attribute if the
    1272                 :                          * offset is already suitably aligned, so that there would be no
    1273                 :                          * pad bytes in any case: then the offset will be valid for either
    1274                 :                          * an aligned or unaligned value.
    1275                 :                          */
    1276             469 :                         if (!slow &&
    1277                 :                                 off == att_align_nominal(off, thisatt->attalign))
    1278              10 :                                 thisatt->attcacheoff = off;
    1279                 :                         else
    1280                 :                         {
    1281             449 :                                 off = att_align_pointer(off, thisatt->attalign, -1,
    1282                 :                                                                                 tp + off);
    1283             449 :                                 slow = true;
    1284                 :                         }
    1285                 :                 }
    1286                 :                 else
    1287                 :                 {
    1288                 :                         /* not varlena, so safe to use att_align_nominal */
    1289             213 :                         off = att_align_nominal(off, thisatt->attalign);
    1290                 : 
    1291             213 :                         if (!slow)
    1292              43 :                                 thisatt->attcacheoff = off;
    1293                 :                 }
    1294                 : 
    1295           35869 :                 values[attnum] = fetchatt(thisatt, tp + off);
    1296                 : 
    1297           35869 :                 off = att_addlength_pointer(off, thisatt->attlen, tp + off);
    1298                 : 
    1299           35869 :                 if (thisatt->attlen <= 0)
    1300            1309 :                         slow = true;            /* can't use attcacheoff anymore */
    1301                 :         }
    1302                 : 
    1303                 :         /*
    1304                 :          * If tuple doesn't have all the atts indicated by tupleDesc, read the
    1305                 :          * rest as null
    1306                 :          */
    1307               1 :         for (; attnum < tdesc_natts; attnum++)
    1308                 :         {
    1309               1 :                 values[attnum] = (Datum) 0;
    1310               1 :                 isnull[attnum] = true;
    1311                 :         }
    1312            3053 : }
    1313                 : 
    1314                 : /* ----------------
    1315                 :  *              heap_deformtuple
    1316                 :  *
    1317                 :  *              Given a tuple, extract data into values/nulls arrays; this is
    1318                 :  *              the inverse of heap_formtuple.
    1319                 :  *
    1320                 :  *              Storage for the values/nulls arrays is provided by the caller;
    1321                 :  *              it should be sized according to tupleDesc->natts not tuple->t_natts.
    1322                 :  *
    1323                 :  *              Note that for pass-by-reference datatypes, the pointer placed
    1324                 :  *              in the Datum will point into the given tuple.
    1325                 :  *
    1326                 :  *              When all or most of a tuple's fields need to be extracted,
    1327                 :  *              this routine will be significantly quicker than a loop around
    1328                 :  *              heap_getattr; the loop will become O(N^2) as soon as any
    1329                 :  *              noncacheable attribute offsets are involved.
    1330                 :  *
    1331                 :  * OLD API with char 'n'/' ' convention for indicating nulls
    1332                 :  * ----------------
    1333                 :  */
    1334                 : void
    1335                 : heap_deformtuple(HeapTuple tuple,
    1336                 :                                  TupleDesc tupleDesc,
    1337                 :                                  Datum *values,
    1338                 :                                  char *nulls)
    1339             291 : {
    1340             291 :         HeapTupleHeader tup = tuple->t_data;
    1341             291 :         bool            hasnulls = HeapTupleHasNulls(tuple);
    1342             291 :         Form_pg_attribute *att = tupleDesc->attrs;
    1343             291 :         int                     tdesc_natts = tupleDesc->natts;
    1344                 :         int                     natts;                  /* number of atts to extract */
    1345                 :         int                     attnum;
    1346                 :         char       *tp;                         /* ptr to tuple data */
    1347                 :         long            off;                    /* offset in tuple data */
    1348             291 :         bits8      *bp = tup->t_bits;                /* ptr to null bitmap in tuple */
    1349             291 :         bool            slow = false;   /* can we use/set attcacheoff? */
    1350                 : 
    1351             291 :         natts = HeapTupleHeaderGetNatts(tup);
    1352                 : 
    1353                 :         /*
    1354                 :          * In inheritance situations, it is possible that the given tuple actually
    1355                 :          * has more fields than the caller is expecting.  Don't run off the end of
    1356                 :          * the caller's arrays.
    1357                 :          */
    1358             291 :         natts = Min(natts, tdesc_natts);
    1359                 : 
    1360             291 :         tp = (char *) tup + tup->t_hoff;
    1361                 : 
    1362             291 :         off = 0;
    1363                 : 
    1364            5157 :         for (attnum = 0; attnum < natts; attnum++)
    1365                 :         {
    1366            4866 :                 Form_pg_attribute thisatt = att[attnum];
    1367                 : 
    1368            4866 :                 if (hasnulls && att_isnull(attnum, bp))
    1369                 :                 {
    1370             591 :                         values[attnum] = (Datum) 0;
    1371             591 :                         nulls[attnum] = 'n';
    1372             591 :                         slow = true;            /* can't use attcacheoff anymore */
    1373             591 :                         continue;
    1374                 :                 }
    1375                 : 
    1376            4275 :                 nulls[attnum] = ' ';
    1377                 : 
    1378            8057 :                 if (!slow && thisatt->attcacheoff >= 0)
    1379            3782 :                         off = thisatt->attcacheoff;
    1380             493 :                 else if (thisatt->attlen == -1)
    1381                 :                 {
    1382                 :                         /*
    1383                 :                          * We can only cache the offset for a varlena attribute if the
    1384                 :                          * offset is already suitably aligned, so that there would be no
    1385                 :                          * pad bytes in any case: then the offset will be valid for either
    1386                 :                          * an aligned or unaligned value.
    1387                 :                          */
    1388             236 :                         if (!slow &&
    1389                 :                                 off == att_align_nominal(off, thisatt->attalign))
    1390              13 :                                 thisatt->attcacheoff = off;
    1391                 :                         else
    1392                 :                         {
    1393             210 :                                 off = att_align_pointer(off, thisatt->attalign, -1,
    1394                 :                                                                                 tp + off);
    1395             210 :                                 slow = true;
    1396                 :                         }
    1397                 :                 }
    1398                 :                 else
    1399                 :                 {
    1400                 :                         /* not varlena, so safe to use att_align_nominal */
    1401             270 :                         off = att_align_nominal(off, thisatt->attalign);
    1402                 : 
    1403             270 :                         if (!slow)
    1404             264 :                                 thisatt->attcacheoff = off;
    1405                 :                 }
    1406                 : 
    1407            4275 :                 values[attnum] = fetchatt(thisatt, tp + off);
    1408                 : 
    1409            4275 :                 off = att_addlength_pointer(off, thisatt->attlen, tp + off);
    1410                 : 
    1411            4275 :                 if (thisatt->attlen <= 0)
    1412             368 :                         slow = true;            /* can't use attcacheoff anymore */
    1413                 :         }
    1414                 : 
    1415                 :         /*
    1416                 :          * If tuple doesn't have all the atts indicated by tupleDesc, read the
    1417                 :          * rest as null
    1418                 :          */
    1419               1 :         for (; attnum < tdesc_natts; attnum++)
    1420                 :         {
    1421               1 :                 values[attnum] = (Datum) 0;
    1422               1 :                 nulls[attnum] = 'n';
    1423                 :         }
    1424             291 : }
    1425                 : 
    1426                 : /*
    1427                 :  * slot_deform_tuple
    1428                 :  *              Given a TupleTableSlot, extract data from the slot's physical tuple
    1429                 :  *              into its Datum/isnull arrays.  Data is extracted up through the
    1430                 :  *              natts'th column (caller must ensure this is a legal column number).
    1431                 :  *
    1432                 :  *              This is essentially an incremental version of heap_deform_tuple:
    1433                 :  *              on each call we extract attributes up to the one needed, without
    1434                 :  *              re-computing information about previously extracted attributes.
    1435                 :  *              slot->tts_nvalid is the number of attributes already extracted.
    1436                 :  */
    1437                 : static void
    1438                 : slot_deform_tuple(TupleTableSlot *slot, int natts)
    1439         1935009 : {
    1440         1935009 :         HeapTuple       tuple = slot->tts_tuple;
    1441         1935009 :         TupleDesc       tupleDesc = slot->tts_tupleDescriptor;
    1442         1935009 :         Datum      *values = slot->tts_values;
    1443         1935009 :         bool       *isnull = slot->tts_isnull;
    1444         1935009 :         HeapTupleHeader tup = tuple->t_data;
    1445         1935009 :         bool            hasnulls = HeapTupleHasNulls(tuple);
    1446         1935009 :         Form_pg_attribute *att = tupleDesc->attrs;
    1447                 :         int                     attnum;
    1448                 :         char       *tp;                         /* ptr to tuple data */
    1449                 :         long            off;                    /* offset in tuple data */
    1450         1935009 :         bits8      *bp = tup->t_bits;                /* ptr to null bitmap in tuple */
    1451                 :         bool            slow;                   /* can we use/set attcacheoff? */
    1452                 : 
    1453                 :         /*
    1454                 :          * Check whether the first call for this tuple, and initialize or restore
    1455                 :          * loop state.
    1456                 :          */
    1457         1935009 :         attnum = slot->tts_nvalid;
    1458         1935009 :         if (attnum == 0)
    1459                 :         {
    1460                 :                 /* Start from the first attribute */
    1461         1440485 :                 off = 0;
    1462         1440485 :                 slow = false;
    1463                 :         }
    1464                 :         else
    1465                 :         {
    1466                 :                 /* Restore state from previous execution */
    1467          494524 :                 off = slot->tts_off;
    1468          494524 :                 slow = slot->tts_slow;
    1469                 :         }
    1470                 : 
    1471         1935009 :         tp = (char *) tup + tup->t_hoff;
    1472                 : 
    1473         7639395 :         for (; attnum < natts; attnum++)
    1474                 :         {
    1475         5704386 :                 Form_pg_attribute thisatt = att[attnum];
    1476                 : 
    1477         5704386 :                 if (hasnulls && att_isnull(attnum, bp))
    1478                 :                 {
    1479          129989 :                         values[attnum] = (Datum) 0;
    1480          129989 :                         isnull[attnum] = true;
    1481          129989 :                         slow = true;            /* can't use attcacheoff anymore */
    1482          129989 :                         continue;
    1483                 :                 }
    1484                 : 
    1485         5574397 :                 isnull[attnum] = false;
    1486                 : 
    1487        10920341 :                 if (!slow && thisatt->attcacheoff >= 0)
    1488         5345944 :                         off = thisatt->attcacheoff;
    1489          228453 :                 else if (thisatt->attlen == -1)
    1490                 :                 {
    1491                 :                         /*
    1492                 :                          * We can only cache the offset for a varlena attribute if the
    1493                 :                          * offset is already suitably aligned, so that there would be no
    1494                 :                          * pad bytes in any case: then the offset will be valid for either
    1495                 :                          * an aligned or unaligned value.
    1496                 :                          */
    1497          140590 :                         if (!slow &&
    1498                 :                                 off == att_align_nominal(off, thisatt->attalign))
    1499             894 :                                 thisatt->attcacheoff = off;
    1500                 :                         else
    1501                 :                         {
    1502          138802 :                                 off = att_align_pointer(off, thisatt->attalign, -1,
    1503                 :                                                                                 tp + off);
    1504          138802 :                                 slow = true;
    1505                 :                         }
    1506                 :                 }
    1507                 :                 else
    1508                 :                 {
    1509                 :                         /* not varlena, so safe to use att_align_nominal */
    1510           88757 :                         off = att_align_nominal(off, thisatt->attalign);
    1511                 : 
    1512           88757 :                         if (!slow)
    1513            5771 :                                 thisatt->attcacheoff = off;
    1514                 :                 }
    1515                 : 
    1516         5574397 :                 values[attnum] = fetchatt(thisatt, tp + off);
    1517                 : 
    1518         5574397 :                 off = att_addlength_pointer(off, thisatt->attlen, tp + off);
    1519                 : 
    1520         5574397 :                 if (thisatt->attlen <= 0)
    1521          606332 :                         slow = true;            /* can't use attcacheoff anymore */
    1522                 :         }
    1523                 : 
    1524                 :         /*
    1525                 :          * Save state for next execution
    1526                 :          */
    1527         1935009 :         slot->tts_nvalid = attnum;
    1528         1935009 :         slot->tts_off = off;
    1529         1935009 :         slot->tts_slow = slow;
    1530         1935009 : }
    1531                 : 
    1532                 : /*
    1533                 :  * slot_getattr
    1534                 :  *              This function fetches an attribute of the slot's current tuple.
    1535                 :  *              It is functionally equivalent to heap_getattr, but fetches of
    1536                 :  *              multiple attributes of the same tuple will be optimized better,
    1537                 :  *              because we avoid O(N^2) behavior from multiple calls of
    1538                 :  *              nocachegetattr(), even when attcacheoff isn't usable.
    1539                 :  *
    1540                 :  *              A difference from raw heap_getattr is that attnums beyond the
    1541                 :  *              slot's tupdesc's last attribute will be considered NULL even
    1542                 :  *              when the physical tuple is longer than the tupdesc.
    1543                 :  */
    1544                 : Datum
    1545                 : slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
    1546         3013884 : {
    1547         3013884 :         HeapTuple       tuple = slot->tts_tuple;
    1548         3013884 :         TupleDesc       tupleDesc = slot->tts_tupleDescriptor;
    1549                 :         HeapTupleHeader tup;
    1550                 : 
    1551                 :         /*
    1552                 :          * system attributes are handled by heap_getsysattr
    1553                 :          */
    1554         3013884 :         if (attnum <= 0)
    1555                 :         {
    1556          236952 :                 if (tuple == NULL)              /* internal error */
    1557               0 :                         elog(ERROR, "cannot extract system attribute from virtual tuple");
    1558          236952 :                 if (slot->tts_mintuple) /* internal error */
    1559               0 :                         elog(ERROR, "cannot extract system attribute from minimal tuple");
    1560          236952 :                 return heap_getsysattr(tuple, attnum, tupleDesc, isnull);
    1561                 :         }
    1562                 : 
    1563                 :         /*
    1564                 :          * fast path if desired attribute already cached
    1565                 :          */
    1566         2776932 :         if (attnum <= slot->tts_nvalid)
    1567                 :         {
    1568          918335 :                 *isnull = slot->tts_isnull[attnum - 1];
    1569          918335 :                 return slot->tts_values[attnum - 1];
    1570                 :         }
    1571                 : 
    1572                 :         /*
    1573                 :          * return NULL if attnum is out of range according to the tupdesc
    1574                 :          */
    1575         1858597 :         if (attnum > tupleDesc->natts)
    1576                 :         {
    1577               0 :                 *isnull = true;
    1578               0 :                 return (Datum) 0;
    1579                 :         }
    1580                 : 
    1581                 :         /*
    1582                 :          * otherwise we had better have a physical tuple (tts_nvalid should equal
    1583                 :          * natts in all virtual-tuple cases)
    1584                 :          */
    1585         1858597 :         if (tuple == NULL)                      /* internal error */
    1586               0 :                 elog(ERROR, "cannot extract attribute from empty tuple slot");
    1587                 : 
    1588                 :         /*
    1589                 :          * return NULL if attnum is out of range according to the tuple
    1590                 :          *
    1591                 :          * (We have to check this separately because of various inheritance and
    1592                 :          * table-alteration scenarios: the tuple could be either longer or shorter
    1593                 :          * than the tupdesc.)
    1594                 :          */
    1595         1858597 :         tup = tuple->t_data;
    1596         1858597 :         if (attnum > HeapTupleHeaderGetNatts(tup))
    1597                 :         {
    1598               2 :                 *isnull = true;
    1599               2 :                 return (Datum) 0;
    1600                 :         }
    1601                 : 
    1602                 :         /*
    1603                 :          * check if target attribute is null: no point in groveling through tuple
    1604                 :          */
    1605         1858595 :         if (HeapTupleHasNulls(tuple) && att_isnull(attnum - 1, tup->t_bits))
    1606                 :         {
    1607            5818 :                 *isnull = true;
    1608            5818 :                 return (Datum) 0;
    1609                 :         }
    1610                 : 
    1611                 :         /*
    1612                 :          * If the attribute's column has been dropped, we force a NULL result.
    1613                 :          * This case should not happen in normal use, but it could happen if we
    1614                 :          * are executing a plan cached before the column was dropped.
    1615                 :          */
    1616         1852777 :         if (tupleDesc->attrs[attnum - 1]->attisdropped)
    1617                 :         {
    1618               0 :                 *isnull = true;
    1619               0 :                 return (Datum) 0;
    1620                 :         }
    1621                 : 
    1622                 :         /*
    1623                 :          * Extract the attribute, along with any preceding attributes.
    1624                 :          */
    1625         1852777 :         slot_deform_tuple(slot, attnum);
    1626                 : 
    1627                 :         /*
    1628                 :          * The result is acquired from tts_values array.
    1629                 :          */
    1630         1852777 :         *isnull = slot->tts_isnull[attnum - 1];
    1631         1852777 :         return slot->tts_values[attnum - 1];
    1632                 : }
    1633                 : 
    1634                 : /*
    1635                 :  * slot_getallattrs
    1636                 :  *              This function forces all the entries of the slot's Datum/isnull
    1637                 :  *              arrays to be valid.  The caller may then extract data directly
    1638                 :  *              from those arrays instead of using slot_getattr.
    1639                 :  */
    1640                 : void
    1641                 : slot_getallattrs(TupleTableSlot *slot)
    1642           28583 : {
    1643           28583 :         int                     tdesc_natts = slot->tts_tupleDescriptor->natts;
    1644                 :         int                     attnum;
    1645                 :         HeapTuple       tuple;
    1646                 : 
    1647                 :         /* Quick out if we have 'em all already */
    1648           28583 :         if (slot->tts_nvalid == tdesc_natts)
    1649           13581 :                 return;
    1650                 : 
    1651                 :         /*
    1652                 :          * otherwise we had better have a physical tuple (tts_nvalid should equal
    1653                 :          * natts in all virtual-tuple cases)
    1654                 :          */
    1655           15002 :         tuple = slot->tts_tuple;
    1656           15002 :         if (tuple == NULL)                      /* internal error */
    1657               0 :                 elog(ERROR, "cannot extract attribute from empty tuple slot");
    1658                 : 
    1659                 :         /*
    1660                 :          * load up any slots available from physical tuple
    1661                 :          */
    1662           15002 :         attnum = HeapTupleHeaderGetNatts(tuple->t_data);
    1663           15002 :         attnum = Min(attnum, tdesc_natts);
    1664                 : 
    1665           15002 :         slot_deform_tuple(slot, attnum);
    1666                 : 
    1667                 :         /*
    1668                 :          * If tuple doesn't have all the atts indicated by tupleDesc, read the
    1669                 :          * rest as null
    1670                 :          */
    1671           15002 :         for (; attnum < tdesc_natts; attnum++)
    1672                 :         {
    1673               0 :                 slot->tts_values[attnum] = (Datum) 0;
    1674               0 :                 slot->tts_isnull[attnum] = true;
    1675                 :         }
    1676           15002 :         slot->tts_nvalid = tdesc_natts;
    1677                 : }
    1678                 : 
    1679                 : /*
    1680                 :  * slot_getsomeattrs
    1681                 :  *              This function forces the entries of the slot's Datum/isnull
    1682                 :  *              arrays to be valid at least up through the attnum'th entry.
    1683                 :  */
    1684                 : void
    1685                 : slot_getsomeattrs(TupleTableSlot *slot, int attnum)
    1686           83242 : {
    1687                 :         HeapTuple       tuple;
    1688                 :         int                     attno;
    1689                 : 
    1690                 :         /* Quick out if we have 'em all already */
    1691           83242 :         if (slot->tts_nvalid >= attnum)
    1692           16012 :                 return;
    1693                 : 
    1694                 :         /* Check for caller error */
    1695           67230 :         if (attnum <= 0 || attnum > slot->tts_tupleDescriptor->natts)
    1696               0 :                 elog(ERROR, "invalid attribute number %d", attnum);
    1697                 : 
    1698                 :         /*
    1699                 :          * otherwise we had better have a physical tuple (tts_nvalid should equal
    1700                 :          * natts in all virtual-tuple cases)
    1701                 :          */
    1702           67230 :         tuple = slot->tts_tuple;
    1703           67230 :         if (tuple == NULL)                      /* internal error */
    1704               0 :                 elog(ERROR, "cannot extract attribute from empty tuple slot");
    1705                 : 
    1706                 :         /*
    1707                 :          * load up any slots available from physical tuple
    1708                 :          */
    1709           67230 :         attno = HeapTupleHeaderGetNatts(tuple->t_data);
    1710           67230 :         attno = Min(attno, attnum);
    1711                 : 
    1712           67230 :         slot_deform_tuple(slot, attno);
    1713                 : 
    1714                 :         /*
    1715                 :          * If tuple doesn't have all the atts indicated by tupleDesc, read the
    1716                 :          * rest as null
    1717                 :          */
    1718           67326 :         for (; attno < attnum; attno++)
    1719                 :         {
    1720              96 :                 slot->tts_values[attno] = (Datum) 0;
    1721              96 :                 slot->tts_isnull[attno] = true;
    1722                 :         }
    1723           67230 :         slot->tts_nvalid = attnum;
    1724                 : }
    1725                 : 
    1726                 : /*
    1727                 :  * slot_attisnull
    1728                 :  *              Detect whether an attribute of the slot is null, without
    1729                 :  *              actually fetching it.
    1730                 :  */
    1731                 : bool
    1732                 : slot_attisnull(TupleTableSlot *slot, int attnum)
    1733           36831 : {
    1734           36831 :         HeapTuple       tuple = slot->tts_tuple;
    1735           36831 :         TupleDesc       tupleDesc = slot->tts_tupleDescriptor;
    1736                 : 
    1737                 :         /*
    1738                 :          * system attributes are handled by heap_attisnull
    1739                 :          */
    1740           36831 :         if (attnum <= 0)
    1741                 :         {
    1742               0 :                 if (tuple == NULL)              /* internal error */
    1743               0 :                         elog(ERROR, "cannot extract system attribute from virtual tuple");
    1744               0 :                 if (slot->tts_mintuple) /* internal error */
    1745               0 :                         elog(ERROR, "cannot extract system attribute from minimal tuple");
    1746               0 :                 return heap_attisnull(tuple, attnum);
    1747                 :         }
    1748                 : 
    1749                 :         /*
    1750                 :          * fast path if desired attribute already cached
    1751                 :          */
    1752           36831 :         if (attnum <= slot->tts_nvalid)
    1753              57 :                 return slot->tts_isnull[attnum - 1];
    1754                 : 
    1755                 :         /*
    1756                 :          * return NULL if attnum is out of range according to the tupdesc
    1757                 :          */
    1758           36774 :         if (attnum > tupleDesc->natts)
    1759               0 :                 return true;
    1760                 : 
    1761                 :         /*
    1762                 :          * otherwise we had better have a physical tuple (tts_nvalid should equal
    1763                 :          * natts in all virtual-tuple cases)
    1764                 :          */
    1765           36774 :         if (tuple == NULL)                      /* internal error */
    1766               0 :                 elog(ERROR, "cannot extract attribute from empty tuple slot");
    1767                 : 
    1768                 :         /* and let the tuple tell it */
    1769           36774 :         return heap_attisnull(tuple, attnum);
    1770                 : }
    1771                 : 
    1772                 : /*
    1773                 :  * heap_freetuple
    1774                 :  */
    1775                 : void
    1776                 : heap_freetuple(HeapTuple htup)
    1777          178402 : {
    1778          178402 :         pfree(htup);
    1779          178402 : }
    1780                 : 
    1781                 : 
    1782                 : /*
    1783                 :  * heap_form_minimal_tuple
    1784                 :  *              construct a MinimalTuple from the given values[] and isnull[] arrays,
    1785                 :  *              which are of the length indicated by tupleDescriptor->natts
    1786                 :  *
    1787                 :  * This is exactly like heap_form_tuple() except that the result is a
    1788                 :  * "minimal" tuple lacking a HeapTupleData header as well as room for system
    1789                 :  * columns.
    1790                 :  *
    1791                 :  * The result is allocated in the current memory context.
    1792                 :  */
    1793                 : MinimalTuple
    1794                 : heap_form_minimal_tuple(TupleDesc tupleDescriptor,
    1795                 :                                                 Datum *values,
    1796                 :                                                 bool *isnull)
    1797          174878 : {
    1798                 :         MinimalTuple tuple;                     /* return tuple */
    1799                 :         Size            len,
    1800                 :                                 data_len;
    1801                 :         int                     hoff;
    1802          174878 :         bool            hasnull = false;
    1803          174878 :         Form_pg_attribute *att = tupleDescriptor->attrs;
    1804          174878 :         int                     numberOfAttributes = tupleDescriptor->natts;
    1805                 :         int                     i;
    1806                 : 
    1807          174878 :         if (numberOfAttributes > MaxTupleAttributeNumber)
    1808               0 :                 ereport(ERROR,
    1809                 :                                 (errcode(ERRCODE_TOO_MANY_COLUMNS),
    1810                 :                                  errmsg("number of columns (%d) exceeds limit (%d)",
    1811                 :                                                 numberOfAttributes, MaxTupleAttributeNumber)));
    1812                 : 
    1813                 :         /*
    1814                 :          * Check for nulls and embedded tuples; expand any toasted attributes in
    1815                 :          * embedded tuples.  This preserves the invariant that toasting can only
    1816                 :          * go one level deep.
    1817                 :          *
    1818                 :          * We can skip calling toast_flatten_tuple_attribute() if the attribute
    1819                 :          * couldn't possibly be of composite type.  All composite datums are
    1820                 :          * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
    1821                 :          * if an attribute is already toasted, it must have been sent to disk
    1822                 :          * already and so cannot contain toasted attributes.
    1823                 :          */
    1824          652805 :         for (i = 0; i < numberOfAttributes; i++)
    1825                 :         {
    1826          477927 :                 if (isnull[i])
    1827            1118 :                         hasnull = true;
    1828          476809 :                 else if (att[i]->attlen == -1 &&
    1829                 :                                  att[i]->attalign == 'd' &&
    1830                 :                                  att[i]->attndims == 0 &&
    1831                 :                                  !VARATT_IS_EXTENDED(values[i]))
    1832                 :                 {
    1833               5 :                         values[i] = toast_flatten_tuple_attribute(values[i],
    1834                 :                                                                                                           att[i]->atttypid,
    1835                 :                                                                                                           att[i]->atttypmod);
    1836                 :                 }
    1837                 :         }
    1838                 : 
    1839                 :         /*
    1840                 :          * Determine total space needed
    1841                 :          */
    1842          174878 :         len = offsetof(MinimalTupleData, t_bits);
    1843                 : 
    1844          174878 :         if (hasnull)
    1845             647 :                 len += BITMAPLEN(numberOfAttributes);
    1846                 : 
    1847          174878 :         if (tupleDescriptor->tdhasoid)
    1848               0 :                 len += sizeof(Oid);
    1849                 : 
    1850          174878 :         hoff = len = MAXALIGN(len); /* align user data safely */
    1851                 : 
    1852          174878 :         data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
    1853                 : 
    1854          174878 :         len += data_len;
    1855                 : 
    1856                 :         /*
    1857                 :          * Allocate and zero the space needed.
    1858                 :          */
    1859          174878 :         tuple = (MinimalTuple) palloc0(len);
    1860                 : 
    1861                 :         /*
    1862                 :          * And fill in the information.
    1863                 :          */
    1864          174878 :         tuple->t_len = len;
    1865          174878 :         HeapTupleHeaderSetNatts(tuple, numberOfAttributes);
    1866          174878 :         tuple->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
    1867                 : 
    1868          174878 :         if (tupleDescriptor->tdhasoid)               /* else leave infomask = 0 */
    1869               0 :                 tuple->t_infomask = HEAP_HASOID;
    1870                 : 
    1871          174878 :         heap_fill_tuple(tupleDescriptor,
    1872                 :                                         values,
    1873                 :                                         isnull,
    1874                 :                                         (char *) tuple + hoff,
    1875                 :                                         data_len,
    1876                 :                                         &tuple->t_infomask,
    1877                 :                                         (hasnull ? tuple->t_bits : NULL));
    1878                 : 
    1879          174878 :         return tuple;
    1880                 : }
    1881                 : 
    1882                 : /*
    1883                 :  * heap_free_minimal_tuple
    1884                 :  */
    1885                 : void
    1886                 : heap_free_minimal_tuple(MinimalTuple mtup)
    1887          104092 : {
    1888          104092 :         pfree(mtup);
    1889          104092 : }
    1890                 : 
    1891                 : /*
    1892                 :  * heap_copy_minimal_tuple
    1893                 :  *              copy a MinimalTuple
    1894                 :  *
    1895                 :  * The result is allocated in the current memory context.
    1896                 :  */
    1897                 : MinimalTuple
    1898                 : heap_copy_minimal_tuple(MinimalTuple mtup)
    1899            1292 : {
    1900                 :         MinimalTuple result;
    1901                 : 
    1902            1292 :         result = (MinimalTuple) palloc(mtup->t_len);
    1903            1292 :         memcpy(result, mtup, mtup->t_len);
    1904            1292 :         return result;
    1905                 : }
    1906                 : 
    1907                 : /*
    1908                 :  * heap_tuple_from_minimal_tuple
    1909                 :  *              create a HeapTuple by copying from a MinimalTuple;
    1910                 :  *              system columns are filled with zeroes
    1911                 :  *
    1912                 :  * The result is allocated in the current memory context.
    1913                 :  * The HeapTuple struct, tuple header, and tuple data are all allocated
    1914                 :  * as a single palloc() block.
    1915                 :  */
    1916                 : HeapTuple
    1917                 : heap_tuple_from_minimal_tuple(MinimalTuple mtup)
    1918           21794 : {
    1919                 :         HeapTuple       result;
    1920           21794 :         uint32          len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
    1921                 : 
    1922           21794 :         result = (HeapTuple) palloc(HEAPTUPLESIZE + len);
    1923           21794 :         result->t_len = len;
    1924           21794 :         ItemPointerSetInvalid(&(result->t_self));
    1925           21794 :         result->t_tableOid = InvalidOid;
    1926           21794 :         result->t_data = (HeapTupleHeader) ((char *) result + HEAPTUPLESIZE);
    1927           21794 :         memcpy((char *) result->t_data + MINIMAL_TUPLE_OFFSET, mtup, mtup->t_len);
    1928           21794 :         memset(result->t_data, 0, offsetof(HeapTupleHeaderData, t_infomask2));
    1929           21794 :         return result;
    1930                 : }
    1931                 : 
    1932                 : /*
    1933                 :  * minimal_tuple_from_heap_tuple
    1934                 :  *              create a MinimalTuple by copying from a HeapTuple
    1935                 :  *
    1936                 :  * The result is allocated in the current memory context.
    1937                 :  */
    1938                 : MinimalTuple
    1939                 : minimal_tuple_from_heap_tuple(HeapTuple htup)
    1940           26605 : {
    1941                 :         MinimalTuple result;
    1942                 :         uint32          len;
    1943                 : 
    1944                 :         Assert(htup->t_len > MINIMAL_TUPLE_OFFSET);
    1945           26605 :         len = htup->t_len - MINIMAL_TUPLE_OFFSET;
    1946           26605 :         result = (MinimalTuple) palloc(len);
    1947           26605 :         memcpy(result, (char *) htup->t_data + MINIMAL_TUPLE_OFFSET, len);
    1948           26605 :         result->t_len = len;
    1949           26605 :         return result;
    1950                 : }
    1951                 : 
    1952                 : 
    1953                 : /* ----------------
    1954                 :  *              heap_addheader
    1955                 :  *
    1956                 :  * This routine forms a HeapTuple by copying the given structure (tuple
    1957                 :  * data) and adding a generic header.  Note that the tuple data is
    1958                 :  * presumed to contain no null fields and no varlena fields.
    1959                 :  *
    1960                 :  * This routine is really only useful for certain system tables that are
    1961                 :  * known to be fixed-width and null-free.  Currently it is only used for
    1962                 :  * pg_attribute tuples.
    1963                 :  * ----------------
    1964                 :  */
    1965                 : HeapTuple
    1966                 : heap_addheader(int natts,               /* max domain index */
    1967                 :                            bool withoid,        /* reserve space for oid */
    1968                 :                            Size structlen,      /* its length */
    1969                 :                            void *structure) /* pointer to the struct */
    1970           10517 : {
    1971                 :         HeapTuple       tuple;
    1972                 :         HeapTupleHeader td;
    1973                 :         Size            len;
    1974                 :         int                     hoff;
    1975                 : 
    1976                 :         AssertArg(natts > 0);
    1977                 : 
    1978                 :         /* header needs no null bitmap */
    1979           10517 :         hoff = offsetof(HeapTupleHeaderData, t_bits);
    1980           10517 :         if (withoid)
    1981               0 :                 hoff += sizeof(Oid);
    1982           10517 :         hoff = MAXALIGN(hoff);
    1983           10517 :         len = hoff + structlen;
    1984                 : 
    1985           10517 :         tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
    1986           10517 :         tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
    1987                 : 
    1988           10517 :         tuple->t_len = len;
    1989           10517 :         ItemPointerSetInvalid(&(tuple->t_self));
    1990           10517 :         tuple->t_tableOid = InvalidOid;
    1991                 : 
    1992                 :         /* we don't bother to fill the Datum fields */
    1993                 : 
    1994           10517 :         HeapTupleHeaderSetNatts(td, natts);
    1995           10517 :         td->t_hoff = hoff;
    1996                 : 
    1997           10517 :         if (withoid)                            /* else leave infomask = 0 */
    1998               0 :                 td->t_infomask = HEAP_HASOID;
    1999                 : 
    2000           10517 :         memcpy((char *) td + hoff, structure, structlen);
    2001                 : 
    2002           10517 :         return tuple;
    2003                 : }

Generated by: LTP GCOV extension version 1.5