LCOV - code coverage report
Current view: top level - src/include - varatt.h (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 96.9 % 97 94
Test Date: 2026-09-24 22:15:42 Functions: 100.0 % 35 35
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 91.7 % 48 44

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * varatt.h
       4                 :             :  *    variable-length datatypes (TOAST support)
       5                 :             :  *
       6                 :             :  *
       7                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       8                 :             :  * Portions Copyright (c) 1995, Regents of the University of California
       9                 :             :  *
      10                 :             :  * src/include/varatt.h
      11                 :             :  *
      12                 :             :  *-------------------------------------------------------------------------
      13                 :             :  */
      14                 :             : 
      15                 :             : #ifndef VARATT_H
      16                 :             : #define VARATT_H
      17                 :             : 
      18                 :             : /*
      19                 :             :  * varatt_external_oid is a traditional "TOAST pointer", that is, the
      20                 :             :  * information needed to fetch a Datum stored out-of-line in a TOAST table.
      21                 :             :  * The data is compressed if and only if the external size stored in
      22                 :             :  * va_extinfo is less than va_rawsize - VARHDRSZ.
      23                 :             :  *
      24                 :             :  * This struct must not contain any padding, because we sometimes compare
      25                 :             :  * these pointers using memcmp.
      26                 :             :  *
      27                 :             :  * Note that this information is stored unaligned within actual tuples, so
      28                 :             :  * you need to memcpy from the tuple into a local struct variable before
      29                 :             :  * you can look at these fields!  (The reason we use memcmp is to avoid
      30                 :             :  * having to do that just to detect equality of two TOAST pointers...)
      31                 :             :  */
      32                 :             : typedef struct varatt_external_oid
      33                 :             : {
      34                 :             :     int32       va_rawsize;     /* Original data size (includes header) */
      35                 :             :     uint32      va_extinfo;     /* External saved size (without header) and
      36                 :             :                                  * compression method */
      37                 :             :     Oid         va_valueid;     /* Unique ID of value within TOAST table */
      38                 :             :     Oid         va_toastrelid;  /* RelID of TOAST table containing it */
      39                 :             : } varatt_external_oid;
      40                 :             : 
      41                 :             : StaticAssertDecl((sizeof(int32) + sizeof(uint32) + 2 * sizeof(Oid)) ==
      42                 :             :                  sizeof(varatt_external_oid),
      43                 :             :                  "varatt_external_oid should have no padding");
      44                 :             : 
      45                 :             : /*
      46                 :             :  * varatt_external_oid8 is a "TOAST pointer" for TOAST tables that use
      47                 :             :  * Oid8 (64-bit) as their chunk_id type.  Same layout as varatt_external_oid
      48                 :             :  * except for the value ID, which is 8 bytes wide.  The value ID is split
      49                 :             :  * into two uint32 to force alignment.
      50                 :             :  *
      51                 :             :  * This struct must not contain any padding, because we sometimes compare
      52                 :             :  * these pointers using memcmp.
      53                 :             :  */
      54                 :             : typedef struct varatt_external_oid8
      55                 :             : {
      56                 :             :     int32       va_rawsize;     /* Original data size (includes header) */
      57                 :             :     uint32      va_extinfo;     /* External saved size (without header) and
      58                 :             :                                  * compression method */
      59                 :             :     uint32      va_valueid_lo;  /* Low 32 bits of value ID */
      60                 :             :     uint32      va_valueid_hi;  /* High 32 bits of value ID */
      61                 :             :     Oid         va_toastrelid;  /* RelID of TOAST table containing it */
      62                 :             : } varatt_external_oid8;
      63                 :             : 
      64                 :             : StaticAssertDecl((sizeof(int32) + 3 * sizeof(uint32) + sizeof(Oid)) ==
      65                 :             :                  sizeof(varatt_external_oid8),
      66                 :             :                  "varatt_external_oid8 should have no padding");
      67                 :             : 
      68                 :             : /* Get/set the 64-bit value ID from the lo/hi halves */
      69                 :             : static inline Oid8
      70                 :         232 : VARATT_EXTERNAL_OID8_GET_VALUEID(varatt_external_oid8 toast_pointer)
      71                 :             : {
      72                 :         464 :     return ((Oid8) toast_pointer.va_valueid_lo) |
      73                 :         232 :         (((Oid8) toast_pointer.va_valueid_hi) << 32);
      74                 :             : }
      75                 :             : 
      76                 :             : static inline void
      77                 :          78 : VARATT_EXTERNAL_OID8_SET_VALUEID(varatt_external_oid8 *toast_pointer, Oid8 id)
      78                 :             : {
      79                 :          78 :     toast_pointer->va_valueid_lo = (uint32) id;
      80                 :          78 :     toast_pointer->va_valueid_hi = (uint32) (id >> 32);
      81                 :          78 : }
      82                 :             : 
      83                 :             : /*
      84                 :             :  * These macros define the "saved size" portion of va_extinfo.  Its remaining
      85                 :             :  * two high-order bits identify the compression method.
      86                 :             :  */
      87                 :             : #define VARLENA_EXTSIZE_BITS    30
      88                 :             : #define VARLENA_EXTSIZE_MASK    ((1U << VARLENA_EXTSIZE_BITS) - 1)
      89                 :             : 
      90                 :             : /*
      91                 :             :  * varatt_indirect is a "TOAST pointer" representing an out-of-line
      92                 :             :  * Datum that's stored in memory, not in an external toast relation.
      93                 :             :  * The creator of such a Datum is entirely responsible that the referenced
      94                 :             :  * storage survives for as long as referencing pointer Datums can exist.
      95                 :             :  *
      96                 :             :  * Note that just as for varatt_external_oid, this struct is stored
      97                 :             :  * unaligned within any containing tuple.
      98                 :             :  */
      99                 :             : typedef struct varatt_indirect
     100                 :             : {
     101                 :             :     varlena    *pointer;        /* Pointer to in-memory varlena */
     102                 :             : } varatt_indirect;
     103                 :             : 
     104                 :             : /*
     105                 :             :  * varatt_expanded is a "TOAST pointer" representing an out-of-line
     106                 :             :  * Datum that is stored in memory, in some type-specific, not necessarily
     107                 :             :  * physically contiguous format that is convenient for computation not
     108                 :             :  * storage.  APIs for this, in particular the definition of struct
     109                 :             :  * ExpandedObjectHeader, are in src/include/utils/expandeddatum.h.
     110                 :             :  *
     111                 :             :  * Note that just as for varatt_external_oid, this struct is stored
     112                 :             :  * unaligned within any containing tuple.
     113                 :             :  */
     114                 :             : typedef struct ExpandedObjectHeader ExpandedObjectHeader;
     115                 :             : 
     116                 :             : typedef struct varatt_expanded
     117                 :             : {
     118                 :             :     ExpandedObjectHeader *eohptr;
     119                 :             : } varatt_expanded;
     120                 :             : 
     121                 :             : /*
     122                 :             :  * Type tag for the various sorts of "TOAST pointer" datums.  The peculiar
     123                 :             :  * value for VARTAG_ONDISK_OID comes from a requirement for on-disk
     124                 :             :  * compatibility with a previous notion that the tag field was the pointer
     125                 :             :  * datum's length.
     126                 :             :  */
     127                 :             : typedef enum vartag_external
     128                 :             : {
     129                 :             :     VARTAG_INDIRECT = 1,
     130                 :             :     VARTAG_EXPANDED_RO = 2,
     131                 :             :     VARTAG_EXPANDED_RW = 3,
     132                 :             :     VARTAG_ONDISK_OID8 = 4,
     133                 :             :     VARTAG_ONDISK_OID = 18
     134                 :             : } vartag_external;
     135                 :             : 
     136                 :             : /* Is a TOAST pointer either type of expanded-object pointer? */
     137                 :             : /* this test relies on the specific tag values above */
     138                 :             : static inline bool
     139                 :      236255 : VARTAG_IS_EXPANDED(vartag_external tag)
     140                 :             : {
     141                 :      236255 :     return ((tag & ~1) == VARTAG_EXPANDED_RO);
     142                 :             : }
     143                 :             : 
     144                 :             : /* Size of the data part of a "TOAST pointer" datum */
     145                 :             : static inline Size
     146                 :      118799 : VARTAG_SIZE(vartag_external tag)
     147                 :             : {
     148         [ +  + ]:      118799 :     if (tag == VARTAG_INDIRECT)
     149                 :         975 :         return sizeof(varatt_indirect);
     150         [ -  + ]:      117824 :     else if (VARTAG_IS_EXPANDED(tag))
     151                 :           0 :         return sizeof(varatt_expanded);
     152         [ +  + ]:      117824 :     else if (tag == VARTAG_ONDISK_OID)
     153                 :      117179 :         return sizeof(varatt_external_oid);
     154         [ +  - ]:         645 :     else if (tag == VARTAG_ONDISK_OID8)
     155                 :         645 :         return sizeof(varatt_external_oid8);
     156                 :             :     else
     157                 :             :     {
     158                 :             :         Assert(false);
     159                 :           0 :         return 0;
     160                 :             :     }
     161                 :             : }
     162                 :             : 
     163                 :             : /*
     164                 :             :  * These structs describe the header of a varlena object that may have been
     165                 :             :  * TOASTed.  Generally, don't reference these structs directly, but use the
     166                 :             :  * functions and macros below.
     167                 :             :  *
     168                 :             :  * We use separate structs for the aligned and unaligned cases because the
     169                 :             :  * compiler might otherwise think it could generate code that assumes
     170                 :             :  * alignment while touching fields of a 1-byte-header varlena.
     171                 :             :  */
     172                 :             : typedef union
     173                 :             : {
     174                 :             :     struct                      /* Normal varlena (4-byte length) */
     175                 :             :     {
     176                 :             :         uint32      va_header;
     177                 :             :         char        va_data[FLEXIBLE_ARRAY_MEMBER];
     178                 :             :     }           va_4byte;
     179                 :             :     struct                      /* Compressed-in-line format */
     180                 :             :     {
     181                 :             :         uint32      va_header;
     182                 :             :         uint32      va_tcinfo;  /* Original data size (excludes header) and
     183                 :             :                                  * compression method; see va_extinfo */
     184                 :             :         char        va_data[FLEXIBLE_ARRAY_MEMBER]; /* Compressed data */
     185                 :             :     }           va_compressed;
     186                 :             : } varattrib_4b;
     187                 :             : 
     188                 :             : typedef struct
     189                 :             : {
     190                 :             :     uint8       va_header;
     191                 :             :     char        va_data[FLEXIBLE_ARRAY_MEMBER]; /* Data begins here */
     192                 :             : } varattrib_1b;
     193                 :             : 
     194                 :             : /* TOAST pointers are a subset of varattrib_1b with an identifying tag byte */
     195                 :             : typedef struct
     196                 :             : {
     197                 :             :     uint8       va_header;      /* Always 0x80 or 0x01 */
     198                 :             :     uint8       va_tag;         /* Type of datum */
     199                 :             :     char        va_data[FLEXIBLE_ARRAY_MEMBER]; /* Type-specific data */
     200                 :             : } varattrib_1b_e;
     201                 :             : 
     202                 :             : /*
     203                 :             :  * Bit layouts for varlena headers on big-endian machines:
     204                 :             :  *
     205                 :             :  * 00xxxxxx 4-byte length word, aligned, uncompressed data (up to 1G)
     206                 :             :  * 01xxxxxx 4-byte length word, aligned, *compressed* data (up to 1G)
     207                 :             :  * 10000000 1-byte length word, unaligned, TOAST pointer
     208                 :             :  * 1xxxxxxx 1-byte length word, unaligned, uncompressed data (up to 126b)
     209                 :             :  *
     210                 :             :  * Bit layouts for varlena headers on little-endian machines:
     211                 :             :  *
     212                 :             :  * xxxxxx00 4-byte length word, aligned, uncompressed data (up to 1G)
     213                 :             :  * xxxxxx10 4-byte length word, aligned, *compressed* data (up to 1G)
     214                 :             :  * 00000001 1-byte length word, unaligned, TOAST pointer
     215                 :             :  * xxxxxxx1 1-byte length word, unaligned, uncompressed data (up to 126b)
     216                 :             :  *
     217                 :             :  * The "xxx" bits are the length field (which includes itself in all cases).
     218                 :             :  * In the big-endian case we mask to extract the length, in the little-endian
     219                 :             :  * case we shift.  Note that in both cases the flag bits are in the physically
     220                 :             :  * first byte.  Also, it is not possible for a 1-byte length word to be zero;
     221                 :             :  * this lets us disambiguate alignment padding bytes from the start of an
     222                 :             :  * unaligned datum.  (We now *require* pad bytes to be filled with zero!)
     223                 :             :  *
     224                 :             :  * In TOAST pointers the va_tag field (see varattrib_1b_e) is used to discern
     225                 :             :  * the specific type and length of the pointer datum.
     226                 :             :  */
     227                 :             : 
     228                 :             : /*
     229                 :             :  * Endian-dependent macros.  These are considered internal --- use the
     230                 :             :  * external functions below instead of using these directly.  All of these
     231                 :             :  * expect an argument that is a pointer, not a Datum.  Some of them have
     232                 :             :  * multiple-evaluation hazards, too.
     233                 :             :  *
     234                 :             :  * Note: IS_1B is true for external toast records but VARSIZE_1B will return 0
     235                 :             :  * for such records. Hence you should usually check for IS_EXTERNAL before
     236                 :             :  * checking for IS_1B.
     237                 :             :  */
     238                 :             : 
     239                 :             : #ifdef WORDS_BIGENDIAN
     240                 :             : 
     241                 :             : #define VARATT_IS_4B(PTR) \
     242                 :             :     ((((const varattrib_1b *) (PTR))->va_header & 0x80) == 0x00)
     243                 :             : #define VARATT_IS_4B_U(PTR) \
     244                 :             :     ((((const varattrib_1b *) (PTR))->va_header & 0xC0) == 0x00)
     245                 :             : #define VARATT_IS_4B_C(PTR) \
     246                 :             :     ((((const varattrib_1b *) (PTR))->va_header & 0xC0) == 0x40)
     247                 :             : #define VARATT_IS_1B(PTR) \
     248                 :             :     ((((const varattrib_1b *) (PTR))->va_header & 0x80) == 0x80)
     249                 :             : #define VARATT_IS_1B_E(PTR) \
     250                 :             :     ((((const varattrib_1b *) (PTR))->va_header) == 0x80)
     251                 :             : #define VARATT_NOT_PAD_BYTE(PTR) \
     252                 :             :     (*((const uint8 *) (PTR)) != 0)
     253                 :             : 
     254                 :             : /* VARSIZE_4B() should only be used on known-aligned data */
     255                 :             : #define VARSIZE_4B(PTR) \
     256                 :             :     (((const varattrib_4b *) (PTR))->va_4byte.va_header & 0x3FFFFFFF)
     257                 :             : #define VARSIZE_1B(PTR) \
     258                 :             :     (((const varattrib_1b *) (PTR))->va_header & 0x7F)
     259                 :             : #define VARTAG_1B_E(PTR) \
     260                 :             :     ((vartag_external) ((const varattrib_1b_e *) (PTR))->va_tag)
     261                 :             : 
     262                 :             : #define SET_VARSIZE_4B(PTR,len) \
     263                 :             :     (((varattrib_4b *) (PTR))->va_4byte.va_header = (len) & 0x3FFFFFFF)
     264                 :             : #define SET_VARSIZE_4B_C(PTR,len) \
     265                 :             :     (((varattrib_4b *) (PTR))->va_4byte.va_header = ((len) & 0x3FFFFFFF) | 0x40000000)
     266                 :             : #define SET_VARSIZE_1B(PTR,len) \
     267                 :             :     (((varattrib_1b *) (PTR))->va_header = (len) | 0x80)
     268                 :             : #define SET_VARTAG_1B_E(PTR,tag) \
     269                 :             :     (((varattrib_1b_e *) (PTR))->va_header = 0x80, \
     270                 :             :      ((varattrib_1b_e *) (PTR))->va_tag = (tag))
     271                 :             : 
     272                 :             : #else                           /* !WORDS_BIGENDIAN */
     273                 :             : 
     274                 :             : #define VARATT_IS_4B(PTR) \
     275                 :             :     ((((const varattrib_1b *) (PTR))->va_header & 0x01) == 0x00)
     276                 :             : #define VARATT_IS_4B_U(PTR) \
     277                 :             :     ((((const varattrib_1b *) (PTR))->va_header & 0x03) == 0x00)
     278                 :             : #define VARATT_IS_4B_C(PTR) \
     279                 :             :     ((((const varattrib_1b *) (PTR))->va_header & 0x03) == 0x02)
     280                 :             : #define VARATT_IS_1B(PTR) \
     281                 :             :     ((((const varattrib_1b *) (PTR))->va_header & 0x01) == 0x01)
     282                 :             : #define VARATT_IS_1B_E(PTR) \
     283                 :             :     ((((const varattrib_1b *) (PTR))->va_header) == 0x01)
     284                 :             : #define VARATT_NOT_PAD_BYTE(PTR) \
     285                 :             :     (*((const uint8 *) (PTR)) != 0)
     286                 :             : 
     287                 :             : /* VARSIZE_4B() should only be used on known-aligned data */
     288                 :             : #define VARSIZE_4B(PTR) \
     289                 :             :     ((((const varattrib_4b *) (PTR))->va_4byte.va_header >> 2) & 0x3FFFFFFF)
     290                 :             : #define VARSIZE_1B(PTR) \
     291                 :             :     ((((const varattrib_1b *) (PTR))->va_header >> 1) & 0x7F)
     292                 :             : #define VARTAG_1B_E(PTR) \
     293                 :             :     ((vartag_external) ((const varattrib_1b_e *) (PTR))->va_tag)
     294                 :             : 
     295                 :             : #define SET_VARSIZE_4B(PTR,len) \
     296                 :             :     (((varattrib_4b *) (PTR))->va_4byte.va_header = (((uint32) (len)) << 2))
     297                 :             : #define SET_VARSIZE_4B_C(PTR,len) \
     298                 :             :     (((varattrib_4b *) (PTR))->va_4byte.va_header = (((uint32) (len)) << 2) | 0x02)
     299                 :             : #define SET_VARSIZE_1B(PTR,len) \
     300                 :             :     (((varattrib_1b *) (PTR))->va_header = (((uint8) (len)) << 1) | 0x01)
     301                 :             : #define SET_VARTAG_1B_E(PTR,tag) \
     302                 :             :     (((varattrib_1b_e *) (PTR))->va_header = 0x01, \
     303                 :             :      ((varattrib_1b_e *) (PTR))->va_tag = (tag))
     304                 :             : 
     305                 :             : #endif                          /* WORDS_BIGENDIAN */
     306                 :             : 
     307                 :             : #define VARDATA_4B(PTR)     (((varattrib_4b *) (PTR))->va_4byte.va_data)
     308                 :             : #define VARDATA_4B_C(PTR)   (((varattrib_4b *) (PTR))->va_compressed.va_data)
     309                 :             : #define VARDATA_1B(PTR)     (((varattrib_1b *) (PTR))->va_data)
     310                 :             : #define VARDATA_1B_E(PTR)   (((varattrib_1b_e *) (PTR))->va_data)
     311                 :             : 
     312                 :             : /*
     313                 :             :  * Externally visible TOAST functions and macros begin here.  All of these
     314                 :             :  * were originally macros, accounting for the upper-case naming.
     315                 :             :  *
     316                 :             :  * Most of these functions accept a pointer to a value of a toastable data
     317                 :             :  * type.  The caller's variable might be declared "text *" or the like,
     318                 :             :  * so we use "void *" here.  Callers that are working with a Datum variable
     319                 :             :  * must apply DatumGetPointer before calling these functions.
     320                 :             :  */
     321                 :             : 
     322                 :             : #define VARHDRSZ_EXTERNAL       offsetof(varattrib_1b_e, va_data)
     323                 :             : #define VARHDRSZ_COMPRESSED     offsetof(varattrib_4b, va_compressed.va_data)
     324                 :             : #define VARHDRSZ_SHORT          offsetof(varattrib_1b, va_data)
     325                 :             : #define VARATT_SHORT_MAX        0x7F
     326                 :             : 
     327                 :             : /*
     328                 :             :  * In consumers oblivious to data alignment, call PG_DETOAST_DATUM_PACKED(),
     329                 :             :  * VARDATA_ANY(), VARSIZE_ANY() and VARSIZE_ANY_EXHDR().  Elsewhere, call
     330                 :             :  * PG_DETOAST_DATUM(), VARDATA() and VARSIZE().  Directly fetching an int16,
     331                 :             :  * int32 or wider field in the struct representing the datum layout requires
     332                 :             :  * aligned data.  memcpy() is alignment-oblivious, as are most operations on
     333                 :             :  * datatypes, such as text, whose layout struct contains only char fields.
     334                 :             :  *
     335                 :             :  * Code assembling a new datum should call VARDATA() and SET_VARSIZE().
     336                 :             :  * (Datums begin life untoasted.)
     337                 :             :  *
     338                 :             :  * Other functions here should usually be used only by tuple assembly/disassembly
     339                 :             :  * code and code that specifically wants to work with still-toasted Datums.
     340                 :             :  */
     341                 :             : 
     342                 :             : /* Size of a known-not-toasted varlena datum, including header */
     343                 :             : static inline Size
     344                 :   142701173 : VARSIZE(const void *PTR)
     345                 :             : {
     346                 :   142701173 :     return VARSIZE_4B(PTR);
     347                 :             : }
     348                 :             : 
     349                 :             : /* Start of data area of a known-not-toasted varlena datum */
     350                 :             : static inline char *
     351                 :    74751691 : VARDATA(const void *PTR)
     352                 :             : {
     353                 :    74751691 :     return VARDATA_4B(PTR);
     354                 :             : }
     355                 :             : 
     356                 :             : /* Size of a known-short-header varlena datum, including header */
     357                 :             : static inline Size
     358                 :    48902981 : VARSIZE_SHORT(const void *PTR)
     359                 :             : {
     360                 :    48902981 :     return VARSIZE_1B(PTR);
     361                 :             : }
     362                 :             : 
     363                 :             : /* Start of data area of a known-short-header varlena datum */
     364                 :             : static inline char *
     365                 :    33865401 : VARDATA_SHORT(const void *PTR)
     366                 :             : {
     367                 :    33865401 :     return VARDATA_1B(PTR);
     368                 :             : }
     369                 :             : 
     370                 :             : /* Type tag of a "TOAST pointer" datum */
     371                 :             : static inline vartag_external
     372                 :      426411 : VARTAG_EXTERNAL(const void *PTR)
     373                 :             : {
     374                 :      426411 :     return VARTAG_1B_E(PTR);
     375                 :             : }
     376                 :             : 
     377                 :             : /* Size of a "TOAST pointer" datum, including header */
     378                 :             : static inline Size
     379                 :      118799 : VARSIZE_EXTERNAL(const void *PTR)
     380                 :             : {
     381                 :      118799 :     return VARHDRSZ_EXTERNAL + VARTAG_SIZE(VARTAG_EXTERNAL(PTR));
     382                 :             : }
     383                 :             : 
     384                 :             : /* Start of data area of a "TOAST pointer" datum */
     385                 :             : static inline char *
     386                 :      214878 : VARDATA_EXTERNAL(const void *PTR)
     387                 :             : {
     388                 :      214878 :     return VARDATA_1B_E(PTR);
     389                 :             : }
     390                 :             : 
     391                 :             : /* Is varlena datum in inline-compressed format? */
     392                 :             : static inline bool
     393                 :   197731694 : VARATT_IS_COMPRESSED(const void *PTR)
     394                 :             : {
     395                 :   197731694 :     return VARATT_IS_4B_C(PTR);
     396                 :             : }
     397                 :             : 
     398                 :             : /* Is varlena datum a "TOAST pointer" datum? */
     399                 :             : static inline bool
     400                 :   359625644 : VARATT_IS_EXTERNAL(const void *PTR)
     401                 :             : {
     402                 :   359625644 :     return VARATT_IS_1B_E(PTR);
     403                 :             : }
     404                 :             : 
     405                 :             : /* Is varlena datum a pointer to on-disk toasted data? */
     406                 :             : static inline bool
     407                 :    52176033 : VARATT_IS_EXTERNAL_ONDISK(const void *PTR)
     408                 :             : {
     409                 :             :     vartag_external tag;
     410                 :             : 
     411         [ +  + ]:    52176033 :     if (!VARATT_IS_EXTERNAL(PTR))
     412                 :    52115252 :         return false;
     413                 :       60781 :     tag = VARTAG_EXTERNAL(PTR);
     414   [ +  +  +  + ]:       60781 :     return (tag == VARTAG_ONDISK_OID || tag == VARTAG_ONDISK_OID8);
     415                 :             : }
     416                 :             : 
     417                 :             : /* Is varlena datum an indirect pointer? */
     418                 :             : static inline bool
     419                 :    51899351 : VARATT_IS_EXTERNAL_INDIRECT(const void *PTR)
     420                 :             : {
     421   [ +  +  +  + ]:    51899351 :     return VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_INDIRECT;
     422                 :             : }
     423                 :             : 
     424                 :             : /* Is varlena datum a read-only pointer to an expanded object? */
     425                 :             : static inline bool
     426                 :       20298 : VARATT_IS_EXTERNAL_EXPANDED_RO(const void *PTR)
     427                 :             : {
     428   [ +  +  +  - ]:       20298 :     return VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_EXPANDED_RO;
     429                 :             : }
     430                 :             : 
     431                 :             : /* Is varlena datum a read-write pointer to an expanded object? */
     432                 :             : static inline bool
     433                 :     6213859 : VARATT_IS_EXTERNAL_EXPANDED_RW(const void *PTR)
     434                 :             : {
     435   [ +  +  +  + ]:     6213859 :     return VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_EXPANDED_RW;
     436                 :             : }
     437                 :             : 
     438                 :             : /* Is varlena datum either type of pointer to an expanded object? */
     439                 :             : static inline bool
     440                 :    78452441 : VARATT_IS_EXTERNAL_EXPANDED(const void *PTR)
     441                 :             : {
     442   [ +  +  +  + ]:    78452441 :     return VARATT_IS_EXTERNAL(PTR) && VARTAG_IS_EXPANDED(VARTAG_EXTERNAL(PTR));
     443                 :             : }
     444                 :             : 
     445                 :             : /* Is varlena datum a "TOAST pointer", but not for an expanded object? */
     446                 :             : static inline bool
     447                 :       29379 : VARATT_IS_EXTERNAL_NON_EXPANDED(const void *PTR)
     448                 :             : {
     449   [ +  +  +  + ]:       29379 :     return VARATT_IS_EXTERNAL(PTR) && !VARTAG_IS_EXPANDED(VARTAG_EXTERNAL(PTR));
     450                 :             : }
     451                 :             : 
     452                 :             : /* Is varlena datum a short-header datum? */
     453                 :             : static inline bool
     454                 :   110481157 : VARATT_IS_SHORT(const void *PTR)
     455                 :             : {
     456                 :   110481157 :     return VARATT_IS_1B(PTR);
     457                 :             : }
     458                 :             : 
     459                 :             : /* Is varlena datum not in traditional (4-byte-header, uncompressed) format? */
     460                 :             : static inline bool
     461                 :    95694688 : VARATT_IS_EXTENDED(const void *PTR)
     462                 :             : {
     463                 :    95694688 :     return !VARATT_IS_4B_U(PTR);
     464                 :             : }
     465                 :             : 
     466                 :             : /* Is varlena datum short enough to convert to short-header format? */
     467                 :             : static inline bool
     468                 :    40628331 : VARATT_CAN_MAKE_SHORT(const void *PTR)
     469                 :             : {
     470         [ +  + ]:    77066525 :     return VARATT_IS_4B_U(PTR) &&
     471         [ +  + ]:    36438194 :         (VARSIZE(PTR) - VARHDRSZ + VARHDRSZ_SHORT) <= VARATT_SHORT_MAX;
     472                 :             : }
     473                 :             : 
     474                 :             : /* Size that datum will have in short-header format, including header */
     475                 :             : static inline Size
     476                 :    35175154 : VARATT_CONVERTED_SHORT_SIZE(const void *PTR)
     477                 :             : {
     478                 :    35175154 :     return VARSIZE(PTR) - VARHDRSZ + VARHDRSZ_SHORT;
     479                 :             : }
     480                 :             : 
     481                 :             : /* Set the size (including header) of a 4-byte-header varlena datum */
     482                 :             : static inline void
     483                 :    89187416 : SET_VARSIZE(void *PTR, Size len)
     484                 :             : {
     485                 :    89187416 :     SET_VARSIZE_4B(PTR, len);
     486                 :    89187416 : }
     487                 :             : 
     488                 :             : /* Set the size (including header) of a short-header varlena datum */
     489                 :             : static inline void
     490                 :    17470623 : SET_VARSIZE_SHORT(void *PTR, Size len)
     491                 :             : {
     492                 :    17470623 :     SET_VARSIZE_1B(PTR, len);
     493                 :    17470623 : }
     494                 :             : 
     495                 :             : /* Set the size (including header) of an inline-compressed varlena datum */
     496                 :             : static inline void
     497                 :       47617 : SET_VARSIZE_COMPRESSED(void *PTR, Size len)
     498                 :             : {
     499                 :       47617 :     SET_VARSIZE_4B_C(PTR, len);
     500                 :       47617 : }
     501                 :             : 
     502                 :             : /* Set the type tag of a "TOAST pointer" datum */
     503                 :             : static inline void
     504                 :       85751 : SET_VARTAG_EXTERNAL(void *PTR, vartag_external tag)
     505                 :             : {
     506                 :       85751 :     SET_VARTAG_1B_E(PTR, tag);
     507                 :       85751 : }
     508                 :             : 
     509                 :             : /* Size of a varlena datum of any format, including header */
     510                 :             : static inline Size
     511                 :   110693019 : VARSIZE_ANY(const void *PTR)
     512                 :             : {
     513         [ +  + ]:   110693019 :     if (VARATT_IS_1B_E(PTR))
     514                 :      106708 :         return VARSIZE_EXTERNAL(PTR);
     515         [ +  + ]:   110586311 :     else if (VARATT_IS_1B(PTR))
     516                 :    76016933 :         return VARSIZE_1B(PTR);
     517                 :             :     else
     518                 :    34569378 :         return VARSIZE_4B(PTR);
     519                 :             : }
     520                 :             : 
     521                 :             : /* Size of a varlena datum of any format, excluding header */
     522                 :             : static inline Size
     523                 :   138875988 : VARSIZE_ANY_EXHDR(const void *PTR)
     524                 :             : {
     525         [ -  + ]:   138875988 :     if (VARATT_IS_1B_E(PTR))
     526                 :           0 :         return VARSIZE_EXTERNAL(PTR) - VARHDRSZ_EXTERNAL;
     527         [ +  + ]:   138875988 :     else if (VARATT_IS_1B(PTR))
     528                 :    14668411 :         return VARSIZE_1B(PTR) - VARHDRSZ_SHORT;
     529                 :             :     else
     530                 :   124207577 :         return VARSIZE_4B(PTR) - VARHDRSZ;
     531                 :             : }
     532                 :             : 
     533                 :             : /* Start of data area of a plain or short-header varlena datum */
     534                 :             : /* caution: this will not work on an external or compressed-in-line Datum */
     535                 :             : /* caution: this will return a possibly unaligned pointer */
     536                 :             : static inline char *
     537                 :   144827873 : VARDATA_ANY(const void *PTR)
     538                 :             : {
     539         [ +  + ]:   144827873 :     return VARATT_IS_1B(PTR) ? VARDATA_1B(PTR) : VARDATA_4B(PTR);
     540                 :             : }
     541                 :             : 
     542                 :             : /* Decompressed size of a compressed-in-line varlena datum */
     543                 :             : static inline Size
     544                 :      226561 : VARDATA_COMPRESSED_GET_EXTSIZE(const void *PTR)
     545                 :             : {
     546                 :      226561 :     return ((const varattrib_4b *) PTR)->va_compressed.va_tcinfo & VARLENA_EXTSIZE_MASK;
     547                 :             : }
     548                 :             : 
     549                 :             : /* Compression method of a compressed-in-line varlena datum */
     550                 :             : static inline uint32
     551                 :        8151 : VARDATA_COMPRESSED_GET_COMPRESS_METHOD(const void *PTR)
     552                 :             : {
     553                 :        8151 :     return ((const varattrib_4b *) PTR)->va_compressed.va_tcinfo >> VARLENA_EXTSIZE_BITS;
     554                 :             : }
     555                 :             : 
     556                 :             : /*
     557                 :             :  * Same for external Datums, saved into a va_extinfo.
     558                 :             :  */
     559                 :             : static inline Size
     560                 :       74271 : VARATT_EXTINFO_GET_EXTSIZE(uint32 extinfo)
     561                 :             : {
     562                 :       74271 :     return extinfo & VARLENA_EXTSIZE_MASK;
     563                 :             : }
     564                 :             : 
     565                 :             : static inline uint32
     566                 :        2841 : VARATT_EXTINFO_GET_COMPRESS_METHOD(uint32 extinfo)
     567                 :             : {
     568                 :        2841 :     return extinfo >> VARLENA_EXTSIZE_BITS;
     569                 :             : }
     570                 :             : 
     571                 :             : /*
     572                 :             :  * Testing whether an externally-stored value is compressed requires comparing
     573                 :             :  * the saved size stored in va_extinfo (the actual length of the external data)
     574                 :             :  * to rawsize (the original uncompressed datum's size).  The latter includes
     575                 :             :  * VARHDRSZ overhead, the former doesn't.  We never use compression unless it
     576                 :             :  * actually saves space, so we expect either equality or less-than.
     577                 :             :  */
     578                 :             : static inline bool
     579                 :       44415 : VARATT_EXTINFO_IS_COMPRESSED(uint32 extinfo, int32 rawsize)
     580                 :             : {
     581                 :       44415 :     return VARATT_EXTINFO_GET_EXTSIZE(extinfo) < (Size) (rawsize - VARHDRSZ);
     582                 :             : }
     583                 :             : 
     584                 :             : #endif
        

Generated by: LCOV version 2.0-1