mirror of
https://github.com/postgres/postgres.git
synced 2025-07-08 11:42:09 +03:00
Move pg_lzcompress.c to src/common.
The meta data of PGLZ symbolized by PGLZ_Header is removed, to make the compression and decompression code independent on the backend-only varlena facility. PGLZ_Header is being used to store some meta data related to the data being compressed like the raw length of the uncompressed record or some varlena-related data, making it unpluggable once PGLZ is stored in src/common as it contains some backend-only code paths with the management of varlena structures. The APIs of PGLZ are reworked at the same time to do only compression and decompression of buffers without the meta-data layer, simplifying its use for a more general usage. On-disk format is preserved as well, so there is no incompatibility with previous major versions of PostgreSQL for TOAST entries. Exposing compression and decompression APIs of pglz makes possible its use by extensions and contrib modules. Especially this commit is required for upcoming WAL compression feature so that the WAL reader facility can decompress the WAL data by using pglz_decompress. Michael Paquier, reviewed by me.
This commit is contained in:
@ -35,9 +35,9 @@
|
||||
#include "access/tuptoaster.h"
|
||||
#include "access/xact.h"
|
||||
#include "catalog/catalog.h"
|
||||
#include "common/pg_lzcompress.h"
|
||||
#include "miscadmin.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/pg_lzcompress.h"
|
||||
#include "utils/rel.h"
|
||||
#include "utils/typcache.h"
|
||||
#include "utils/tqual.h"
|
||||
@ -45,6 +45,26 @@
|
||||
|
||||
#undef TOAST_DEBUG
|
||||
|
||||
/*
|
||||
* The information at the start of the compressed toast data.
|
||||
*/
|
||||
typedef struct toast_compress_header
|
||||
{
|
||||
int32 vl_len_; /* varlena header (do not touch directly!) */
|
||||
int32 rawsize;
|
||||
} toast_compress_header;
|
||||
|
||||
/*
|
||||
* Utilities for manipulation of header information for compressed
|
||||
* toast entries.
|
||||
*/
|
||||
#define TOAST_COMPRESS_HDRSZ ((int32) sizeof(toast_compress_header))
|
||||
#define TOAST_COMPRESS_RAWSIZE(ptr) (((toast_compress_header *) ptr)->rawsize)
|
||||
#define TOAST_COMPRESS_RAWDATA(ptr) \
|
||||
(((char *) ptr) + TOAST_COMPRESS_HDRSZ)
|
||||
#define TOAST_COMPRESS_SET_RAWSIZE(ptr, len) \
|
||||
(((toast_compress_header *) ptr)->rawsize = len)
|
||||
|
||||
static void toast_delete_datum(Relation rel, Datum value);
|
||||
static Datum toast_save_datum(Relation rel, Datum value,
|
||||
struct varlena * oldexternal, int options);
|
||||
@ -53,6 +73,7 @@ static bool toastid_valueid_exists(Oid toastrelid, Oid valueid);
|
||||
static struct varlena *toast_fetch_datum(struct varlena * attr);
|
||||
static struct varlena *toast_fetch_datum_slice(struct varlena * attr,
|
||||
int32 sliceoffset, int32 length);
|
||||
static struct varlena *toast_decompress_datum(struct varlena * attr);
|
||||
static int toast_open_indexes(Relation toastrel,
|
||||
LOCKMODE lock,
|
||||
Relation **toastidxs,
|
||||
@ -138,11 +159,8 @@ heap_tuple_untoast_attr(struct varlena * attr)
|
||||
/* If it's compressed, decompress it */
|
||||
if (VARATT_IS_COMPRESSED(attr))
|
||||
{
|
||||
PGLZ_Header *tmp = (PGLZ_Header *) attr;
|
||||
|
||||
attr = (struct varlena *) palloc(PGLZ_RAW_SIZE(tmp) + VARHDRSZ);
|
||||
SET_VARSIZE(attr, PGLZ_RAW_SIZE(tmp) + VARHDRSZ);
|
||||
pglz_decompress(tmp, VARDATA(attr));
|
||||
struct varlena *tmp = attr;
|
||||
attr = toast_decompress_datum(tmp);
|
||||
pfree(tmp);
|
||||
}
|
||||
}
|
||||
@ -163,11 +181,7 @@ heap_tuple_untoast_attr(struct varlena * attr)
|
||||
/*
|
||||
* This is a compressed value inside of the main tuple
|
||||
*/
|
||||
PGLZ_Header *tmp = (PGLZ_Header *) attr;
|
||||
|
||||
attr = (struct varlena *) palloc(PGLZ_RAW_SIZE(tmp) + VARHDRSZ);
|
||||
SET_VARSIZE(attr, PGLZ_RAW_SIZE(tmp) + VARHDRSZ);
|
||||
pglz_decompress(tmp, VARDATA(attr));
|
||||
attr = toast_decompress_datum(attr);
|
||||
}
|
||||
else if (VARATT_IS_SHORT(attr))
|
||||
{
|
||||
@ -234,14 +248,10 @@ heap_tuple_untoast_attr_slice(struct varlena * attr,
|
||||
|
||||
if (VARATT_IS_COMPRESSED(preslice))
|
||||
{
|
||||
PGLZ_Header *tmp = (PGLZ_Header *) preslice;
|
||||
Size size = PGLZ_RAW_SIZE(tmp) + VARHDRSZ;
|
||||
struct varlena *tmp = preslice;
|
||||
preslice = toast_decompress_datum(tmp);
|
||||
|
||||
preslice = (struct varlena *) palloc(size);
|
||||
SET_VARSIZE(preslice, size);
|
||||
pglz_decompress(tmp, VARDATA(preslice));
|
||||
|
||||
if (tmp != (PGLZ_Header *) attr)
|
||||
if (tmp != attr)
|
||||
pfree(tmp);
|
||||
}
|
||||
|
||||
@ -1228,6 +1238,7 @@ toast_compress_datum(Datum value)
|
||||
{
|
||||
struct varlena *tmp;
|
||||
int32 valsize = VARSIZE_ANY_EXHDR(DatumGetPointer(value));
|
||||
int32 len;
|
||||
|
||||
Assert(!VARATT_IS_EXTERNAL(DatumGetPointer(value)));
|
||||
Assert(!VARATT_IS_COMPRESSED(DatumGetPointer(value)));
|
||||
@ -1240,7 +1251,8 @@ toast_compress_datum(Datum value)
|
||||
valsize > PGLZ_strategy_default->max_input_size)
|
||||
return PointerGetDatum(NULL);
|
||||
|
||||
tmp = (struct varlena *) palloc(PGLZ_MAX_OUTPUT(valsize));
|
||||
tmp = (struct varlena *) palloc(PGLZ_MAX_OUTPUT(valsize) +
|
||||
TOAST_COMPRESS_HDRSZ);
|
||||
|
||||
/*
|
||||
* We recheck the actual size even if pglz_compress() reports success,
|
||||
@ -1252,10 +1264,15 @@ toast_compress_datum(Datum value)
|
||||
* only one header byte and no padding if the value is short enough. So
|
||||
* we insist on a savings of more than 2 bytes to ensure we have a gain.
|
||||
*/
|
||||
if (pglz_compress(VARDATA_ANY(DatumGetPointer(value)), valsize,
|
||||
(PGLZ_Header *) tmp, PGLZ_strategy_default) &&
|
||||
VARSIZE(tmp) < valsize - 2)
|
||||
len = pglz_compress(VARDATA_ANY(DatumGetPointer(value)),
|
||||
valsize,
|
||||
TOAST_COMPRESS_RAWDATA(tmp),
|
||||
PGLZ_strategy_default);
|
||||
if (len >= 0 &&
|
||||
len + TOAST_COMPRESS_HDRSZ < valsize - 2)
|
||||
{
|
||||
TOAST_COMPRESS_SET_RAWSIZE(tmp, valsize);
|
||||
SET_VARSIZE_COMPRESSED(tmp, len + TOAST_COMPRESS_HDRSZ);
|
||||
/* successful compression */
|
||||
return PointerGetDatum(tmp);
|
||||
}
|
||||
@ -2100,6 +2117,32 @@ toast_fetch_datum_slice(struct varlena * attr, int32 sliceoffset, int32 length)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ----------
|
||||
* toast_decompress_datum -
|
||||
*
|
||||
* Decompress a compressed version of a varlena datum
|
||||
*/
|
||||
static struct varlena *
|
||||
toast_decompress_datum(struct varlena * attr)
|
||||
{
|
||||
struct varlena *result;
|
||||
|
||||
Assert(VARATT_IS_COMPRESSED(attr));
|
||||
|
||||
result = (struct varlena *)
|
||||
palloc(TOAST_COMPRESS_RAWSIZE(attr) + VARHDRSZ);
|
||||
SET_VARSIZE(result, TOAST_COMPRESS_RAWSIZE(attr) + VARHDRSZ);
|
||||
|
||||
if (pglz_decompress(TOAST_COMPRESS_RAWDATA(attr),
|
||||
VARSIZE(attr) - TOAST_COMPRESS_HDRSZ,
|
||||
VARDATA(result),
|
||||
TOAST_COMPRESS_RAWSIZE(attr)) < 0)
|
||||
elog(ERROR, "compressed data is corrupted");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* ----------
|
||||
* toast_open_indexes
|
||||
*
|
||||
|
Reference in New Issue
Block a user