LCOV - code coverage report
Current view: top level - src/include/access - tupmacs.h (source / functions) Coverage Total Hit
Test: Code coverage Lines: 84.6 % 26 22
Test Date: 2026-01-26 10:56:24 Functions: 100.0 % 3 3
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 50.0 % 20 10

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * tupmacs.h
       4                 :             :  *        Tuple macros used by both index tuples and heap tuples.
       5                 :             :  *
       6                 :             :  *
       7                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       8                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       9                 :             :  *
      10                 :             :  * src/include/access/tupmacs.h
      11                 :             :  *
      12                 :             :  *-------------------------------------------------------------------------
      13                 :             :  */
      14                 :             : #ifndef TUPMACS_H
      15                 :             : #define TUPMACS_H
      16                 :             : 
      17                 :             : #include "catalog/pg_type_d.h"        /* for TYPALIGN macros */
      18                 :             : 
      19                 :             : 
      20                 :             : /*
      21                 :             :  * Check a tuple's null bitmap to determine whether the attribute is null.
      22                 :             :  * Note that a 0 in the null bitmap indicates a null, while 1 indicates
      23                 :             :  * non-null.
      24                 :             :  */
      25                 :             : static inline bool
      26                 :    41078583 : att_isnull(int ATT, const bits8 *BITS)
      27                 :             : {
      28                 :    41078583 :         return !(BITS[ATT >> 3] & (1 << (ATT & 0x07)));
      29                 :             : }
      30                 :             : 
      31                 :             : #ifndef FRONTEND
      32                 :             : /*
      33                 :             :  * Given an attbyval and an attlen from either a Form_pg_attribute or
      34                 :             :  * CompactAttribute and a pointer into a tuple's data area, return the
      35                 :             :  * correct value or pointer.
      36                 :             :  *
      37                 :             :  * We return a Datum value in all cases.  If attbyval is false,  we return the
      38                 :             :  * same pointer into the tuple data area that we're passed.  Otherwise, we
      39                 :             :  * return the correct number of bytes fetched from the data area and extended
      40                 :             :  * to Datum form.
      41                 :             :  *
      42                 :             :  * Note that T must already be properly aligned for this to work correctly.
      43                 :             :  */
      44                 :             : #define fetchatt(A,T) fetch_att(T, (A)->attbyval, (A)->attlen)
      45                 :             : 
      46                 :             : /*
      47                 :             :  * Same, but work from byval/len parameters rather than Form_pg_attribute.
      48                 :             :  */
      49                 :             : static inline Datum
      50                 :   142950327 : fetch_att(const void *T, bool attbyval, int attlen)
      51                 :             : {
      52         [ +  + ]:   142950327 :         if (attbyval)
      53                 :             :         {
      54   [ +  +  +  +  :   111831464 :                 switch (attlen)
                      - ]
      55                 :             :                 {
      56                 :             :                         case sizeof(char):
      57                 :     7090347 :                                 return CharGetDatum(*((const char *) T));
      58                 :             :                         case sizeof(int16):
      59                 :     4513499 :                                 return Int16GetDatum(*((const int16 *) T));
      60                 :             :                         case sizeof(int32):
      61                 :    96496994 :                                 return Int32GetDatum(*((const int32 *) T));
      62                 :             :                         case sizeof(int64):
      63                 :     3730624 :                                 return Int64GetDatum(*((const int64 *) T));
      64                 :             :                         default:
      65   [ #  #  #  # ]:           0 :                                 elog(ERROR, "unsupported byval length: %d", attlen);
      66                 :           0 :                                 return 0;
      67                 :             :                 }
      68                 :             :         }
      69                 :             :         else
      70                 :    31118863 :                 return PointerGetDatum(T);
      71                 :   142950327 : }
      72                 :             : #endif                                                  /* FRONTEND */
      73                 :             : 
      74                 :             : /*
      75                 :             :  * att_align_datum aligns the given offset as needed for a datum of alignment
      76                 :             :  * requirement attalign and typlen attlen.  attdatum is the Datum variable
      77                 :             :  * we intend to pack into a tuple (it's only accessed if we are dealing with
      78                 :             :  * a varlena type).  Note that this assumes the Datum will be stored as-is;
      79                 :             :  * callers that are intending to convert non-short varlena datums to short
      80                 :             :  * format have to account for that themselves.
      81                 :             :  */
      82                 :             : #define att_align_datum(cur_offset, attalign, attlen, attdatum) \
      83                 :             : ( \
      84                 :             :         ((attlen) == -1 && VARATT_IS_SHORT(DatumGetPointer(attdatum))) ? \
      85                 :             :         (uintptr_t) (cur_offset) : \
      86                 :             :         att_align_nominal(cur_offset, attalign) \
      87                 :             : )
      88                 :             : 
      89                 :             : /*
      90                 :             :  * Similar to att_align_datum, but accepts a number of bytes, typically from
      91                 :             :  * CompactAttribute.attalignby to align the Datum by.
      92                 :             :  */
      93                 :             : #define att_datum_alignby(cur_offset, attalignby, attlen, attdatum) \
      94                 :             :         ( \
      95                 :             :         ((attlen) == -1 && VARATT_IS_SHORT(DatumGetPointer(attdatum))) ? \
      96                 :             :         (uintptr_t) (cur_offset) : \
      97                 :             :         TYPEALIGN(attalignby, cur_offset))
      98                 :             : 
      99                 :             : /*
     100                 :             :  * att_align_pointer performs the same calculation as att_align_datum,
     101                 :             :  * but is used when walking a tuple.  attptr is the current actual data
     102                 :             :  * pointer; when accessing a varlena field we have to "peek" to see if we
     103                 :             :  * are looking at a pad byte or the first byte of a 1-byte-header datum.
     104                 :             :  * (A zero byte must be either a pad byte, or the first byte of a correctly
     105                 :             :  * aligned 4-byte length word; in either case we can align safely.  A non-zero
     106                 :             :  * byte must be either a 1-byte length word, or the first byte of a correctly
     107                 :             :  * aligned 4-byte length word; in either case we need not align.)
     108                 :             :  *
     109                 :             :  * Note: some callers pass a "char *" pointer for cur_offset.  This is
     110                 :             :  * a bit of a hack but should work all right as long as uintptr_t is the
     111                 :             :  * correct width.
     112                 :             :  */
     113                 :             : #define att_align_pointer(cur_offset, attalign, attlen, attptr) \
     114                 :             : ( \
     115                 :             :         ((attlen) == -1 && VARATT_NOT_PAD_BYTE(attptr)) ? \
     116                 :             :         (uintptr_t) (cur_offset) : \
     117                 :             :         att_align_nominal(cur_offset, attalign) \
     118                 :             : )
     119                 :             : 
     120                 :             : /*
     121                 :             :  * Similar to att_align_pointer, but accepts a number of bytes, typically from
     122                 :             :  * CompactAttribute.attalignby to align the pointer by.
     123                 :             :  */
     124                 :             : #define att_pointer_alignby(cur_offset, attalignby, attlen, attptr) \
     125                 :             :         ( \
     126                 :             :         ((attlen) == -1 && VARATT_NOT_PAD_BYTE(attptr)) ? \
     127                 :             :         (uintptr_t) (cur_offset) : \
     128                 :             :         TYPEALIGN(attalignby, cur_offset))
     129                 :             : 
     130                 :             : /*
     131                 :             :  * att_align_nominal aligns the given offset as needed for a datum of alignment
     132                 :             :  * requirement attalign, ignoring any consideration of packed varlena datums.
     133                 :             :  * There are three main use cases for using this macro directly:
     134                 :             :  *      * we know that the att in question is not varlena (attlen != -1);
     135                 :             :  *        in this case it is cheaper than the above macros and just as good.
     136                 :             :  *      * we need to estimate alignment padding cost abstractly, ie without
     137                 :             :  *        reference to a real tuple.  We must assume the worst case that
     138                 :             :  *        all varlenas are aligned.
     139                 :             :  *      * within arrays and multiranges, we unconditionally align varlenas (XXX this
     140                 :             :  *        should be revisited, probably).
     141                 :             :  *
     142                 :             :  * The attalign cases are tested in what is hopefully something like their
     143                 :             :  * frequency of occurrence.
     144                 :             :  */
     145                 :             : #define att_align_nominal(cur_offset, attalign) \
     146                 :             : ( \
     147                 :             :         ((attalign) == TYPALIGN_INT) ? INTALIGN(cur_offset) : \
     148                 :             :          (((attalign) == TYPALIGN_CHAR) ? (uintptr_t) (cur_offset) : \
     149                 :             :           (((attalign) == TYPALIGN_DOUBLE) ? DOUBLEALIGN(cur_offset) : \
     150                 :             :            ( \
     151                 :             :                         AssertMacro((attalign) == TYPALIGN_SHORT), \
     152                 :             :                         SHORTALIGN(cur_offset) \
     153                 :             :            ))) \
     154                 :             : )
     155                 :             : 
     156                 :             : /*
     157                 :             :  * Similar to att_align_nominal, but accepts a number of bytes, typically from
     158                 :             :  * CompactAttribute.attalignby to align the offset by.
     159                 :             :  */
     160                 :             : #define att_nominal_alignby(cur_offset, attalignby) \
     161                 :             :         TYPEALIGN(attalignby, cur_offset)
     162                 :             : 
     163                 :             : /*
     164                 :             :  * att_addlength_datum increments the given offset by the space needed for
     165                 :             :  * the given Datum variable.  attdatum is only accessed if we are dealing
     166                 :             :  * with a variable-length attribute.
     167                 :             :  */
     168                 :             : #define att_addlength_datum(cur_offset, attlen, attdatum) \
     169                 :             :         att_addlength_pointer(cur_offset, attlen, DatumGetPointer(attdatum))
     170                 :             : 
     171                 :             : /*
     172                 :             :  * att_addlength_pointer performs the same calculation as att_addlength_datum,
     173                 :             :  * but is used when walking a tuple --- attptr is the pointer to the field
     174                 :             :  * within the tuple.
     175                 :             :  *
     176                 :             :  * Note: some callers pass a "char *" pointer for cur_offset.  This is
     177                 :             :  * actually perfectly OK, but probably should be cleaned up along with
     178                 :             :  * the same practice for att_align_pointer.
     179                 :             :  */
     180                 :             : #define att_addlength_pointer(cur_offset, attlen, attptr) \
     181                 :             : ( \
     182                 :             :         ((attlen) > 0) ? \
     183                 :             :         ( \
     184                 :             :                 (cur_offset) + (attlen) \
     185                 :             :         ) \
     186                 :             :         : (((attlen) == -1) ? \
     187                 :             :         ( \
     188                 :             :                 (cur_offset) + VARSIZE_ANY(attptr) \
     189                 :             :         ) \
     190                 :             :         : \
     191                 :             :         ( \
     192                 :             :                 AssertMacro((attlen) == -2), \
     193                 :             :                 (cur_offset) + (strlen((char *) (attptr)) + 1) \
     194                 :             :         )) \
     195                 :             : )
     196                 :             : 
     197                 :             : #ifndef FRONTEND
     198                 :             : /*
     199                 :             :  * store_att_byval is a partial inverse of fetch_att: store a given Datum
     200                 :             :  * value into a tuple data area at the specified address.  However, it only
     201                 :             :  * handles the byval case, because in typical usage the caller needs to
     202                 :             :  * distinguish by-val and by-ref cases anyway, and so a do-it-all function
     203                 :             :  * wouldn't be convenient.
     204                 :             :  */
     205                 :             : static inline void
     206                 :    18590400 : store_att_byval(void *T, Datum newdatum, int attlen)
     207                 :             : {
     208   [ +  +  +  +  :    18590400 :         switch (attlen)
                      - ]
     209                 :             :         {
     210                 :             :                 case sizeof(char):
     211                 :     1389917 :                         *(char *) T = DatumGetChar(newdatum);
     212                 :     1389917 :                         break;
     213                 :             :                 case sizeof(int16):
     214                 :      772972 :                         *(int16 *) T = DatumGetInt16(newdatum);
     215                 :      772972 :                         break;
     216                 :             :                 case sizeof(int32):
     217                 :    13783986 :                         *(int32 *) T = DatumGetInt32(newdatum);
     218                 :    13783986 :                         break;
     219                 :             :                 case sizeof(int64):
     220                 :     2643525 :                         *(int64 *) T = DatumGetInt64(newdatum);
     221                 :     2643525 :                         break;
     222                 :             :                 default:
     223   [ #  #  #  # ]:           0 :                         elog(ERROR, "unsupported byval length: %d", attlen);
     224                 :           0 :         }
     225                 :    18590400 : }
     226                 :             : #endif                                                  /* FRONTEND */
     227                 :             : 
     228                 :             : #endif                                                  /* TUPMACS_H */
        

Generated by: LCOV version 2.3.2-1