LCOV - differential code coverage report
Current view: top level - src/backend/access/common - toast_compression.c (source / functions) Coverage Total Hit LBC UIC UBC GIC GNC CBC EUB ECB
Current: Differential Code Coverage HEAD vs 15 Lines: 88.9 % 90 80 7 1 2 55 1 24 8 49
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 9 9 9 9
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (180,240] days: 100.0 % 1 1 1
Legend: Lines: hit not hit (240..) days: 88.8 % 89 79 7 1 2 55 24 8 49
Function coverage date bins:
(240..) days: 50.0 % 18 9 9 9

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

Generated by: LCOV version v1.16-55-g56c0a2a