LCOV - code coverage report
Current view: top level - src/include - varatt.h (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 96.5 % 86 83
Test Date: 2026-07-03 19:57:34 Functions: 100.0 % 33 33
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 90.9 % 44 40

             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 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
      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;
      40                 :             : 
      41                 :             : /*
      42                 :             :  * These macros define the "saved size" portion of va_extinfo.  Its remaining
      43                 :             :  * two high-order bits identify the compression method.
      44                 :             :  */
      45                 :             : #define VARLENA_EXTSIZE_BITS    30
      46                 :             : #define VARLENA_EXTSIZE_MASK    ((1U << VARLENA_EXTSIZE_BITS) - 1)
      47                 :             : 
      48                 :             : /*
      49                 :             :  * varatt_indirect is a "TOAST pointer" representing an out-of-line
      50                 :             :  * Datum that's stored in memory, not in an external toast relation.
      51                 :             :  * The creator of such a Datum is entirely responsible that the referenced
      52                 :             :  * storage survives for as long as referencing pointer Datums can exist.
      53                 :             :  *
      54                 :             :  * Note that just as for varatt_external, this struct is stored
      55                 :             :  * unaligned within any containing tuple.
      56                 :             :  */
      57                 :             : typedef struct varatt_indirect
      58                 :             : {
      59                 :             :     varlena    *pointer;        /* Pointer to in-memory varlena */
      60                 :             : } varatt_indirect;
      61                 :             : 
      62                 :             : /*
      63                 :             :  * varatt_expanded is a "TOAST pointer" representing an out-of-line
      64                 :             :  * Datum that is stored in memory, in some type-specific, not necessarily
      65                 :             :  * physically contiguous format that is convenient for computation not
      66                 :             :  * storage.  APIs for this, in particular the definition of struct
      67                 :             :  * ExpandedObjectHeader, are in src/include/utils/expandeddatum.h.
      68                 :             :  *
      69                 :             :  * Note that just as for varatt_external, this struct is stored
      70                 :             :  * unaligned within any containing tuple.
      71                 :             :  */
      72                 :             : typedef struct ExpandedObjectHeader ExpandedObjectHeader;
      73                 :             : 
      74                 :             : typedef struct varatt_expanded
      75                 :             : {
      76                 :             :     ExpandedObjectHeader *eohptr;
      77                 :             : } varatt_expanded;
      78                 :             : 
      79                 :             : /*
      80                 :             :  * Type tag for the various sorts of "TOAST pointer" datums.  The peculiar
      81                 :             :  * value for VARTAG_ONDISK comes from a requirement for on-disk compatibility
      82                 :             :  * with a previous notion that the tag field was the pointer datum's length.
      83                 :             :  */
      84                 :             : typedef enum vartag_external
      85                 :             : {
      86                 :             :     VARTAG_INDIRECT = 1,
      87                 :             :     VARTAG_EXPANDED_RO = 2,
      88                 :             :     VARTAG_EXPANDED_RW = 3,
      89                 :             :     VARTAG_ONDISK = 18
      90                 :             : } vartag_external;
      91                 :             : 
      92                 :             : /* Is a TOAST pointer either type of expanded-object pointer? */
      93                 :             : /* this test relies on the specific tag values above */
      94                 :             : static inline bool
      95                 :      288569 : VARTAG_IS_EXPANDED(vartag_external tag)
      96                 :             : {
      97                 :      288569 :     return ((tag & ~1) == VARTAG_EXPANDED_RO);
      98                 :             : }
      99                 :             : 
     100                 :             : /* Size of the data part of a "TOAST pointer" datum */
     101                 :             : static inline Size
     102                 :      164991 : VARTAG_SIZE(vartag_external tag)
     103                 :             : {
     104         [ +  + ]:      164991 :     if (tag == VARTAG_INDIRECT)
     105                 :         957 :         return sizeof(varatt_indirect);
     106         [ -  + ]:      164034 :     else if (VARTAG_IS_EXPANDED(tag))
     107                 :           0 :         return sizeof(varatt_expanded);
     108         [ +  - ]:      164034 :     else if (tag == VARTAG_ONDISK)
     109                 :      164034 :         return sizeof(varatt_external);
     110                 :             :     else
     111                 :             :     {
     112                 :             :         Assert(false);
     113                 :           0 :         return 0;
     114                 :             :     }
     115                 :             : }
     116                 :             : 
     117                 :             : /*
     118                 :             :  * These structs describe the header of a varlena object that may have been
     119                 :             :  * TOASTed.  Generally, don't reference these structs directly, but use the
     120                 :             :  * functions and macros below.
     121                 :             :  *
     122                 :             :  * We use separate structs for the aligned and unaligned cases because the
     123                 :             :  * compiler might otherwise think it could generate code that assumes
     124                 :             :  * alignment while touching fields of a 1-byte-header varlena.
     125                 :             :  */
     126                 :             : typedef union
     127                 :             : {
     128                 :             :     struct                      /* Normal varlena (4-byte length) */
     129                 :             :     {
     130                 :             :         uint32      va_header;
     131                 :             :         char        va_data[FLEXIBLE_ARRAY_MEMBER];
     132                 :             :     }           va_4byte;
     133                 :             :     struct                      /* Compressed-in-line format */
     134                 :             :     {
     135                 :             :         uint32      va_header;
     136                 :             :         uint32      va_tcinfo;  /* Original data size (excludes header) and
     137                 :             :                                  * compression method; see va_extinfo */
     138                 :             :         char        va_data[FLEXIBLE_ARRAY_MEMBER]; /* Compressed data */
     139                 :             :     }           va_compressed;
     140                 :             : } varattrib_4b;
     141                 :             : 
     142                 :             : typedef struct
     143                 :             : {
     144                 :             :     uint8       va_header;
     145                 :             :     char        va_data[FLEXIBLE_ARRAY_MEMBER]; /* Data begins here */
     146                 :             : } varattrib_1b;
     147                 :             : 
     148                 :             : /* TOAST pointers are a subset of varattrib_1b with an identifying tag byte */
     149                 :             : typedef struct
     150                 :             : {
     151                 :             :     uint8       va_header;      /* Always 0x80 or 0x01 */
     152                 :             :     uint8       va_tag;         /* Type of datum */
     153                 :             :     char        va_data[FLEXIBLE_ARRAY_MEMBER]; /* Type-specific data */
     154                 :             : } varattrib_1b_e;
     155                 :             : 
     156                 :             : /*
     157                 :             :  * Bit layouts for varlena headers on big-endian machines:
     158                 :             :  *
     159                 :             :  * 00xxxxxx 4-byte length word, aligned, uncompressed data (up to 1G)
     160                 :             :  * 01xxxxxx 4-byte length word, aligned, *compressed* data (up to 1G)
     161                 :             :  * 10000000 1-byte length word, unaligned, TOAST pointer
     162                 :             :  * 1xxxxxxx 1-byte length word, unaligned, uncompressed data (up to 126b)
     163                 :             :  *
     164                 :             :  * Bit layouts for varlena headers on little-endian machines:
     165                 :             :  *
     166                 :             :  * xxxxxx00 4-byte length word, aligned, uncompressed data (up to 1G)
     167                 :             :  * xxxxxx10 4-byte length word, aligned, *compressed* data (up to 1G)
     168                 :             :  * 00000001 1-byte length word, unaligned, TOAST pointer
     169                 :             :  * xxxxxxx1 1-byte length word, unaligned, uncompressed data (up to 126b)
     170                 :             :  *
     171                 :             :  * The "xxx" bits are the length field (which includes itself in all cases).
     172                 :             :  * In the big-endian case we mask to extract the length, in the little-endian
     173                 :             :  * case we shift.  Note that in both cases the flag bits are in the physically
     174                 :             :  * first byte.  Also, it is not possible for a 1-byte length word to be zero;
     175                 :             :  * this lets us disambiguate alignment padding bytes from the start of an
     176                 :             :  * unaligned datum.  (We now *require* pad bytes to be filled with zero!)
     177                 :             :  *
     178                 :             :  * In TOAST pointers the va_tag field (see varattrib_1b_e) is used to discern
     179                 :             :  * the specific type and length of the pointer datum.
     180                 :             :  */
     181                 :             : 
     182                 :             : /*
     183                 :             :  * Endian-dependent macros.  These are considered internal --- use the
     184                 :             :  * external functions below instead of using these directly.  All of these
     185                 :             :  * expect an argument that is a pointer, not a Datum.  Some of them have
     186                 :             :  * multiple-evaluation hazards, too.
     187                 :             :  *
     188                 :             :  * Note: IS_1B is true for external toast records but VARSIZE_1B will return 0
     189                 :             :  * for such records. Hence you should usually check for IS_EXTERNAL before
     190                 :             :  * checking for IS_1B.
     191                 :             :  */
     192                 :             : 
     193                 :             : #ifdef WORDS_BIGENDIAN
     194                 :             : 
     195                 :             : #define VARATT_IS_4B(PTR) \
     196                 :             :     ((((const varattrib_1b *) (PTR))->va_header & 0x80) == 0x00)
     197                 :             : #define VARATT_IS_4B_U(PTR) \
     198                 :             :     ((((const varattrib_1b *) (PTR))->va_header & 0xC0) == 0x00)
     199                 :             : #define VARATT_IS_4B_C(PTR) \
     200                 :             :     ((((const varattrib_1b *) (PTR))->va_header & 0xC0) == 0x40)
     201                 :             : #define VARATT_IS_1B(PTR) \
     202                 :             :     ((((const varattrib_1b *) (PTR))->va_header & 0x80) == 0x80)
     203                 :             : #define VARATT_IS_1B_E(PTR) \
     204                 :             :     ((((const varattrib_1b *) (PTR))->va_header) == 0x80)
     205                 :             : #define VARATT_NOT_PAD_BYTE(PTR) \
     206                 :             :     (*((const uint8 *) (PTR)) != 0)
     207                 :             : 
     208                 :             : /* VARSIZE_4B() should only be used on known-aligned data */
     209                 :             : #define VARSIZE_4B(PTR) \
     210                 :             :     (((const varattrib_4b *) (PTR))->va_4byte.va_header & 0x3FFFFFFF)
     211                 :             : #define VARSIZE_1B(PTR) \
     212                 :             :     (((const varattrib_1b *) (PTR))->va_header & 0x7F)
     213                 :             : #define VARTAG_1B_E(PTR) \
     214                 :             :     ((vartag_external) ((const varattrib_1b_e *) (PTR))->va_tag)
     215                 :             : 
     216                 :             : #define SET_VARSIZE_4B(PTR,len) \
     217                 :             :     (((varattrib_4b *) (PTR))->va_4byte.va_header = (len) & 0x3FFFFFFF)
     218                 :             : #define SET_VARSIZE_4B_C(PTR,len) \
     219                 :             :     (((varattrib_4b *) (PTR))->va_4byte.va_header = ((len) & 0x3FFFFFFF) | 0x40000000)
     220                 :             : #define SET_VARSIZE_1B(PTR,len) \
     221                 :             :     (((varattrib_1b *) (PTR))->va_header = (len) | 0x80)
     222                 :             : #define SET_VARTAG_1B_E(PTR,tag) \
     223                 :             :     (((varattrib_1b_e *) (PTR))->va_header = 0x80, \
     224                 :             :      ((varattrib_1b_e *) (PTR))->va_tag = (tag))
     225                 :             : 
     226                 :             : #else                           /* !WORDS_BIGENDIAN */
     227                 :             : 
     228                 :             : #define VARATT_IS_4B(PTR) \
     229                 :             :     ((((const varattrib_1b *) (PTR))->va_header & 0x01) == 0x00)
     230                 :             : #define VARATT_IS_4B_U(PTR) \
     231                 :             :     ((((const varattrib_1b *) (PTR))->va_header & 0x03) == 0x00)
     232                 :             : #define VARATT_IS_4B_C(PTR) \
     233                 :             :     ((((const varattrib_1b *) (PTR))->va_header & 0x03) == 0x02)
     234                 :             : #define VARATT_IS_1B(PTR) \
     235                 :             :     ((((const varattrib_1b *) (PTR))->va_header & 0x01) == 0x01)
     236                 :             : #define VARATT_IS_1B_E(PTR) \
     237                 :             :     ((((const varattrib_1b *) (PTR))->va_header) == 0x01)
     238                 :             : #define VARATT_NOT_PAD_BYTE(PTR) \
     239                 :             :     (*((const uint8 *) (PTR)) != 0)
     240                 :             : 
     241                 :             : /* VARSIZE_4B() should only be used on known-aligned data */
     242                 :             : #define VARSIZE_4B(PTR) \
     243                 :             :     ((((const varattrib_4b *) (PTR))->va_4byte.va_header >> 2) & 0x3FFFFFFF)
     244                 :             : #define VARSIZE_1B(PTR) \
     245                 :             :     ((((const varattrib_1b *) (PTR))->va_header >> 1) & 0x7F)
     246                 :             : #define VARTAG_1B_E(PTR) \
     247                 :             :     ((vartag_external) ((const varattrib_1b_e *) (PTR))->va_tag)
     248                 :             : 
     249                 :             : #define SET_VARSIZE_4B(PTR,len) \
     250                 :             :     (((varattrib_4b *) (PTR))->va_4byte.va_header = (((uint32) (len)) << 2))
     251                 :             : #define SET_VARSIZE_4B_C(PTR,len) \
     252                 :             :     (((varattrib_4b *) (PTR))->va_4byte.va_header = (((uint32) (len)) << 2) | 0x02)
     253                 :             : #define SET_VARSIZE_1B(PTR,len) \
     254                 :             :     (((varattrib_1b *) (PTR))->va_header = (((uint8) (len)) << 1) | 0x01)
     255                 :             : #define SET_VARTAG_1B_E(PTR,tag) \
     256                 :             :     (((varattrib_1b_e *) (PTR))->va_header = 0x01, \
     257                 :             :      ((varattrib_1b_e *) (PTR))->va_tag = (tag))
     258                 :             : 
     259                 :             : #endif                          /* WORDS_BIGENDIAN */
     260                 :             : 
     261                 :             : #define VARDATA_4B(PTR)     (((varattrib_4b *) (PTR))->va_4byte.va_data)
     262                 :             : #define VARDATA_4B_C(PTR)   (((varattrib_4b *) (PTR))->va_compressed.va_data)
     263                 :             : #define VARDATA_1B(PTR)     (((varattrib_1b *) (PTR))->va_data)
     264                 :             : #define VARDATA_1B_E(PTR)   (((varattrib_1b_e *) (PTR))->va_data)
     265                 :             : 
     266                 :             : /*
     267                 :             :  * Externally visible TOAST functions and macros begin here.  All of these
     268                 :             :  * were originally macros, accounting for the upper-case naming.
     269                 :             :  *
     270                 :             :  * Most of these functions accept a pointer to a value of a toastable data
     271                 :             :  * type.  The caller's variable might be declared "text *" or the like,
     272                 :             :  * so we use "void *" here.  Callers that are working with a Datum variable
     273                 :             :  * must apply DatumGetPointer before calling these functions.
     274                 :             :  */
     275                 :             : 
     276                 :             : #define VARHDRSZ_EXTERNAL       offsetof(varattrib_1b_e, va_data)
     277                 :             : #define VARHDRSZ_COMPRESSED     offsetof(varattrib_4b, va_compressed.va_data)
     278                 :             : #define VARHDRSZ_SHORT          offsetof(varattrib_1b, va_data)
     279                 :             : #define VARATT_SHORT_MAX        0x7F
     280                 :             : 
     281                 :             : /*
     282                 :             :  * In consumers oblivious to data alignment, call PG_DETOAST_DATUM_PACKED(),
     283                 :             :  * VARDATA_ANY(), VARSIZE_ANY() and VARSIZE_ANY_EXHDR().  Elsewhere, call
     284                 :             :  * PG_DETOAST_DATUM(), VARDATA() and VARSIZE().  Directly fetching an int16,
     285                 :             :  * int32 or wider field in the struct representing the datum layout requires
     286                 :             :  * aligned data.  memcpy() is alignment-oblivious, as are most operations on
     287                 :             :  * datatypes, such as text, whose layout struct contains only char fields.
     288                 :             :  *
     289                 :             :  * Code assembling a new datum should call VARDATA() and SET_VARSIZE().
     290                 :             :  * (Datums begin life untoasted.)
     291                 :             :  *
     292                 :             :  * Other functions here should usually be used only by tuple assembly/disassembly
     293                 :             :  * code and code that specifically wants to work with still-toasted Datums.
     294                 :             :  */
     295                 :             : 
     296                 :             : /* Size of a known-not-toasted varlena datum, including header */
     297                 :             : static inline Size
     298                 :   140558016 : VARSIZE(const void *PTR)
     299                 :             : {
     300                 :   140558016 :     return VARSIZE_4B(PTR);
     301                 :             : }
     302                 :             : 
     303                 :             : /* Start of data area of a known-not-toasted varlena datum */
     304                 :             : static inline char *
     305                 :    74744407 : VARDATA(const void *PTR)
     306                 :             : {
     307                 :    74744407 :     return VARDATA_4B(PTR);
     308                 :             : }
     309                 :             : 
     310                 :             : /* Size of a known-short-header varlena datum, including header */
     311                 :             : static inline Size
     312                 :    48664973 : VARSIZE_SHORT(const void *PTR)
     313                 :             : {
     314                 :    48664973 :     return VARSIZE_1B(PTR);
     315                 :             : }
     316                 :             : 
     317                 :             : /* Start of data area of a known-short-header varlena datum */
     318                 :             : static inline char *
     319                 :    33622758 : VARDATA_SHORT(const void *PTR)
     320                 :             : {
     321                 :    33622758 :     return VARDATA_1B(PTR);
     322                 :             : }
     323                 :             : 
     324                 :             : /* Type tag of a "TOAST pointer" datum */
     325                 :             : static inline vartag_external
     326                 :      424435 : VARTAG_EXTERNAL(const void *PTR)
     327                 :             : {
     328                 :      424435 :     return VARTAG_1B_E(PTR);
     329                 :             : }
     330                 :             : 
     331                 :             : /* Size of a "TOAST pointer" datum, including header */
     332                 :             : static inline Size
     333                 :      164991 : VARSIZE_EXTERNAL(const void *PTR)
     334                 :             : {
     335                 :      164991 :     return VARHDRSZ_EXTERNAL + VARTAG_SIZE(VARTAG_EXTERNAL(PTR));
     336                 :             : }
     337                 :             : 
     338                 :             : /* Start of data area of a "TOAST pointer" datum */
     339                 :             : static inline char *
     340                 :      229525 : VARDATA_EXTERNAL(const void *PTR)
     341                 :             : {
     342                 :      229525 :     return VARDATA_1B_E(PTR);
     343                 :             : }
     344                 :             : 
     345                 :             : /* Is varlena datum in inline-compressed format? */
     346                 :             : static inline bool
     347                 :   197866051 : VARATT_IS_COMPRESSED(const void *PTR)
     348                 :             : {
     349                 :   197866051 :     return VARATT_IS_4B_C(PTR);
     350                 :             : }
     351                 :             : 
     352                 :             : /* Is varlena datum a "TOAST pointer" datum? */
     353                 :             : static inline bool
     354                 :   359045881 : VARATT_IS_EXTERNAL(const void *PTR)
     355                 :             : {
     356                 :   359045881 :     return VARATT_IS_1B_E(PTR);
     357                 :             : }
     358                 :             : 
     359                 :             : /* Is varlena datum a pointer to on-disk toasted data? */
     360                 :             : static inline bool
     361                 :    51871262 : VARATT_IS_EXTERNAL_ONDISK(const void *PTR)
     362                 :             : {
     363   [ +  +  +  + ]:    51871262 :     return VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_ONDISK;
     364                 :             : }
     365                 :             : 
     366                 :             : /* Is varlena datum an indirect pointer? */
     367                 :             : static inline bool
     368                 :    51593086 : VARATT_IS_EXTERNAL_INDIRECT(const void *PTR)
     369                 :             : {
     370   [ +  +  +  + ]:    51593086 :     return VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_INDIRECT;
     371                 :             : }
     372                 :             : 
     373                 :             : /* Is varlena datum a read-only pointer to an expanded object? */
     374                 :             : static inline bool
     375                 :       20817 : VARATT_IS_EXTERNAL_EXPANDED_RO(const void *PTR)
     376                 :             : {
     377   [ +  +  +  - ]:       20817 :     return VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_EXPANDED_RO;
     378                 :             : }
     379                 :             : 
     380                 :             : /* Is varlena datum a read-write pointer to an expanded object? */
     381                 :             : static inline bool
     382                 :     6279831 : VARATT_IS_EXTERNAL_EXPANDED_RW(const void *PTR)
     383                 :             : {
     384   [ +  +  +  + ]:     6279831 :     return VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_EXPANDED_RW;
     385                 :             : }
     386                 :             : 
     387                 :             : /* Is varlena datum either type of pointer to an expanded object? */
     388                 :             : static inline bool
     389                 :    78453795 : VARATT_IS_EXTERNAL_EXPANDED(const void *PTR)
     390                 :             : {
     391   [ +  +  +  + ]:    78453795 :     return VARATT_IS_EXTERNAL(PTR) && VARTAG_IS_EXPANDED(VARTAG_EXTERNAL(PTR));
     392                 :             : }
     393                 :             : 
     394                 :             : /* Is varlena datum a "TOAST pointer", but not for an expanded object? */
     395                 :             : static inline bool
     396                 :       29787 : VARATT_IS_EXTERNAL_NON_EXPANDED(const void *PTR)
     397                 :             : {
     398   [ +  +  +  + ]:       29787 :     return VARATT_IS_EXTERNAL(PTR) && !VARTAG_IS_EXPANDED(VARTAG_EXTERNAL(PTR));
     399                 :             : }
     400                 :             : 
     401                 :             : /* Is varlena datum a short-header datum? */
     402                 :             : static inline bool
     403                 :   112392653 : VARATT_IS_SHORT(const void *PTR)
     404                 :             : {
     405                 :   112392653 :     return VARATT_IS_1B(PTR);
     406                 :             : }
     407                 :             : 
     408                 :             : /* Is varlena datum not in traditional (4-byte-header, uncompressed) format? */
     409                 :             : static inline bool
     410                 :    95530053 : VARATT_IS_EXTENDED(const void *PTR)
     411                 :             : {
     412                 :    95530053 :     return !VARATT_IS_4B_U(PTR);
     413                 :             : }
     414                 :             : 
     415                 :             : /* Is varlena datum short enough to convert to short-header format? */
     416                 :             : static inline bool
     417                 :    39657774 : VARATT_CAN_MAKE_SHORT(const void *PTR)
     418                 :             : {
     419         [ +  + ]:    75017002 :     return VARATT_IS_4B_U(PTR) &&
     420         [ +  + ]:    35359228 :         (VARSIZE(PTR) - VARHDRSZ + VARHDRSZ_SHORT) <= VARATT_SHORT_MAX;
     421                 :             : }
     422                 :             : 
     423                 :             : /* Size that datum will have in short-header format, including header */
     424                 :             : static inline Size
     425                 :    34027952 : VARATT_CONVERTED_SHORT_SIZE(const void *PTR)
     426                 :             : {
     427                 :    34027952 :     return VARSIZE(PTR) - VARHDRSZ + VARHDRSZ_SHORT;
     428                 :             : }
     429                 :             : 
     430                 :             : /* Set the size (including header) of a 4-byte-header varlena datum */
     431                 :             : static inline void
     432                 :    88000289 : SET_VARSIZE(void *PTR, Size len)
     433                 :             : {
     434                 :    88000289 :     SET_VARSIZE_4B(PTR, len);
     435                 :    88000289 : }
     436                 :             : 
     437                 :             : /* Set the size (including header) of a short-header varlena datum */
     438                 :             : static inline void
     439                 :    16896300 : SET_VARSIZE_SHORT(void *PTR, Size len)
     440                 :             : {
     441                 :    16896300 :     SET_VARSIZE_1B(PTR, len);
     442                 :    16896300 : }
     443                 :             : 
     444                 :             : /* Set the size (including header) of an inline-compressed varlena datum */
     445                 :             : static inline void
     446                 :       47913 : SET_VARSIZE_COMPRESSED(void *PTR, Size len)
     447                 :             : {
     448                 :       47913 :     SET_VARSIZE_4B_C(PTR, len);
     449                 :       47913 : }
     450                 :             : 
     451                 :             : /* Set the type tag of a "TOAST pointer" datum */
     452                 :             : static inline void
     453                 :       86269 : SET_VARTAG_EXTERNAL(void *PTR, vartag_external tag)
     454                 :             : {
     455                 :       86269 :     SET_VARTAG_1B_E(PTR, tag);
     456                 :       86269 : }
     457                 :             : 
     458                 :             : /* Size of a varlena datum of any format, including header */
     459                 :             : static inline Size
     460                 :   112192419 : VARSIZE_ANY(const void *PTR)
     461                 :             : {
     462         [ +  + ]:   112192419 :     if (VARATT_IS_1B_E(PTR))
     463                 :      150400 :         return VARSIZE_EXTERNAL(PTR);
     464         [ +  + ]:   112042019 :     else if (VARATT_IS_1B(PTR))
     465                 :    77315733 :         return VARSIZE_1B(PTR);
     466                 :             :     else
     467                 :    34726286 :         return VARSIZE_4B(PTR);
     468                 :             : }
     469                 :             : 
     470                 :             : /* Size of a varlena datum of any format, excluding header */
     471                 :             : static inline Size
     472                 :   138517065 : VARSIZE_ANY_EXHDR(const void *PTR)
     473                 :             : {
     474         [ -  + ]:   138517065 :     if (VARATT_IS_1B_E(PTR))
     475                 :           0 :         return VARSIZE_EXTERNAL(PTR) - VARHDRSZ_EXTERNAL;
     476         [ +  + ]:   138517065 :     else if (VARATT_IS_1B(PTR))
     477                 :    14560996 :         return VARSIZE_1B(PTR) - VARHDRSZ_SHORT;
     478                 :             :     else
     479                 :   123956069 :         return VARSIZE_4B(PTR) - VARHDRSZ;
     480                 :             : }
     481                 :             : 
     482                 :             : /* Start of data area of a plain or short-header varlena datum */
     483                 :             : /* caution: this will not work on an external or compressed-in-line Datum */
     484                 :             : /* caution: this will return a possibly unaligned pointer */
     485                 :             : static inline char *
     486                 :   144589783 : VARDATA_ANY(const void *PTR)
     487                 :             : {
     488         [ +  + ]:   144589783 :     return VARATT_IS_1B(PTR) ? VARDATA_1B(PTR) : VARDATA_4B(PTR);
     489                 :             : }
     490                 :             : 
     491                 :             : /* Decompressed size of a compressed-in-line varlena datum */
     492                 :             : static inline Size
     493                 :      218254 : VARDATA_COMPRESSED_GET_EXTSIZE(const void *PTR)
     494                 :             : {
     495                 :      218254 :     return ((const varattrib_4b *) PTR)->va_compressed.va_tcinfo & VARLENA_EXTSIZE_MASK;
     496                 :             : }
     497                 :             : 
     498                 :             : /* Compression method of a compressed-in-line varlena datum */
     499                 :             : static inline uint32
     500                 :        8662 : VARDATA_COMPRESSED_GET_COMPRESS_METHOD(const void *PTR)
     501                 :             : {
     502                 :        8662 :     return ((const varattrib_4b *) PTR)->va_compressed.va_tcinfo >> VARLENA_EXTSIZE_BITS;
     503                 :             : }
     504                 :             : 
     505                 :             : /* Same for external Datums; but note argument is a varatt_external */
     506                 :             : static inline Size
     507                 :       75257 : VARATT_EXTERNAL_GET_EXTSIZE(varatt_external toast_pointer)
     508                 :             : {
     509                 :       75257 :     return toast_pointer.va_extinfo & VARLENA_EXTSIZE_MASK;
     510                 :             : }
     511                 :             : 
     512                 :             : static inline uint32
     513                 :         120 : VARATT_EXTERNAL_GET_COMPRESS_METHOD(varatt_external toast_pointer)
     514                 :             : {
     515                 :         120 :     return toast_pointer.va_extinfo >> VARLENA_EXTSIZE_BITS;
     516                 :             : }
     517                 :             : 
     518                 :             : /* Set size and compress method of an externally-stored varlena datum */
     519                 :             : /* This has to remain a macro; beware multiple evaluations! */
     520                 :             : #define VARATT_EXTERNAL_SET_SIZE_AND_COMPRESS_METHOD(toast_pointer, len, cm) \
     521                 :             :     do { \
     522                 :             :         Assert((cm) == TOAST_PGLZ_COMPRESSION_ID || \
     523                 :             :                (cm) == TOAST_LZ4_COMPRESSION_ID); \
     524                 :             :         ((toast_pointer).va_extinfo = \
     525                 :             :             (len) | ((uint32) (cm) << VARLENA_EXTSIZE_BITS)); \
     526                 :             :     } while (0)
     527                 :             : 
     528                 :             : /*
     529                 :             :  * Testing whether an externally-stored value is compressed now requires
     530                 :             :  * comparing size stored in va_extinfo (the actual length of the external data)
     531                 :             :  * to rawsize (the original uncompressed datum's size).  The latter includes
     532                 :             :  * VARHDRSZ overhead, the former doesn't.  We never use compression unless it
     533                 :             :  * actually saves space, so we expect either equality or less-than.
     534                 :             :  */
     535                 :             : static inline bool
     536                 :       45014 : VARATT_EXTERNAL_IS_COMPRESSED(varatt_external toast_pointer)
     537                 :             : {
     538                 :       45014 :     return VARATT_EXTERNAL_GET_EXTSIZE(toast_pointer) <
     539                 :       45014 :         (Size) (toast_pointer.va_rawsize - VARHDRSZ);
     540                 :             : }
     541                 :             : 
     542                 :             : #endif
        

Generated by: LCOV version 2.0-1