LCOV - code coverage report
Current view: top level - src/include - varatt.h (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 96.5 % 86 83
Test Date: 2026-03-02 12:14:42 Functions: 100.0 % 33 33
Legend: Lines:     hit not hit

            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       180709 : VARTAG_IS_EXPANDED(vartag_external tag)
      96              : {
      97       180709 :     return ((tag & ~1) == VARTAG_EXPANDED_RO);
      98              : }
      99              : 
     100              : /* Size of the data part of a "TOAST pointer" datum */
     101              : static inline Size
     102        93060 : VARTAG_SIZE(vartag_external tag)
     103              : {
     104        93060 :     if (tag == VARTAG_INDIRECT)
     105          707 :         return sizeof(varatt_indirect);
     106        92353 :     else if (VARTAG_IS_EXPANDED(tag))
     107            0 :         return sizeof(varatt_expanded);
     108        92353 :     else if (tag == VARTAG_ONDISK)
     109        92353 :         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    112679838 : VARSIZE(const void *PTR)
     299              : {
     300    112679838 :     return VARSIZE_4B(PTR);
     301              : }
     302              : 
     303              : /* Start of data area of a known-not-toasted varlena datum */
     304              : static inline char *
     305     60852721 : VARDATA(const void *PTR)
     306              : {
     307     60852721 :     return VARDATA_4B(PTR);
     308              : }
     309              : 
     310              : /* Size of a known-short-header varlena datum, including header */
     311              : static inline Size
     312     37625369 : VARSIZE_SHORT(const void *PTR)
     313              : {
     314     37625369 :     return VARSIZE_1B(PTR);
     315              : }
     316              : 
     317              : /* Start of data area of a known-short-header varlena datum */
     318              : static inline char *
     319     25943247 : VARDATA_SHORT(const void *PTR)
     320              : {
     321     25943247 :     return VARDATA_1B(PTR);
     322              : }
     323              : 
     324              : /* Type tag of a "TOAST pointer" datum */
     325              : static inline vartag_external
     326       285206 : VARTAG_EXTERNAL(const void *PTR)
     327              : {
     328       285206 :     return VARTAG_1B_E(PTR);
     329              : }
     330              : 
     331              : /* Size of a "TOAST pointer" datum, including header */
     332              : static inline Size
     333        93060 : VARSIZE_EXTERNAL(const void *PTR)
     334              : {
     335        93060 :     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       176556 : VARDATA_EXTERNAL(const void *PTR)
     341              : {
     342       176556 :     return VARDATA_1B_E(PTR);
     343              : }
     344              : 
     345              : /* Is varlena datum in inline-compressed format? */
     346              : static inline bool
     347    161459987 : VARATT_IS_COMPRESSED(const void *PTR)
     348              : {
     349    161459987 :     return VARATT_IS_4B_C(PTR);
     350              : }
     351              : 
     352              : /* Is varlena datum a "TOAST pointer" datum? */
     353              : static inline bool
     354    285894527 : VARATT_IS_EXTERNAL(const void *PTR)
     355              : {
     356    285894527 :     return VARATT_IS_1B_E(PTR);
     357              : }
     358              : 
     359              : /* Is varlena datum a pointer to on-disk toasted data? */
     360              : static inline bool
     361     38974037 : VARATT_IS_EXTERNAL_ONDISK(const void *PTR)
     362              : {
     363     38974037 :     return VARATT_IS_EXTERNAL(PTR) && VARTAG_EXTERNAL(PTR) == VARTAG_ONDISK;
     364              : }
     365              : 
     366              : /* Is varlena datum an indirect pointer? */
     367              : static inline bool
     368     38713575 : VARATT_IS_EXTERNAL_INDIRECT(const void *PTR)
     369              : {
     370     38713575 :     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        17865 : VARATT_IS_EXTERNAL_EXPANDED_RO(const void *PTR)
     376              : {
     377        17865 :     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      4859238 : VARATT_IS_EXTERNAL_EXPANDED_RW(const void *PTR)
     383              : {
     384      4859238 :     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     59204778 : VARATT_IS_EXTERNAL_EXPANDED(const void *PTR)
     390              : {
     391     59204778 :     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        21916 : VARATT_IS_EXTERNAL_NON_EXPANDED(const void *PTR)
     397              : {
     398        21916 :     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     63486922 : VARATT_IS_SHORT(const void *PTR)
     404              : {
     405     63486922 :     return VARATT_IS_1B(PTR);
     406              : }
     407              : 
     408              : /* Is varlena datum not in traditional (4-byte-header, uncompressed) format? */
     409              : static inline bool
     410     73840386 : VARATT_IS_EXTENDED(const void *PTR)
     411              : {
     412     73840386 :     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     33916115 : VARATT_CAN_MAKE_SHORT(const void *PTR)
     418              : {
     419     63912734 :     return VARATT_IS_4B_U(PTR) &&
     420     29996619 :         (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     28891697 : VARATT_CONVERTED_SHORT_SIZE(const void *PTR)
     426              : {
     427     28891697 :     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     69593397 : SET_VARSIZE(void *PTR, Size len)
     433              : {
     434     69593397 :     SET_VARSIZE_4B(PTR, len);
     435     69593397 : }
     436              : 
     437              : /* Set the size (including header) of a short-header varlena datum */
     438              : static inline void
     439     14361547 : SET_VARSIZE_SHORT(void *PTR, Size len)
     440              : {
     441     14361547 :     SET_VARSIZE_1B(PTR, len);
     442     14361547 : }
     443              : 
     444              : /* Set the size (including header) of an inline-compressed varlena datum */
     445              : static inline void
     446        31499 : SET_VARSIZE_COMPRESSED(void *PTR, Size len)
     447              : {
     448        31499 :     SET_VARSIZE_4B_C(PTR, len);
     449        31499 : }
     450              : 
     451              : /* Set the type tag of a "TOAST pointer" datum */
     452              : static inline void
     453        64027 : SET_VARTAG_EXTERNAL(void *PTR, vartag_external tag)
     454              : {
     455        64027 :     SET_VARTAG_1B_E(PTR, tag);
     456        64027 : }
     457              : 
     458              : /* Size of a varlena datum of any format, including header */
     459              : static inline Size
     460    101892112 : VARSIZE_ANY(const void *PTR)
     461              : {
     462    101892112 :     if (VARATT_IS_1B_E(PTR))
     463        83813 :         return VARSIZE_EXTERNAL(PTR);
     464    101808299 :     else if (VARATT_IS_1B(PTR))
     465     73992891 :         return VARSIZE_1B(PTR);
     466              :     else
     467     27815408 :         return VARSIZE_4B(PTR);
     468              : }
     469              : 
     470              : /* Size of a varlena datum of any format, excluding header */
     471              : static inline Size
     472    117536987 : VARSIZE_ANY_EXHDR(const void *PTR)
     473              : {
     474    117536987 :     if (VARATT_IS_1B_E(PTR))
     475            0 :         return VARSIZE_EXTERNAL(PTR) - VARHDRSZ_EXTERNAL;
     476    117536987 :     else if (VARATT_IS_1B(PTR))
     477     11876850 :         return VARSIZE_1B(PTR) - VARHDRSZ_SHORT;
     478              :     else
     479    105660137 :         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    121811560 : VARDATA_ANY(const void *PTR)
     487              : {
     488    121811560 :     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       161155 : VARDATA_COMPRESSED_GET_EXTSIZE(const void *PTR)
     494              : {
     495       161155 :     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         5343 : VARDATA_COMPRESSED_GET_COMPRESS_METHOD(const void *PTR)
     501              : {
     502         5343 :     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        63350 : VARATT_EXTERNAL_GET_EXTSIZE(varatt_external toast_pointer)
     508              : {
     509        63350 :     return toast_pointer.va_extinfo & VARLENA_EXTSIZE_MASK;
     510              : }
     511              : 
     512              : static inline uint32
     513           33 : VARATT_EXTERNAL_GET_COMPRESS_METHOD(varatt_external toast_pointer)
     514              : {
     515           33 :     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        39088 : VARATT_EXTERNAL_IS_COMPRESSED(varatt_external toast_pointer)
     537              : {
     538        39088 :     return VARATT_EXTERNAL_GET_EXTSIZE(toast_pointer) <
     539        39088 :         (Size) (toast_pointer.va_rawsize - VARHDRSZ);
     540              : }
     541              : 
     542              : #endif
        

Generated by: LCOV version 2.0-1