LCOV - differential code coverage report
Current view: top level - src/backend/access/common - toast_compression.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 88.9 % 90 80 10 80
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 9 9 9
Baseline: 16@8cea358b128 Branches: 45.7 % 81 37 44 37
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 88.9 % 90 80 10 80
Function coverage date bins:
(240..) days: 100.0 % 9 9 9
Branch coverage date bins:
(240..) days: 45.7 % 81 37 44 37

 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-2024, 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 = TOAST_PGLZ_COMPRESSION;
                                 27                 :                : 
                                 28                 :                : #define NO_LZ4_SUPPORT() \
                                 29                 :                :     ereport(ERROR, \
                                 30                 :                :             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \
                                 31                 :                :              errmsg("compression method lz4 not supported"), \
                                 32                 :                :              errdetail("This functionality requires the server to be built with lz4 support.")))
                                 33                 :                : 
                                 34                 :                : /*
                                 35                 :                :  * Compress a varlena using PGLZ.
                                 36                 :                :  *
                                 37                 :                :  * Returns the compressed varlena, or NULL if compression fails.
                                 38                 :                :  */
                                 39                 :                : struct varlena *
 1122 rhaas@postgresql.org       40                 :CBC       22381 : pglz_compress_datum(const struct varlena *value)
                                 41                 :                : {
                                 42                 :                :     int32       valsize,
                                 43                 :                :                 len;
                                 44                 :          22381 :     struct varlena *tmp = NULL;
                                 45                 :                : 
  595 peter@eisentraut.org       46   [ -  +  -  -  :          22381 :     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                 :                :      */
 1122 rhaas@postgresql.org       52         [ +  + ]:          22381 :     if (valsize < PGLZ_strategy_default->min_input_size ||
                                 53         [ -  + ]:          22033 :         valsize > PGLZ_strategy_default->max_input_size)
                                 54                 :            348 :         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                 :                :      */
                                 60                 :          22033 :     tmp = (struct varlena *) palloc(PGLZ_MAX_OUTPUT(valsize) +
                                 61                 :                :                                     VARHDRSZ_COMPRESSED);
                                 62                 :                : 
                                 63         [ +  + ]:          22033 :     len = pglz_compress(VARDATA_ANY(value),
                                 64                 :                :                         valsize,
                                 65                 :                :                         (char *) tmp + VARHDRSZ_COMPRESSED,
                                 66                 :                :                         NULL);
                                 67         [ +  + ]:          22033 :     if (len < 0)
                                 68                 :                :     {
                                 69                 :           5465 :         pfree(tmp);
                                 70                 :           5465 :         return NULL;
                                 71                 :                :     }
                                 72                 :                : 
 1119 tgl@sss.pgh.pa.us          73                 :          16568 :     SET_VARSIZE_COMPRESSED(tmp, len + VARHDRSZ_COMPRESSED);
                                 74                 :                : 
 1122 rhaas@postgresql.org       75                 :          16568 :     return tmp;
                                 76                 :                : }
                                 77                 :                : 
                                 78                 :                : /*
                                 79                 :                :  * Decompress a varlena that was compressed using PGLZ.
                                 80                 :                :  */
                                 81                 :                : struct varlena *
                                 82                 :          65457 : pglz_decompress_datum(const struct varlena *value)
                                 83                 :                : {
                                 84                 :                :     struct varlena *result;
                                 85                 :                :     int32       rawsize;
                                 86                 :                : 
                                 87                 :                :     /* allocate memory for the uncompressed data */
 1119 tgl@sss.pgh.pa.us          88                 :          65457 :     result = (struct varlena *) palloc(VARDATA_COMPRESSED_GET_EXTSIZE(value) + VARHDRSZ);
                                 89                 :                : 
                                 90                 :                :     /* decompress the data */
                                 91                 :          65457 :     rawsize = pglz_decompress((char *) value + VARHDRSZ_COMPRESSED,
                                 92                 :          65457 :                               VARSIZE(value) - VARHDRSZ_COMPRESSED,
 1122 rhaas@postgresql.org       93                 :          65457 :                               VARDATA(result),
 1119 tgl@sss.pgh.pa.us          94                 :          65457 :                               VARDATA_COMPRESSED_GET_EXTSIZE(value), true);
 1122 rhaas@postgresql.org       95         [ -  + ]:          65457 :     if (rawsize < 0)
 1122 rhaas@postgresql.org       96         [ #  # ]:UBC           0 :         ereport(ERROR,
                                 97                 :                :                 (errcode(ERRCODE_DATA_CORRUPTED),
                                 98                 :                :                  errmsg_internal("compressed pglz data is corrupt")));
                                 99                 :                : 
 1122 rhaas@postgresql.org      100                 :CBC       65457 :     SET_VARSIZE(result, rawsize + VARHDRSZ);
                                101                 :                : 
                                102                 :          65457 :     return result;
                                103                 :                : }
                                104                 :                : 
                                105                 :                : /*
                                106                 :                :  * Decompress part of a varlena that was compressed using PGLZ.
                                107                 :                :  */
                                108                 :                : struct varlena *
                                109                 :             33 : pglz_decompress_datum_slice(const struct varlena *value,
                                110                 :                :                             int32 slicelength)
                                111                 :                : {
                                112                 :                :     struct varlena *result;
                                113                 :                :     int32       rawsize;
                                114                 :                : 
                                115                 :                :     /* allocate memory for the uncompressed data */
                                116                 :             33 :     result = (struct varlena *) palloc(slicelength + VARHDRSZ);
                                117                 :                : 
                                118                 :                :     /* decompress the data */
 1119 tgl@sss.pgh.pa.us         119                 :             33 :     rawsize = pglz_decompress((char *) value + VARHDRSZ_COMPRESSED,
                                120                 :             33 :                               VARSIZE(value) - VARHDRSZ_COMPRESSED,
 1122 rhaas@postgresql.org      121                 :             33 :                               VARDATA(result),
                                122                 :                :                               slicelength, false);
                                123         [ -  + ]:             33 :     if (rawsize < 0)
 1122 rhaas@postgresql.org      124         [ #  # ]:UBC           0 :         ereport(ERROR,
                                125                 :                :                 (errcode(ERRCODE_DATA_CORRUPTED),
                                126                 :                :                  errmsg_internal("compressed pglz data is corrupt")));
                                127                 :                : 
 1122 rhaas@postgresql.org      128                 :CBC          33 :     SET_VARSIZE(result, rawsize + VARHDRSZ);
                                129                 :                : 
                                130                 :             33 :     return result;
                                131                 :                : }
                                132                 :                : 
                                133                 :                : /*
                                134                 :                :  * Compress a varlena using LZ4.
                                135                 :                :  *
                                136                 :                :  * Returns the compressed varlena, or NULL if compression fails.
                                137                 :                :  */
                                138                 :                : struct varlena *
                                139                 :             18 : lz4_compress_datum(const struct varlena *value)
                                140                 :                : {
                                141                 :                : #ifndef USE_LZ4
                                142                 :                :     NO_LZ4_SUPPORT();
                                143                 :                :     return NULL;                /* keep compiler quiet */
                                144                 :                : #else
                                145                 :                :     int32       valsize;
                                146                 :                :     int32       len;
                                147                 :                :     int32       max_size;
                                148                 :             18 :     struct varlena *tmp = NULL;
                                149                 :                : 
                                150   [ -  +  -  -  :             18 :     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                 :             18 :     max_size = LZ4_compressBound(valsize);
 1119 tgl@sss.pgh.pa.us         157                 :             18 :     tmp = (struct varlena *) palloc(max_size + VARHDRSZ_COMPRESSED);
                                158                 :                : 
 1122 rhaas@postgresql.org      159         [ -  + ]:             18 :     len = LZ4_compress_default(VARDATA_ANY(value),
                                160                 :                :                                (char *) tmp + VARHDRSZ_COMPRESSED,
                                161                 :                :                                valsize, max_size);
                                162         [ -  + ]:             18 :     if (len <= 0)
 1122 rhaas@postgresql.org      163         [ #  # ]:UBC           0 :         elog(ERROR, "lz4 compression failed");
                                164                 :                : 
                                165                 :                :     /* data is incompressible so just free the memory and return NULL */
 1122 rhaas@postgresql.org      166         [ -  + ]:CBC          18 :     if (len > valsize)
                                167                 :                :     {
 1122 rhaas@postgresql.org      168                 :UBC           0 :         pfree(tmp);
                                169                 :              0 :         return NULL;
                                170                 :                :     }
                                171                 :                : 
 1119 tgl@sss.pgh.pa.us         172                 :CBC          18 :     SET_VARSIZE_COMPRESSED(tmp, len + VARHDRSZ_COMPRESSED);
                                173                 :                : 
 1122 rhaas@postgresql.org      174                 :             18 :     return tmp;
                                175                 :                : #endif
                                176                 :                : }
                                177                 :                : 
                                178                 :                : /*
                                179                 :                :  * Decompress a varlena that was compressed using LZ4.
                                180                 :                :  */
                                181                 :                : struct varlena *
                                182                 :             50 : lz4_decompress_datum(const struct varlena *value)
                                183                 :                : {
                                184                 :                : #ifndef USE_LZ4
                                185                 :                :     NO_LZ4_SUPPORT();
                                186                 :                :     return NULL;                /* keep compiler quiet */
                                187                 :                : #else
                                188                 :                :     int32       rawsize;
                                189                 :                :     struct varlena *result;
                                190                 :                : 
                                191                 :                :     /* allocate memory for the uncompressed data */
 1119 tgl@sss.pgh.pa.us         192                 :             50 :     result = (struct varlena *) palloc(VARDATA_COMPRESSED_GET_EXTSIZE(value) + VARHDRSZ);
                                193                 :                : 
                                194                 :                :     /* decompress the data */
                                195                 :             50 :     rawsize = LZ4_decompress_safe((char *) value + VARHDRSZ_COMPRESSED,
 1122 rhaas@postgresql.org      196                 :             50 :                                   VARDATA(result),
 1119 tgl@sss.pgh.pa.us         197                 :             50 :                                   VARSIZE(value) - VARHDRSZ_COMPRESSED,
                                198                 :             50 :                                   VARDATA_COMPRESSED_GET_EXTSIZE(value));
 1122 rhaas@postgresql.org      199         [ -  + ]:             50 :     if (rawsize < 0)
 1122 rhaas@postgresql.org      200         [ #  # ]:UBC           0 :         ereport(ERROR,
                                201                 :                :                 (errcode(ERRCODE_DATA_CORRUPTED),
                                202                 :                :                  errmsg_internal("compressed lz4 data is corrupt")));
                                203                 :                : 
                                204                 :                : 
 1122 rhaas@postgresql.org      205                 :CBC          50 :     SET_VARSIZE(result, rawsize + VARHDRSZ);
                                206                 :                : 
                                207                 :             50 :     return result;
                                208                 :                : #endif
                                209                 :                : }
                                210                 :                : 
                                211                 :                : /*
                                212                 :                :  * Decompress part of a varlena that was compressed using LZ4.
                                213                 :                :  */
                                214                 :                : struct varlena *
                                215                 :              9 : lz4_decompress_datum_slice(const struct varlena *value, int32 slicelength)
                                216                 :                : {
                                217                 :                : #ifndef USE_LZ4
                                218                 :                :     NO_LZ4_SUPPORT();
                                219                 :                :     return NULL;                /* keep compiler quiet */
                                220                 :                : #else
                                221                 :                :     int32       rawsize;
                                222                 :                :     struct varlena *result;
                                223                 :                : 
                                224                 :                :     /* slice decompression not supported prior to 1.8.3 */
                                225         [ -  + ]:              9 :     if (LZ4_versionNumber() < 10803)
 1122 rhaas@postgresql.org      226                 :UBC           0 :         return lz4_decompress_datum(value);
                                227                 :                : 
                                228                 :                :     /* allocate memory for the uncompressed data */
 1122 rhaas@postgresql.org      229                 :CBC           9 :     result = (struct varlena *) palloc(slicelength + VARHDRSZ);
                                230                 :                : 
                                231                 :                :     /* decompress the data */
 1119 tgl@sss.pgh.pa.us         232                 :              9 :     rawsize = LZ4_decompress_safe_partial((char *) value + VARHDRSZ_COMPRESSED,
 1122 rhaas@postgresql.org      233                 :              9 :                                           VARDATA(result),
 1119 tgl@sss.pgh.pa.us         234                 :              9 :                                           VARSIZE(value) - VARHDRSZ_COMPRESSED,
                                235                 :                :                                           slicelength,
                                236                 :                :                                           slicelength);
 1122 rhaas@postgresql.org      237         [ -  + ]:              9 :     if (rawsize < 0)
 1122 rhaas@postgresql.org      238         [ #  # ]:UBC           0 :         ereport(ERROR,
                                239                 :                :                 (errcode(ERRCODE_DATA_CORRUPTED),
                                240                 :                :                  errmsg_internal("compressed lz4 data is corrupt")));
                                241                 :                : 
 1122 rhaas@postgresql.org      242                 :CBC           9 :     SET_VARSIZE(result, rawsize + VARHDRSZ);
                                243                 :                : 
                                244                 :              9 :     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
                                254                 :             81 : toast_get_compression_id(struct varlena *attr)
                                255                 :                : {
 1068 tgl@sss.pgh.pa.us         256                 :             81 :     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                 :                :      */
 1122 rhaas@postgresql.org      263   [ +  +  +  - ]:             81 :     if (VARATT_IS_EXTERNAL_ONDISK(attr))
                                264                 :             12 :     {
                                265                 :                :         struct varatt_external toast_pointer;
                                266                 :                : 
                                267   [ -  +  +  -  :             12 :         VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
                                     +  -  -  +  -  
                                                 + ]
                                268                 :                : 
                                269         [ +  - ]:             12 :         if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer))
 1119 tgl@sss.pgh.pa.us         270                 :             12 :             cmid = VARATT_EXTERNAL_GET_COMPRESS_METHOD(toast_pointer);
                                271                 :                :     }
 1122 rhaas@postgresql.org      272         [ +  + ]:             69 :     else if (VARATT_IS_COMPRESSED(attr))
 1119 tgl@sss.pgh.pa.us         273                 :             66 :         cmid = VARDATA_COMPRESSED_GET_COMPRESS_METHOD(attr);
                                274                 :                : 
 1122 rhaas@postgresql.org      275                 :             81 :     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
 1117                           285                 :             68 : CompressionNameToMethod(const char *compression)
                                286                 :                : {
                                287         [ +  + ]:             68 :     if (strcmp(compression, "pglz") == 0)
                                288                 :             30 :         return TOAST_PGLZ_COMPRESSION;
                                289         [ +  + ]:             38 :     else if (strcmp(compression, "lz4") == 0)
                                290                 :                :     {
                                291                 :                : #ifndef USE_LZ4
                                292                 :                :         NO_LZ4_SUPPORT();
                                293                 :                : #endif
                                294                 :             32 :         return TOAST_LZ4_COMPRESSION;
                                295                 :                :     }
                                296                 :                : 
                                297                 :              6 :     return InvalidCompressionMethod;
                                298                 :                : }
                                299                 :                : 
                                300                 :                : /*
                                301                 :                :  * GetCompressionMethodName - Get compression method name
                                302                 :                :  */
                                303                 :                : const char *
                                304                 :             15 : GetCompressionMethodName(char method)
                                305                 :                : {
                                306      [ +  +  - ]:             15 :     switch (method)
                                307                 :                :     {
                                308                 :              6 :         case TOAST_PGLZ_COMPRESSION:
                                309                 :              6 :             return "pglz";
                                310                 :              9 :         case TOAST_LZ4_COMPRESSION:
                                311                 :              9 :             return "lz4";
 1117 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.1-beta2-3-g6141622