Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1a417dd

Browse files
nikhilveldandaCommitfest Bot
authored and
Commitfest Bot
committed
Design to extend the varattrib_4b/varatt_external format for support of multiple TOAST compression algorithms.
1 parent b006bcd commit 1a417dd

File tree

12 files changed

+189
-78
lines changed

12 files changed

+189
-78
lines changed

contrib/amcheck/verify_heapam.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1786,7 +1786,7 @@ check_tuple_attribute(HeapCheckContext *ctx)
17861786
bool valid = false;
17871787

17881788
/* Compressed attributes should have a valid compression method */
1789-
cmid = TOAST_COMPRESS_METHOD(&toast_pointer);
1789+
cmid = VARATT_EXTERNAL_GET_COMPRESS_METHOD(toast_pointer);
17901790
switch (cmid)
17911791
{
17921792
/* List of all valid compression method IDs */

src/backend/access/brin/brin_tuple.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ brin_form_tuple(BrinDesc *brdesc, BlockNumber blkno, BrinMemTuple *tuple,
223223
{
224224
Datum cvalue;
225225
char compression;
226+
CompressionInfo cmp;
226227
Form_pg_attribute att = TupleDescAttr(brdesc->bd_tupdesc,
227228
keyno);
228229

@@ -237,7 +238,8 @@ brin_form_tuple(BrinDesc *brdesc, BlockNumber blkno, BrinMemTuple *tuple,
237238
else
238239
compression = InvalidCompressionMethod;
239240

240-
cvalue = toast_compress_datum(value, compression);
241+
cmp = setup_cmp_info(compression, att);
242+
cvalue = toast_compress_datum(value, cmp);
241243

242244
if (DatumGetPointer(cvalue) != NULL)
243245
{

src/backend/access/common/detoast.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ toast_decompress_datum(struct varlena *attr)
478478
* Fetch the compression method id stored in the compression header and
479479
* decompress the data using the appropriate decompression routine.
480480
*/
481-
cmid = TOAST_COMPRESS_METHOD(attr);
481+
cmid = VARDATA_COMPRESSED_GET_COMPRESS_METHOD(attr);
482482
switch (cmid)
483483
{
484484
case TOAST_PGLZ_COMPRESSION_ID:
@@ -514,14 +514,14 @@ toast_decompress_datum_slice(struct varlena *attr, int32 slicelength)
514514
* have been seen to give wrong results if passed an output size that is
515515
* more than the data's true decompressed size.
516516
*/
517-
if ((uint32) slicelength >= TOAST_COMPRESS_EXTSIZE(attr))
517+
if ((uint32) slicelength >= VARDATA_COMPRESSED_GET_EXTSIZE(attr))
518518
return toast_decompress_datum(attr);
519519

520520
/*
521521
* Fetch the compression method id stored in the compression header and
522522
* decompress the data slice using the appropriate decompression routine.
523523
*/
524-
cmid = TOAST_COMPRESS_METHOD(attr);
524+
cmid = VARDATA_COMPRESSED_GET_COMPRESS_METHOD(attr);
525525
switch (cmid)
526526
{
527527
case TOAST_PGLZ_COMPRESSION_ID:

src/backend/access/common/indextuple.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,10 @@ index_form_tuple_context(TupleDesc tupleDescriptor,
123123
att->attstorage == TYPSTORAGE_MAIN))
124124
{
125125
Datum cvalue;
126+
CompressionInfo cmp;
126127

127-
cvalue = toast_compress_datum(untoasted_values[i],
128-
att->attcompression);
128+
cmp = setup_cmp_info(att->attcompression, att);
129+
cvalue = toast_compress_datum(untoasted_values[i], cmp);
129130

130131
if (DatumGetPointer(cvalue) != NULL)
131132
{

src/backend/access/common/toast_compression.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "access/toast_compression.h"
2222
#include "common/pg_lzcompress.h"
2323
#include "varatt.h"
24+
#include "utils/attoptcache.h"
2425

2526
/* GUC */
2627
int default_toast_compression = TOAST_PGLZ_COMPRESSION;
@@ -314,3 +315,28 @@ GetCompressionMethodName(char method)
314315
return NULL; /* keep compiler quiet */
315316
}
316317
}
318+
319+
CompressionInfo
320+
setup_cmp_info(char cmethod, Form_pg_attribute att)
321+
{
322+
CompressionInfo info;
323+
324+
/* initialize from the attribute’s default settings */
325+
info.cmethod = cmethod;
326+
info.meta = false;
327+
328+
/* If the compression method is not valid, use the current default */
329+
if (!CompressionMethodIsValid(cmethod))
330+
info.cmethod = default_toast_compression;
331+
332+
switch (info.cmethod)
333+
{
334+
case TOAST_PGLZ_COMPRESSION:
335+
case TOAST_LZ4_COMPRESSION:
336+
break;
337+
default:
338+
elog(ERROR, "invalid compression method %c", info.cmethod);
339+
}
340+
341+
return info;
342+
}

src/backend/access/common/toast_internals.c

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ static bool toastid_valueid_exists(Oid toastrelid, Oid valueid);
4343
* ----------
4444
*/
4545
Datum
46-
toast_compress_datum(Datum value, char cmethod)
46+
toast_compress_datum(Datum value, CompressionInfo cmp)
4747
{
4848
struct varlena *tmp = NULL;
4949
int32 valsize;
@@ -54,14 +54,10 @@ toast_compress_datum(Datum value, char cmethod)
5454

5555
valsize = VARSIZE_ANY_EXHDR(DatumGetPointer(value));
5656

57-
/* If the compression method is not valid, use the current default */
58-
if (!CompressionMethodIsValid(cmethod))
59-
cmethod = default_toast_compression;
60-
6157
/*
6258
* Call appropriate compression routine for the compression method.
6359
*/
64-
switch (cmethod)
60+
switch (cmp.cmethod)
6561
{
6662
case TOAST_PGLZ_COMPRESSION:
6763
tmp = pglz_compress_datum((const struct varlena *) value);
@@ -72,7 +68,7 @@ toast_compress_datum(Datum value, char cmethod)
7268
cmid = TOAST_LZ4_COMPRESSION_ID;
7369
break;
7470
default:
75-
elog(ERROR, "invalid compression method %c", cmethod);
71+
elog(ERROR, "invalid compression method %c", cmp.cmethod);
7672
}
7773

7874
if (tmp == NULL)
@@ -90,9 +86,11 @@ toast_compress_datum(Datum value, char cmethod)
9086
*/
9187
if (VARSIZE(tmp) < valsize - 2)
9288
{
89+
bool meta = cmp.meta;
90+
9391
/* successful compression */
9492
Assert(cmid != TOAST_INVALID_COMPRESSION_ID);
95-
TOAST_COMPRESS_SET_SIZE_AND_COMPRESS_METHOD(tmp, valsize, cmid);
93+
TOAST_COMPRESS_SET_SIZE_AND_COMPRESS_METHOD(tmp, valsize, cmid, meta);
9694
return PointerGetDatum(tmp);
9795
}
9896
else
@@ -143,6 +141,7 @@ toast_save_datum(Relation rel, Datum value,
143141
Pointer dval = DatumGetPointer(value);
144142
int num_indexes;
145143
int validIndex;
144+
ToastCompressionId cm = TOAST_INVALID_COMPRESSION_ID;
146145

147146
Assert(!VARATT_IS_EXTERNAL(value));
148147

@@ -179,14 +178,18 @@ toast_save_datum(Relation rel, Datum value,
179178
}
180179
else if (VARATT_IS_COMPRESSED(dval))
181180
{
181+
bool meta;
182+
182183
data_p = VARDATA(dval);
183184
data_todo = VARSIZE(dval) - VARHDRSZ;
184185
/* rawsize in a compressed datum is just the size of the payload */
185186
toast_pointer.va_rawsize = VARDATA_COMPRESSED_GET_EXTSIZE(dval) + VARHDRSZ;
186-
187+
cm = VARDATA_COMPRESSED_GET_COMPRESS_METHOD(dval);
188+
meta = TOAST_CMPID_EXTENDED(cm) ?
189+
VARATT_4BCE_HAS_META(((varattrib_4b *) (dval))->va_compressed_ext.va_ecinfo) :
190+
false;
187191
/* set external size and compression method */
188-
VARATT_EXTERNAL_SET_SIZE_AND_COMPRESS_METHOD(toast_pointer, data_todo,
189-
VARDATA_COMPRESSED_GET_COMPRESS_METHOD(dval));
192+
VARATT_EXTERNAL_SET_SIZE_AND_COMPRESS_METHOD(toast_pointer, data_todo, cm, meta);
190193
/* Assert that the numbers look like it's compressed */
191194
Assert(VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer));
192195
}
@@ -368,9 +371,9 @@ toast_save_datum(Relation rel, Datum value,
368371
/*
369372
* Create the TOAST pointer value that we'll return
370373
*/
371-
result = (struct varlena *) palloc(TOAST_POINTER_SIZE);
374+
result = (struct varlena *) palloc(TOAST_CMPID_EXTENDED(cm) ? TOAST_POINTER_EXT_SIZE : TOAST_POINTER_NOEXT_SIZE);
372375
SET_VARTAG_EXTERNAL(result, VARTAG_ONDISK);
373-
memcpy(VARDATA_EXTERNAL(result), &toast_pointer, sizeof(toast_pointer));
376+
memcpy(VARDATA_EXTERNAL(result), &toast_pointer, TOAST_CMPID_EXTENDED(cm) ? TOAST_POINTER_EXT_SIZE - VARHDRSZ_EXTERNAL : TOAST_POINTER_NOEXT_SIZE - VARHDRSZ_EXTERNAL);
374377

375378
return PointerGetDatum(result);
376379
}

src/backend/access/table/toast_helper.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ toast_tuple_init(ToastTupleContext *ttc)
171171
* The column must have attstorage EXTERNAL or EXTENDED if check_main is
172172
* false, and must have attstorage MAIN if check_main is true.
173173
*
174-
* The column must have a minimum size of MAXALIGN(TOAST_POINTER_SIZE);
174+
* The column must have a minimum size of MAXALIGN(TOAST_POINTER_NOEXT_SIZE);
175175
* if not, no benefit is to be expected by compressing it.
176176
*
177177
* The return value is the index of the biggest suitable column, or
@@ -184,7 +184,7 @@ toast_tuple_find_biggest_attribute(ToastTupleContext *ttc,
184184
TupleDesc tupleDesc = ttc->ttc_rel->rd_att;
185185
int numAttrs = tupleDesc->natts;
186186
int biggest_attno = -1;
187-
int32 biggest_size = MAXALIGN(TOAST_POINTER_SIZE);
187+
int32 biggest_size = MAXALIGN(TOAST_POINTER_NOEXT_SIZE);
188188
int32 skip_colflags = TOASTCOL_IGNORE;
189189
int i;
190190

@@ -229,8 +229,10 @@ toast_tuple_try_compression(ToastTupleContext *ttc, int attribute)
229229
Datum *value = &ttc->ttc_values[attribute];
230230
Datum new_value;
231231
ToastAttrInfo *attr = &ttc->ttc_attr[attribute];
232+
Form_pg_attribute att = TupleDescAttr(ttc->ttc_rel->rd_att, attribute);
233+
CompressionInfo cmp = setup_cmp_info(attr->tai_compression, att);
232234

233-
new_value = toast_compress_datum(*value, attr->tai_compression);
235+
new_value = toast_compress_datum(*value, cmp);
234236

235237
if (DatumGetPointer(new_value) != NULL)
236238
{

src/include/access/detoast.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@
2323
do { \
2424
varattrib_1b_e *attre = (varattrib_1b_e *) (attr); \
2525
Assert(VARATT_IS_EXTERNAL(attre)); \
26-
Assert(VARSIZE_EXTERNAL(attre) == sizeof(toast_pointer) + VARHDRSZ_EXTERNAL); \
27-
memcpy(&(toast_pointer), VARDATA_EXTERNAL(attre), sizeof(toast_pointer)); \
26+
memset(&(toast_pointer), 0, sizeof(toast_pointer)); \
27+
memcpy(&(toast_pointer), VARDATA_EXTERNAL(attre), VARSIZE_EXTERNAL(attre) - VARHDRSZ_EXTERNAL); \
2828
} while (0)
2929

3030
/* Size of an EXTERNAL datum that contains a standard TOAST pointer */
31-
#define TOAST_POINTER_SIZE (VARHDRSZ_EXTERNAL + sizeof(varatt_external))
31+
#define TOAST_POINTER_NOEXT_SIZE (VARHDRSZ_EXTERNAL + offsetof(varatt_external, extended))
32+
#define TOAST_POINTER_EXT_SIZE (TOAST_POINTER_NOEXT_SIZE + MEMBER_SIZE(varatt_external, extended.cmp))
3233

3334
/* Size of an EXTERNAL datum that contains an indirection pointer */
3435
#define INDIRECT_POINTER_SIZE (VARHDRSZ_EXTERNAL + sizeof(varatt_indirect))

src/include/access/toast_compression.h

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#ifndef TOAST_COMPRESSION_H
1414
#define TOAST_COMPRESSION_H
1515

16+
#include "catalog/pg_attribute.h"
17+
1618
/*
1719
* GUC support.
1820
*
@@ -22,25 +24,19 @@
2224
*/
2325
extern PGDLLIMPORT int default_toast_compression;
2426

25-
/*
26-
* Built-in compression method ID. The toast compression header will store
27-
* this in the first 2 bits of the raw length. These built-in compression
28-
* method IDs are directly mapped to the built-in compression methods.
29-
*
30-
* Don't use these values for anything other than understanding the meaning
31-
* of the raw bits from a varlena; in particular, if the goal is to identify
32-
* a compression method, use the constants TOAST_PGLZ_COMPRESSION, etc.
33-
* below. We might someday support more than 4 compression methods, but
34-
* we can never have more than 4 values in this enum, because there are
35-
* only 2 bits available in the places where this is stored.
36-
*/
3727
typedef enum ToastCompressionId
3828
{
3929
TOAST_PGLZ_COMPRESSION_ID = 0,
4030
TOAST_LZ4_COMPRESSION_ID = 1,
4131
TOAST_INVALID_COMPRESSION_ID = 2,
4232
} ToastCompressionId;
4333

34+
typedef struct CompressionInfo
35+
{
36+
char cmethod;
37+
bool meta;
38+
} CompressionInfo;
39+
4440
/*
4541
* Built-in compression methods. pg_attribute will store these in the
4642
* attcompression column. In attcompression, InvalidCompressionMethod
@@ -51,6 +47,7 @@ typedef enum ToastCompressionId
5147
#define InvalidCompressionMethod '\0'
5248

5349
#define CompressionMethodIsValid(cm) ((cm) != InvalidCompressionMethod)
50+
#define TOAST_CMPID_EXTENDED(cmpid) (!(cmpid == TOAST_PGLZ_COMPRESSION_ID || cmpid == TOAST_LZ4_COMPRESSION_ID ||cmpid == TOAST_INVALID_COMPRESSION_ID))
5451

5552

5653
/* pglz compression/decompression routines */
@@ -69,5 +66,6 @@ extern struct varlena *lz4_decompress_datum_slice(const struct varlena *value,
6966
extern ToastCompressionId toast_get_compression_id(struct varlena *attr);
7067
extern char CompressionNameToMethod(const char *compression);
7168
extern const char *GetCompressionMethodName(char method);
69+
extern CompressionInfo setup_cmp_info(char cmethod, Form_pg_attribute att);
7270

7371
#endif /* TOAST_COMPRESSION_H */

src/include/access/toast_internals.h

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,31 @@
1717
#include "utils/relcache.h"
1818
#include "utils/snapshot.h"
1919

20-
/*
21-
* The information at the start of the compressed toast data.
22-
*/
23-
typedef struct toast_compress_header
24-
{
25-
int32 vl_len_; /* varlena header (do not touch directly!) */
26-
uint32 tcinfo; /* 2 bits for compression method and 30 bits
27-
* external size; see va_extinfo */
28-
} toast_compress_header;
29-
3020
/*
3121
* Utilities for manipulation of header information for compressed
3222
* toast entries.
3323
*/
34-
#define TOAST_COMPRESS_EXTSIZE(ptr) \
35-
(((toast_compress_header *) (ptr))->tcinfo & VARLENA_EXTSIZE_MASK)
36-
#define TOAST_COMPRESS_METHOD(ptr) \
37-
(((toast_compress_header *) (ptr))->tcinfo >> VARLENA_EXTSIZE_BITS)
38-
39-
#define TOAST_COMPRESS_SET_SIZE_AND_COMPRESS_METHOD(ptr, len, cm_method) \
40-
do { \
41-
Assert((len) > 0 && (len) <= VARLENA_EXTSIZE_MASK); \
42-
Assert((cm_method) == TOAST_PGLZ_COMPRESSION_ID || \
43-
(cm_method) == TOAST_LZ4_COMPRESSION_ID); \
44-
((toast_compress_header *) (ptr))->tcinfo = \
45-
(len) | ((uint32) (cm_method) << VARLENA_EXTSIZE_BITS); \
24+
#define TOAST_COMPRESS_SET_SIZE_AND_COMPRESS_METHOD(ptr, len, cm_method, meta) \
25+
do { \
26+
Assert((len) > 0 && (len) <= VARLENA_EXTSIZE_MASK); \
27+
Assert((cm_method) == TOAST_PGLZ_COMPRESSION_ID || \
28+
(cm_method) == TOAST_LZ4_COMPRESSION_ID); \
29+
if (!TOAST_CMPID_EXTENDED((cm_method))) \
30+
{ \
31+
((varattrib_4b *)(ptr))->va_compressed.va_tcinfo = \
32+
((uint32)(len)) | ((uint32)(cm_method) << VARLENA_EXTSIZE_BITS); \
33+
} \
34+
else \
35+
{ \
36+
/* extended path: mark EXT flag in tcinfo */ \
37+
((varattrib_4b *)(ptr))->va_compressed_ext.va_tcinfo = \
38+
((uint32)(len)) | ((uint32)(VARATT_4BCE_EXTFLAG) << VARLENA_EXTSIZE_BITS); \
39+
((varattrib_4b *)(ptr))->va_compressed_ext.va_ecinfo = \
40+
VARATT_4BCE_ENCODE((meta), (cm_method)); \
41+
} \
4642
} while (0)
4743

48-
extern Datum toast_compress_datum(Datum value, char cmethod);
44+
extern Datum toast_compress_datum(Datum value, CompressionInfo cmp);
4945
extern Oid toast_get_valid_index(Oid toastoid, LOCKMODE lock);
5046

5147
extern void toast_delete_datum(Relation rel, Datum value, bool is_speculative);

0 commit comments

Comments
 (0)