LCOV - differential code coverage report
Current view: top level - src/backend/access/common - toast_compression.c (source / functions) Coverage Total Hit LBC UBC GBC GNC CBC EUB ECB DCB
Current: 0e5ff9b9b45a657aea12440478dc002e9b01f138 vs 0123ce131fca454009439dfa3b2266d1d40737d7 Lines: 89.4 % 85 76 1 8 2 19 55 5 19
Current Date: 2026-03-14 14:10:32 -0400 Functions: 100.0 % 9 9 7 2 7
Baseline: lcov-20260315-024220-baseline Branches: 53.1 % 49 26 2 21 3 23 20 12
Baseline Date: 2026-03-14 15:27:56 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 100.0 % 19 19 19
(360..) days: 86.4 % 66 57 1 8 2 55 5
Function coverage date bins:
(30,360] days: 100.0 % 7 7 7
(360..) days: 100.0 % 2 2 2
Branch coverage date bins:
(360..) days: 32.1 % 81 26 2 21 3 23 20 12

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * toast_compression.c
                                  4                 :                :  *    Functions for toast compression.
                                  5                 :                :  *
                                  6                 :                :  * Copyright (c) 2021-2026, PostgreSQL Global Development Group
                                  7                 :                :  *
                                  8                 :                :  *
                                  9                 :                :  * IDENTIFICATION
                                 10                 :                :  *    src/backend/access/common/toast_compression.c
                                 11                 :                :  *
                                 12                 :                :  *-------------------------------------------------------------------------
                                 13                 :                :  */
                                 14                 :                : #include "postgres.h"
                                 15                 :                : 
                                 16                 :                : #ifdef USE_LZ4
                                 17                 :                : #include <lz4.h>
                                 18                 :                : #endif
                                 19                 :                : 
                                 20                 :                : #include "access/detoast.h"
                                 21                 :                : #include "access/toast_compression.h"
                                 22                 :                : #include "common/pg_lzcompress.h"
                                 23                 :                : #include "varatt.h"
                                 24                 :                : 
                                 25                 :                : /* GUC */
                                 26                 :                : int         default_toast_compression = DEFAULT_TOAST_COMPRESSION;
                                 27                 :                : 
                                 28                 :                : #define NO_COMPRESSION_SUPPORT(method) \
                                 29                 :                :     ereport(ERROR, \
                                 30                 :                :             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \
                                 31                 :                :              errmsg("compression method %s not supported", method), \
                                 32                 :                :              errdetail("This functionality requires the server to be built with %s support.", method)))
                                 33                 :                : 
                                 34                 :                : /*
                                 35                 :                :  * Compress a varlena using PGLZ.
                                 36                 :                :  *
                                 37                 :                :  * Returns the compressed varlena, or NULL if compression fails.
                                 38                 :                :  */
                                 39                 :                : varlena *
   32 michael@paquier.xyz        40                 :GNC          81 : pglz_compress_datum(const varlena *value)
                                 41                 :                : {
                                 42                 :                :     int32       valsize,
                                 43                 :                :                 len;
                                 44                 :             81 :     varlena    *tmp = NULL;
                                 45                 :                : 
 1295 peter@eisentraut.org       46   [ -  +  -  -  :CBC          81 :     valsize = VARSIZE_ANY_EXHDR(value);
                                     -  -  -  -  +  
                                                 + ]
                                 47                 :                : 
                                 48                 :                :     /*
                                 49                 :                :      * No point in wasting a palloc cycle if value size is outside the allowed
                                 50                 :                :      * range for compression.
                                 51                 :                :      */
 1822 rhaas@postgresql.org       52         [ +  - ]:             81 :     if (valsize < PGLZ_strategy_default->min_input_size ||
                                 53         [ -  + ]:             81 :         valsize > PGLZ_strategy_default->max_input_size)
 1822 rhaas@postgresql.org       54                 :LBC       (478) :         return NULL;
                                 55                 :                : 
                                 56                 :                :     /*
                                 57                 :                :      * Figure out the maximum possible size of the pglz output, add the bytes
                                 58                 :                :      * that will be needed for varlena overhead, and allocate that amount.
                                 59                 :                :      */
   32 michael@paquier.xyz        60                 :GNC          81 :     tmp = (varlena *) palloc(PGLZ_MAX_OUTPUT(valsize) +
                                 61                 :                :                              VARHDRSZ_COMPRESSED);
                                 62                 :                : 
 1822 rhaas@postgresql.org       63         [ +  + ]:CBC          81 :     len = pglz_compress(VARDATA_ANY(value),
                                 64                 :                :                         valsize,
                                 65                 :                :                         (char *) tmp + VARHDRSZ_COMPRESSED,
                                 66                 :                :                         NULL);
                                 67         [ +  + ]:             81 :     if (len < 0)
                                 68                 :                :     {
                                 69                 :              3 :         pfree(tmp);
                                 70                 :              3 :         return NULL;
                                 71                 :                :     }
                                 72                 :                : 
 1819 tgl@sss.pgh.pa.us          73                 :             78 :     SET_VARSIZE_COMPRESSED(tmp, len + VARHDRSZ_COMPRESSED);
                                 74                 :                : 
 1822 rhaas@postgresql.org       75                 :             78 :     return tmp;
                                 76                 :                : }
                                 77                 :                : 
                                 78                 :                : /*
                                 79                 :                :  * Decompress a varlena that was compressed using PGLZ.
                                 80                 :                :  */
                                 81                 :                : varlena *
   32 michael@paquier.xyz        82                 :GNC         280 : pglz_decompress_datum(const varlena *value)
                                 83                 :                : {
                                 84                 :                :     varlena    *result;
                                 85                 :                :     int32       rawsize;
                                 86                 :                : 
                                 87                 :                :     /* allocate memory for the uncompressed data */
                                 88                 :            280 :     result = (varlena *) palloc(VARDATA_COMPRESSED_GET_EXTSIZE(value) + VARHDRSZ);
                                 89                 :                : 
                                 90                 :                :     /* decompress the data */
   48 peter@eisentraut.org       91                 :            280 :     rawsize = pglz_decompress((const char *) value + VARHDRSZ_COMPRESSED,
 1819 tgl@sss.pgh.pa.us          92                 :CBC         280 :                               VARSIZE(value) - VARHDRSZ_COMPRESSED,
 1822 rhaas@postgresql.org       93                 :ECB     (74527) :                               VARDATA(result),
 1819 tgl@sss.pgh.pa.us          94                 :CBC         280 :                               VARDATA_COMPRESSED_GET_EXTSIZE(value), true);
 1822 rhaas@postgresql.org       95         [ -  + ]:            280 :     if (rawsize < 0)
 1822 rhaas@postgresql.org       96         [ #  # ]:UBC           0 :         ereport(ERROR,
                                 97                 :                :                 (errcode(ERRCODE_DATA_CORRUPTED),
                                 98                 :                :                  errmsg_internal("compressed pglz data is corrupt")));
                                 99                 :                : 
 1822 rhaas@postgresql.org      100                 :CBC         280 :     SET_VARSIZE(result, rawsize + VARHDRSZ);
                                101                 :                : 
                                102                 :            280 :     return result;
                                103                 :                : }
                                104                 :                : 
                                105                 :                : /*
                                106                 :                :  * Decompress part of a varlena that was compressed using PGLZ.
                                107                 :                :  */
                                108                 :                : varlena *
   32 michael@paquier.xyz       109                 :GNC          18 : pglz_decompress_datum_slice(const varlena *value,
                                110                 :                :                             int32 slicelength)
                                111                 :                : {
                                112                 :                :     varlena    *result;
                                113                 :                :     int32       rawsize;
                                114                 :                : 
                                115                 :                :     /* allocate memory for the uncompressed data */
                                116                 :             18 :     result = (varlena *) palloc(slicelength + VARHDRSZ);
                                117                 :                : 
                                118                 :                :     /* decompress the data */
   48 peter@eisentraut.org      119                 :             18 :     rawsize = pglz_decompress((const char *) value + VARHDRSZ_COMPRESSED,
 1819 tgl@sss.pgh.pa.us         120                 :CBC          18 :                               VARSIZE(value) - VARHDRSZ_COMPRESSED,
 1822 rhaas@postgresql.org      121                 :ECB        (36) :                               VARDATA(result),
                                122                 :                :                               slicelength, false);
 1822 rhaas@postgresql.org      123         [ -  + ]:CBC          18 :     if (rawsize < 0)
 1822 rhaas@postgresql.org      124         [ #  # ]:UBC           0 :         ereport(ERROR,
                                125                 :                :                 (errcode(ERRCODE_DATA_CORRUPTED),
                                126                 :                :                  errmsg_internal("compressed pglz data is corrupt")));
                                127                 :                : 
 1822 rhaas@postgresql.org      128                 :CBC          18 :     SET_VARSIZE(result, rawsize + VARHDRSZ);
                                129                 :                : 
                                130                 :             18 :     return result;
                                131                 :                : }
                                132                 :                : 
                                133                 :                : /*
                                134                 :                :  * Compress a varlena using LZ4.
                                135                 :                :  *
                                136                 :                :  * Returns the compressed varlena, or NULL if compression fails.
                                137                 :                :  */
                                138                 :                : varlena *
   32 michael@paquier.xyz       139                 :GNC       27602 : lz4_compress_datum(const varlena *value)
                                140                 :                : {
                                141                 :                : #ifndef USE_LZ4
                                142                 :                :     NO_COMPRESSION_SUPPORT("lz4");
                                143                 :                :     return NULL;                /* keep compiler quiet */
                                144                 :                : #else
                                145                 :                :     int32       valsize;
                                146                 :                :     int32       len;
                                147                 :                :     int32       max_size;
                                148                 :          27602 :     varlena    *tmp = NULL;
                                149                 :                : 
 1822 rhaas@postgresql.org      150   [ -  +  -  -  :CBC       27602 :     valsize = VARSIZE_ANY_EXHDR(value);
                                     -  -  -  -  -  
                                                 + ]
                                151                 :                : 
                                152                 :                :     /*
                                153                 :                :      * Figure out the maximum possible size of the LZ4 output, add the bytes
                                154                 :                :      * that will be needed for varlena overhead, and allocate that amount.
                                155                 :                :      */
                                156                 :          27602 :     max_size = LZ4_compressBound(valsize);
   32 michael@paquier.xyz       157                 :GNC       27602 :     tmp = (varlena *) palloc(max_size + VARHDRSZ_COMPRESSED);
                                158                 :                : 
 1822 rhaas@postgresql.org      159         [ -  + ]:CBC       27602 :     len = LZ4_compress_default(VARDATA_ANY(value),
                                160                 :                :                                (char *) tmp + VARHDRSZ_COMPRESSED,
                                161                 :                :                                valsize, max_size);
                                162         [ -  + ]:          27602 :     if (len <= 0)
 1822 rhaas@postgresql.org      163         [ #  # ]:UBC           0 :         elog(ERROR, "lz4 compression failed");
                                164                 :                : 
                                165                 :                :     /* data is incompressible so just free the memory and return NULL */
 1822 rhaas@postgresql.org      166         [ +  + ]:CBC       27602 :     if (len > valsize)
                                167                 :                :     {
 1822 rhaas@postgresql.org      168                 :GBC         619 :         pfree(tmp);
                                169                 :            619 :         return NULL;
                                170                 :                :     }
                                171                 :                : 
 1819 tgl@sss.pgh.pa.us         172                 :CBC       26983 :     SET_VARSIZE_COMPRESSED(tmp, len + VARHDRSZ_COMPRESSED);
                                173                 :                : 
 1822 rhaas@postgresql.org      174                 :          26983 :     return tmp;
                                175                 :                : #endif
                                176                 :                : }
                                177                 :                : 
                                178                 :                : /*
                                179                 :                :  * Decompress a varlena that was compressed using LZ4.
                                180                 :                :  */
                                181                 :                : varlena *
   32 michael@paquier.xyz       182                 :GNC       85864 : lz4_decompress_datum(const varlena *value)
                                183                 :                : {
                                184                 :                : #ifndef USE_LZ4
                                185                 :                :     NO_COMPRESSION_SUPPORT("lz4");
                                186                 :                :     return NULL;                /* keep compiler quiet */
                                187                 :                : #else
                                188                 :                :     int32       rawsize;
                                189                 :                :     varlena    *result;
                                190                 :                : 
                                191                 :                :     /* allocate memory for the uncompressed data */
                                192                 :          85864 :     result = (varlena *) palloc(VARDATA_COMPRESSED_GET_EXTSIZE(value) + VARHDRSZ);
                                193                 :                : 
                                194                 :                :     /* decompress the data */
   48 peter@eisentraut.org      195                 :          85864 :     rawsize = LZ4_decompress_safe((const char *) value + VARHDRSZ_COMPRESSED,
 1822 rhaas@postgresql.org      196                 :ECB        (50) :                                   VARDATA(result),
 1819 tgl@sss.pgh.pa.us         197                 :CBC       85864 :                                   VARSIZE(value) - VARHDRSZ_COMPRESSED,
                                198                 :          85864 :                                   VARDATA_COMPRESSED_GET_EXTSIZE(value));
 1822 rhaas@postgresql.org      199         [ -  + ]:          85864 :     if (rawsize < 0)
 1822 rhaas@postgresql.org      200         [ #  # ]:UBC           0 :         ereport(ERROR,
                                201                 :                :                 (errcode(ERRCODE_DATA_CORRUPTED),
                                202                 :                :                  errmsg_internal("compressed lz4 data is corrupt")));
                                203                 :                : 
                                204                 :                : 
 1822 rhaas@postgresql.org      205                 :CBC       85864 :     SET_VARSIZE(result, rawsize + VARHDRSZ);
                                206                 :                : 
                                207                 :          85864 :     return result;
                                208                 :                : #endif
                                209                 :                : }
                                210                 :                : 
                                211                 :                : /*
                                212                 :                :  * Decompress part of a varlena that was compressed using LZ4.
                                213                 :                :  */
                                214                 :                : varlena *
   32 michael@paquier.xyz       215                 :GNC         135 : lz4_decompress_datum_slice(const varlena *value, int32 slicelength)
                                216                 :                : {
                                217                 :                : #ifndef USE_LZ4
                                218                 :                :     NO_COMPRESSION_SUPPORT("lz4");
                                219                 :                :     return NULL;                /* keep compiler quiet */
                                220                 :                : #else
                                221                 :                :     int32       rawsize;
                                222                 :                :     varlena    *result;
                                223                 :                : 
                                224                 :                :     /* slice decompression not supported prior to 1.8.3 */
 1822 rhaas@postgresql.org      225         [ -  + ]:CBC         135 :     if (LZ4_versionNumber() < 10803)
 1822 rhaas@postgresql.org      226                 :UBC           0 :         return lz4_decompress_datum(value);
                                227                 :                : 
                                228                 :                :     /* allocate memory for the uncompressed data */
   32 michael@paquier.xyz       229                 :GNC         135 :     result = (varlena *) palloc(slicelength + VARHDRSZ);
                                230                 :                : 
                                231                 :                :     /* decompress the data */
   48 peter@eisentraut.org      232                 :            135 :     rawsize = LZ4_decompress_safe_partial((const char *) value + VARHDRSZ_COMPRESSED,
 1822 rhaas@postgresql.org      233                 :ECB         (9) :                                           VARDATA(result),
 1819 tgl@sss.pgh.pa.us         234                 :CBC         135 :                                           VARSIZE(value) - VARHDRSZ_COMPRESSED,
                                235                 :                :                                           slicelength,
                                236                 :                :                                           slicelength);
 1822 rhaas@postgresql.org      237         [ -  + ]:            135 :     if (rawsize < 0)
 1822 rhaas@postgresql.org      238         [ #  # ]:UBC           0 :         ereport(ERROR,
                                239                 :                :                 (errcode(ERRCODE_DATA_CORRUPTED),
                                240                 :                :                  errmsg_internal("compressed lz4 data is corrupt")));
                                241                 :                : 
 1822 rhaas@postgresql.org      242                 :CBC         135 :     SET_VARSIZE(result, rawsize + VARHDRSZ);
                                243                 :                : 
                                244                 :            135 :     return result;
                                245                 :                : #endif
                                246                 :                : }
                                247                 :                : 
                                248                 :                : /*
                                249                 :                :  * Extract compression ID from a varlena.
                                250                 :                :  *
                                251                 :                :  * Returns TOAST_INVALID_COMPRESSION_ID if the varlena is not compressed.
                                252                 :                :  */
                                253                 :                : ToastCompressionId
   32 michael@paquier.xyz       254                 :GNC          96 : toast_get_compression_id(varlena *attr)
                                255                 :                : {
 1768 tgl@sss.pgh.pa.us         256                 :CBC          96 :     ToastCompressionId cmid = TOAST_INVALID_COMPRESSION_ID;
                                257                 :                : 
                                258                 :                :     /*
                                259                 :                :      * If it is stored externally then fetch the compression method id from
                                260                 :                :      * the external toast pointer.  If compressed inline, fetch it from the
                                261                 :                :      * toast compression header.
                                262                 :                :      */
 1822 rhaas@postgresql.org      263   [ +  +  +  - ]:             96 :     if (VARATT_IS_EXTERNAL_ONDISK(attr))
 1822 rhaas@postgresql.org      264                 :ECB        (12) :     {
                                265                 :                :         varatt_external toast_pointer;
                                266                 :                : 
 1822 rhaas@postgresql.org      267   [ -  +  -  +  :CBC          24 :         VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
                                     +  -  -  +  -  
                                                 + ]
                                268                 :                : 
                                269         [ +  + ]:             24 :         if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer))
 1819 tgl@sss.pgh.pa.us         270                 :              9 :             cmid = VARATT_EXTERNAL_GET_COMPRESS_METHOD(toast_pointer);
                                271                 :                :     }
 1822 rhaas@postgresql.org      272         [ +  + ]:             72 :     else if (VARATT_IS_COMPRESSED(attr))
 1819 tgl@sss.pgh.pa.us         273                 :             66 :         cmid = VARDATA_COMPRESSED_GET_COMPRESS_METHOD(attr);
                                274                 :                : 
 1822 rhaas@postgresql.org      275                 :             96 :     return cmid;
                                276                 :                : }
                                277                 :                : 
                                278                 :                : /*
                                279                 :                :  * CompressionNameToMethod - Get compression method from compression name
                                280                 :                :  *
                                281                 :                :  * Search in the available built-in methods.  If the compression not found
                                282                 :                :  * in the built-in methods then return InvalidCompressionMethod.
                                283                 :                :  */
                                284                 :                : char
 1817                           285                 :            104 : CompressionNameToMethod(const char *compression)
                                286                 :                : {
                                287         [ +  + ]:            104 :     if (strcmp(compression, "pglz") == 0)
                                288                 :             64 :         return TOAST_PGLZ_COMPRESSION;
                                289         [ +  + ]:             40 :     else if (strcmp(compression, "lz4") == 0)
                                290                 :                :     {
                                291                 :                : #ifndef USE_LZ4
                                292                 :                :         NO_COMPRESSION_SUPPORT("lz4");
                                293                 :                : #endif
                                294                 :             34 :         return TOAST_LZ4_COMPRESSION;
                                295                 :                :     }
                                296                 :                : 
                                297                 :              6 :     return InvalidCompressionMethod;
                                298                 :                : }
                                299                 :                : 
                                300                 :                : /*
                                301                 :                :  * GetCompressionMethodName - Get compression method name
                                302                 :                :  */
                                303                 :                : const char *
                                304                 :             30 : GetCompressionMethodName(char method)
                                305                 :                : {
                                306      [ +  +  - ]:             30 :     switch (method)
                                307                 :                :     {
                                308                 :             21 :         case TOAST_PGLZ_COMPRESSION:
                                309                 :             21 :             return "pglz";
                                310                 :              9 :         case TOAST_LZ4_COMPRESSION:
                                311                 :              9 :             return "lz4";
 1817 rhaas@postgresql.org      312                 :UBC           0 :         default:
                                313         [ #  # ]:              0 :             elog(ERROR, "invalid compression method %c", method);
                                314                 :                :             return NULL;        /* keep compiler quiet */
                                315                 :                :     }
                                316                 :                : }
        

Generated by: LCOV version 2.4-beta