From 55ca2b6123cb4dd7820b39ae4ef3bacfb00df81c Mon Sep 17 00:00:00 2001 From: Tomas Vondra Date: Wed, 1 Oct 2025 01:34:12 +0200 Subject: [PATCH v20251001 22/25] experimental: zlib (gzip?) compression --- src/backend/storage/file/buffile.c | 50 +++++++++++++++++++++++++++++ src/backend/utils/misc/guc_tables.c | 3 ++ src/include/storage/buffile.h | 3 +- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/backend/storage/file/buffile.c b/src/backend/storage/file/buffile.c index e3d4e2a342e..380537fb126 100644 --- a/src/backend/storage/file/buffile.c +++ b/src/backend/storage/file/buffile.c @@ -60,10 +60,15 @@ #include #endif +#ifdef HAVE_LIBZ +#include +#endif + /* Compression types */ #define TEMP_NONE_COMPRESSION 0 #define TEMP_PGLZ_COMPRESSION 1 #define TEMP_LZ4_COMPRESSION 2 +#define TEMP_GZIP_COMPRESSION 3 /* * We break BufFiles into gigabyte-sized segments, regardless of RELSEG_SIZE. @@ -294,6 +299,15 @@ BufFileCreateCompressTemp(bool interXact) size = LZ4_compressBound(BLCKSZ) + sizeof(CompressHeader); #endif break; + + case TEMP_GZIP_COMPRESSION: + { +#ifdef HAVE_LIBZ + size = compressBound(BLCKSZ) + sizeof(CompressHeader); +#endif + break; + } + case TEMP_PGLZ_COMPRESSION: size = pglz_maximum_compressed_size(BLCKSZ, BLCKSZ) + sizeof(CompressHeader); break; @@ -689,6 +703,20 @@ BufFileLoadBuffer(BufFile *file) #endif break; + case TEMP_GZIP_COMPRESSION: +#ifdef HAVE_LIBZ + int ret; + size_t len = sizeof(file->buffer); + + ret = uncompress((uint8 *) file->buffer.data, &len, + (uint8 *) buff, header.len); + if (ret != Z_OK) + elog(ERROR, "uncompress failed"); + + file->nbytes = len; +#endif + break; + case TEMP_PGLZ_COMPRESSION: file->nbytes = pglz_decompress(buff, header.len, file->buffer.data, header.raw_len, false); @@ -785,6 +813,28 @@ BufFileDumpBuffer(BufFile *file) errmsg_internal("compression failed, compressed size %d, original size %d", cSize, nbytesOriginal))); } +#endif + break; + } + case TEMP_GZIP_COMPRESSION: + { +#ifdef HAVE_LIBZ + int ret; + size_t len = compressBound(file->nbytes); + + /* XXX maybe lower level? the default is pretty slow ... */ + ret = compress2((uint8 *) (cData + sizeof(CompressHeader)), &len, + (uint8 *) file->buffer.data, file->nbytes, + Z_DEFAULT_COMPRESSION); + if (ret != Z_OK) + { + ereport(ERROR, + (errcode(ERRCODE_DATA_CORRUPTED), + errmsg_internal("compression failed, compressed size %d, original size %d", + cSize, nbytesOriginal))); + } + + cSize = len; #endif break; } diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c index 2fb3891b730..88fbe405d59 100644 --- a/src/backend/utils/misc/guc_tables.c +++ b/src/backend/utils/misc/guc_tables.c @@ -473,6 +473,9 @@ static const struct config_enum_entry temp_file_compression_options[] = { {"pglz", TEMP_PGLZ_COMPRESSION, false}, #ifdef USE_LZ4 {"lz4", TEMP_LZ4_COMPRESSION, false}, +#endif +#ifdef HAVE_LIBZ + {"gzip", TEMP_GZIP_COMPRESSION, false}, #endif {NULL, 0, false} }; diff --git a/src/include/storage/buffile.h b/src/include/storage/buffile.h index 49594f1948e..7a1bb1d6085 100644 --- a/src/include/storage/buffile.h +++ b/src/include/storage/buffile.h @@ -36,7 +36,8 @@ typedef enum { TEMP_NONE_COMPRESSION, TEMP_PGLZ_COMPRESSION, - TEMP_LZ4_COMPRESSION + TEMP_LZ4_COMPRESSION, + TEMP_GZIP_COMPRESSION } TempCompression; extern PGDLLIMPORT int temp_file_compression; -- 2.51.0