Skip to content

Commit aeb1631

Browse files
committed
Mostly-cosmetic adjustments of TOAST-related macros.
The authors of bbe0a81 hadn't quite got the idea that macros named like SOMETHING_4B_C were only meant for internal endianness-related details in postgres.h. Choose more legible names for macros that are intended to be used elsewhere. Rearrange postgres.h a bit to clarify the separation between those internal macros and ones intended for wider use. Also, avoid using the term "rawsize" for true decompressed size; we've used "extsize" for that, because "rawsize" generally denotes total Datum size including header. This choice seemed particularly unfortunate in tests that were comparing one of these meanings to the other. This patch includes a couple of not-purely-cosmetic changes: be sure that the shifts aligning compression methods are unsigned (not critical today, but will be when compression method 2 exists), and fix broken definition of VARATT_EXTERNAL_GET_COMPRESSION (now VARATT_EXTERNAL_GET_COMPRESS_METHOD), whose callers worked only accidentally. Discussion: https://postgr.es/m/[email protected]
1 parent 2c75f8a commit aeb1631

File tree

5 files changed

+87
-84
lines changed

5 files changed

+87
-84
lines changed

src/backend/access/common/detoast.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ detoast_attr_slice(struct varlena *attr,
251251
* determine how much compressed data we need to be sure of being
252252
* able to decompress the required slice.
253253
*/
254-
if (VARATT_EXTERNAL_GET_COMPRESSION(toast_pointer) ==
254+
if (VARATT_EXTERNAL_GET_COMPRESS_METHOD(toast_pointer) ==
255255
TOAST_PGLZ_COMPRESSION_ID)
256256
max_size = pglz_maximum_compressed_size(slicelimit, max_size);
257257

@@ -562,7 +562,7 @@ toast_raw_datum_size(Datum value)
562562
else if (VARATT_IS_COMPRESSED(attr))
563563
{
564564
/* here, va_rawsize is just the payload size */
565-
result = VARRAWSIZE_4B_C(attr) + VARHDRSZ;
565+
result = VARDATA_COMPRESSED_GET_EXTSIZE(attr) + VARHDRSZ;
566566
}
567567
else if (VARATT_IS_SHORT(attr))
568568
{

src/backend/access/common/toast_compression.c

+20-20
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,19 @@ pglz_compress_datum(const struct varlena *value)
5353
* that will be needed for varlena overhead, and allocate that amount.
5454
*/
5555
tmp = (struct varlena *) palloc(PGLZ_MAX_OUTPUT(valsize) +
56-
VARHDRSZ_COMPRESS);
56+
VARHDRSZ_COMPRESSED);
5757

5858
len = pglz_compress(VARDATA_ANY(value),
5959
valsize,
60-
(char *) tmp + VARHDRSZ_COMPRESS,
60+
(char *) tmp + VARHDRSZ_COMPRESSED,
6161
NULL);
6262
if (len < 0)
6363
{
6464
pfree(tmp);
6565
return NULL;
6666
}
6767

68-
SET_VARSIZE_COMPRESSED(tmp, len + VARHDRSZ_COMPRESS);
68+
SET_VARSIZE_COMPRESSED(tmp, len + VARHDRSZ_COMPRESSED);
6969

7070
return tmp;
7171
}
@@ -80,13 +80,13 @@ pglz_decompress_datum(const struct varlena *value)
8080
int32 rawsize;
8181

8282
/* allocate memory for the uncompressed data */
83-
result = (struct varlena *) palloc(VARRAWSIZE_4B_C(value) + VARHDRSZ);
83+
result = (struct varlena *) palloc(VARDATA_COMPRESSED_GET_EXTSIZE(value) + VARHDRSZ);
8484

8585
/* decompress the data */
86-
rawsize = pglz_decompress((char *) value + VARHDRSZ_COMPRESS,
87-
VARSIZE(value) - VARHDRSZ_COMPRESS,
86+
rawsize = pglz_decompress((char *) value + VARHDRSZ_COMPRESSED,
87+
VARSIZE(value) - VARHDRSZ_COMPRESSED,
8888
VARDATA(result),
89-
VARRAWSIZE_4B_C(value), true);
89+
VARDATA_COMPRESSED_GET_EXTSIZE(value), true);
9090
if (rawsize < 0)
9191
ereport(ERROR,
9292
(errcode(ERRCODE_DATA_CORRUPTED),
@@ -111,8 +111,8 @@ pglz_decompress_datum_slice(const struct varlena *value,
111111
result = (struct varlena *) palloc(slicelength + VARHDRSZ);
112112

113113
/* decompress the data */
114-
rawsize = pglz_decompress((char *) value + VARHDRSZ_COMPRESS,
115-
VARSIZE(value) - VARHDRSZ_COMPRESS,
114+
rawsize = pglz_decompress((char *) value + VARHDRSZ_COMPRESSED,
115+
VARSIZE(value) - VARHDRSZ_COMPRESSED,
116116
VARDATA(result),
117117
slicelength, false);
118118
if (rawsize < 0)
@@ -149,10 +149,10 @@ lz4_compress_datum(const struct varlena *value)
149149
* that will be needed for varlena overhead, and allocate that amount.
150150
*/
151151
max_size = LZ4_compressBound(valsize);
152-
tmp = (struct varlena *) palloc(max_size + VARHDRSZ_COMPRESS);
152+
tmp = (struct varlena *) palloc(max_size + VARHDRSZ_COMPRESSED);
153153

154154
len = LZ4_compress_default(VARDATA_ANY(value),
155-
(char *) tmp + VARHDRSZ_COMPRESS,
155+
(char *) tmp + VARHDRSZ_COMPRESSED,
156156
valsize, max_size);
157157
if (len <= 0)
158158
elog(ERROR, "lz4 compression failed");
@@ -164,7 +164,7 @@ lz4_compress_datum(const struct varlena *value)
164164
return NULL;
165165
}
166166

167-
SET_VARSIZE_COMPRESSED(tmp, len + VARHDRSZ_COMPRESS);
167+
SET_VARSIZE_COMPRESSED(tmp, len + VARHDRSZ_COMPRESSED);
168168

169169
return tmp;
170170
#endif
@@ -184,13 +184,13 @@ lz4_decompress_datum(const struct varlena *value)
184184
struct varlena *result;
185185

186186
/* allocate memory for the uncompressed data */
187-
result = (struct varlena *) palloc(VARRAWSIZE_4B_C(value) + VARHDRSZ);
187+
result = (struct varlena *) palloc(VARDATA_COMPRESSED_GET_EXTSIZE(value) + VARHDRSZ);
188188

189189
/* decompress the data */
190-
rawsize = LZ4_decompress_safe((char *) value + VARHDRSZ_COMPRESS,
190+
rawsize = LZ4_decompress_safe((char *) value + VARHDRSZ_COMPRESSED,
191191
VARDATA(result),
192-
VARSIZE(value) - VARHDRSZ_COMPRESS,
193-
VARRAWSIZE_4B_C(value));
192+
VARSIZE(value) - VARHDRSZ_COMPRESSED,
193+
VARDATA_COMPRESSED_GET_EXTSIZE(value));
194194
if (rawsize < 0)
195195
ereport(ERROR,
196196
(errcode(ERRCODE_DATA_CORRUPTED),
@@ -224,9 +224,9 @@ lz4_decompress_datum_slice(const struct varlena *value, int32 slicelength)
224224
result = (struct varlena *) palloc(slicelength + VARHDRSZ);
225225

226226
/* decompress the data */
227-
rawsize = LZ4_decompress_safe_partial((char *) value + VARHDRSZ_COMPRESS,
227+
rawsize = LZ4_decompress_safe_partial((char *) value + VARHDRSZ_COMPRESSED,
228228
VARDATA(result),
229-
VARSIZE(value) - VARHDRSZ_COMPRESS,
229+
VARSIZE(value) - VARHDRSZ_COMPRESSED,
230230
slicelength,
231231
slicelength);
232232
if (rawsize < 0)
@@ -262,10 +262,10 @@ toast_get_compression_id(struct varlena *attr)
262262
VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
263263

264264
if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer))
265-
cmid = VARATT_EXTERNAL_GET_COMPRESSION(toast_pointer);
265+
cmid = VARATT_EXTERNAL_GET_COMPRESS_METHOD(toast_pointer);
266266
}
267267
else if (VARATT_IS_COMPRESSED(attr))
268-
cmid = VARCOMPRESS_4B_C(attr);
268+
cmid = VARDATA_COMPRESSED_GET_COMPRESS_METHOD(attr);
269269

270270
return cmid;
271271
}

src/backend/access/common/toast_internals.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ toast_compress_datum(Datum value, char cmethod)
9191
{
9292
/* successful compression */
9393
Assert(cmid != TOAST_INVALID_COMPRESSION_ID);
94-
TOAST_COMPRESS_SET_SIZE_AND_METHOD(tmp, valsize, cmid);
94+
TOAST_COMPRESS_SET_SIZE_AND_COMPRESS_METHOD(tmp, valsize, cmid);
9595
return PointerGetDatum(tmp);
9696
}
9797
else
@@ -181,11 +181,11 @@ toast_save_datum(Relation rel, Datum value,
181181
data_p = VARDATA(dval);
182182
data_todo = VARSIZE(dval) - VARHDRSZ;
183183
/* rawsize in a compressed datum is just the size of the payload */
184-
toast_pointer.va_rawsize = VARRAWSIZE_4B_C(dval) + VARHDRSZ;
184+
toast_pointer.va_rawsize = VARDATA_COMPRESSED_GET_EXTSIZE(dval) + VARHDRSZ;
185185

186186
/* set external size and compression method */
187-
VARATT_EXTERNAL_SET_SIZE_AND_COMPRESSION(toast_pointer, data_todo,
188-
VARCOMPRESS_4B_C(dval));
187+
VARATT_EXTERNAL_SET_SIZE_AND_COMPRESS_METHOD(toast_pointer, data_todo,
188+
VARDATA_COMPRESSED_GET_COMPRESS_METHOD(dval));
189189
/* Assert that the numbers look like it's compressed */
190190
Assert(VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer));
191191
}

src/include/access/toast_internals.h

+7-6
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,23 @@ typedef struct toast_compress_header
2424
{
2525
int32 vl_len_; /* varlena header (do not touch directly!) */
2626
uint32 tcinfo; /* 2 bits for compression method and 30 bits
27-
* rawsize */
27+
* external size; see va_extinfo */
2828
} toast_compress_header;
2929

3030
/*
3131
* Utilities for manipulation of header information for compressed
3232
* toast entries.
3333
*/
34-
#define TOAST_COMPRESS_METHOD(ptr) \
35-
(((toast_compress_header *) (ptr))->tcinfo >> VARLENA_RAWSIZE_BITS)
36-
#define TOAST_COMPRESS_SET_SIZE_AND_METHOD(ptr, len, cm_method) \
34+
#define TOAST_COMPRESS_METHOD(ptr) \
35+
(((toast_compress_header *) (ptr))->tcinfo >> VARLENA_EXTSIZE_BITS)
36+
37+
#define TOAST_COMPRESS_SET_SIZE_AND_COMPRESS_METHOD(ptr, len, cm_method) \
3738
do { \
38-
Assert((len) > 0 && (len) <= VARLENA_RAWSIZE_MASK); \
39+
Assert((len) > 0 && (len) <= VARLENA_EXTSIZE_MASK); \
3940
Assert((cm_method) == TOAST_PGLZ_COMPRESSION_ID || \
4041
(cm_method) == TOAST_LZ4_COMPRESSION_ID); \
4142
((toast_compress_header *) (ptr))->tcinfo = \
42-
((len) | (cm_method) << VARLENA_RAWSIZE_BITS); \
43+
(len) | ((uint32) (cm_method) << VARLENA_EXTSIZE_BITS); \
4344
} while (0)
4445

4546
extern Datum toast_compress_datum(Datum value, char cmethod);

src/include/postgres.h

+54-52
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@
5555
/*
5656
* struct varatt_external is a traditional "TOAST pointer", that is, the
5757
* information needed to fetch a Datum stored out-of-line in a TOAST table.
58-
* The data is compressed if and only if the size stored in va_extinfo <
59-
* va_rawsize - VARHDRSZ.
58+
* The data is compressed if and only if the external size stored in
59+
* va_extinfo is less than va_rawsize - VARHDRSZ.
6060
*
6161
* This struct must not contain any padding, because we sometimes compare
6262
* these pointers using memcmp.
@@ -75,6 +75,13 @@ typedef struct varatt_external
7575
Oid va_toastrelid; /* RelID of TOAST table containing it */
7676
} varatt_external;
7777

78+
/*
79+
* These macros define the "saved size" portion of va_extinfo. Its remaining
80+
* two high-order bits identify the compression method.
81+
*/
82+
#define VARLENA_EXTSIZE_BITS 30
83+
#define VARLENA_EXTSIZE_MASK ((1U << VARLENA_EXTSIZE_BITS) - 1)
84+
7885
/*
7986
* struct varatt_indirect is a "TOAST pointer" representing an out-of-line
8087
* Datum that's stored in memory, not in an external toast relation.
@@ -149,7 +156,7 @@ typedef union
149156
{
150157
uint32 va_header;
151158
uint32 va_tcinfo; /* Original data size (excludes header) and
152-
* compression method */
159+
* compression method; see va_extinfo */
153160
char va_data[FLEXIBLE_ARRAY_MEMBER]; /* Compressed data */
154161
} va_compressed;
155162
} varattrib_4b;
@@ -235,6 +242,7 @@ typedef struct
235242
#define SET_VARTAG_1B_E(PTR,tag) \
236243
(((varattrib_1b_e *) (PTR))->va_header = 0x80, \
237244
((varattrib_1b_e *) (PTR))->va_tag = (tag))
245+
238246
#else /* !WORDS_BIGENDIAN */
239247

240248
#define VARATT_IS_4B(PTR) \
@@ -267,36 +275,28 @@ typedef struct
267275
#define SET_VARTAG_1B_E(PTR,tag) \
268276
(((varattrib_1b_e *) (PTR))->va_header = 0x01, \
269277
((varattrib_1b_e *) (PTR))->va_tag = (tag))
270-
#endif /* WORDS_BIGENDIAN */
271278

272-
#define VARHDRSZ_SHORT offsetof(varattrib_1b, va_data)
273-
#define VARATT_SHORT_MAX 0x7F
274-
#define VARATT_CAN_MAKE_SHORT(PTR) \
275-
(VARATT_IS_4B_U(PTR) && \
276-
(VARSIZE(PTR) - VARHDRSZ + VARHDRSZ_SHORT) <= VARATT_SHORT_MAX)
277-
#define VARATT_CONVERTED_SHORT_SIZE(PTR) \
278-
(VARSIZE(PTR) - VARHDRSZ + VARHDRSZ_SHORT)
279-
280-
#define VARHDRSZ_EXTERNAL offsetof(varattrib_1b_e, va_data)
281-
#define VARHDRSZ_COMPRESS offsetof(varattrib_4b, va_compressed.va_data)
279+
#endif /* WORDS_BIGENDIAN */
282280

283281
#define VARDATA_4B(PTR) (((varattrib_4b *) (PTR))->va_4byte.va_data)
284282
#define VARDATA_4B_C(PTR) (((varattrib_4b *) (PTR))->va_compressed.va_data)
285283
#define VARDATA_1B(PTR) (((varattrib_1b *) (PTR))->va_data)
286284
#define VARDATA_1B_E(PTR) (((varattrib_1b_e *) (PTR))->va_data)
287285

288-
#define VARLENA_RAWSIZE_BITS 30
289-
#define VARLENA_RAWSIZE_MASK ((1U << VARLENA_RAWSIZE_BITS) - 1)
290-
291286
/*
292-
* va_tcinfo in va_compress contains raw size of datum and compression method.
287+
* Externally visible TOAST macros begin here.
293288
*/
294-
#define VARRAWSIZE_4B_C(PTR) \
295-
(((varattrib_4b *) (PTR))->va_compressed.va_tcinfo & VARLENA_RAWSIZE_MASK)
296-
#define VARCOMPRESS_4B_C(PTR) \
297-
(((varattrib_4b *) (PTR))->va_compressed.va_tcinfo >> VARLENA_RAWSIZE_BITS)
298289

299-
/* Externally visible macros */
290+
#define VARHDRSZ_EXTERNAL offsetof(varattrib_1b_e, va_data)
291+
#define VARHDRSZ_COMPRESSED offsetof(varattrib_4b, va_compressed.va_data)
292+
#define VARHDRSZ_SHORT offsetof(varattrib_1b, va_data)
293+
294+
#define VARATT_SHORT_MAX 0x7F
295+
#define VARATT_CAN_MAKE_SHORT(PTR) \
296+
(VARATT_IS_4B_U(PTR) && \
297+
(VARSIZE(PTR) - VARHDRSZ + VARHDRSZ_SHORT) <= VARATT_SHORT_MAX)
298+
#define VARATT_CONVERTED_SHORT_SIZE(PTR) \
299+
(VARSIZE(PTR) - VARHDRSZ + VARHDRSZ_SHORT)
300300

301301
/*
302302
* In consumers oblivious to data alignment, call PG_DETOAST_DATUM_PACKED(),
@@ -336,35 +336,6 @@ typedef struct
336336
(VARATT_IS_EXTERNAL(PTR) && VARTAG_IS_EXPANDED(VARTAG_EXTERNAL(PTR)))
337337
#define VARATT_IS_EXTERNAL_NON_EXPANDED(PTR) \
338338
(VARATT_IS_EXTERNAL(PTR) && !VARTAG_IS_EXPANDED(VARTAG_EXTERNAL(PTR)))
339-
340-
/*
341-
* va_extinfo in varatt_external contains actual length of the external data
342-
* and compression method if external data is compressed.
343-
*/
344-
#define VARATT_EXTERNAL_GET_EXTSIZE(toast_pointer) \
345-
((toast_pointer).va_extinfo & VARLENA_RAWSIZE_MASK)
346-
347-
#define VARATT_EXTERNAL_SET_SIZE_AND_COMPRESSION(toast_pointer, len, cm) \
348-
do { \
349-
Assert((cm) == TOAST_PGLZ_COMPRESSION_ID || \
350-
(cm) == TOAST_LZ4_COMPRESSION_ID); \
351-
((toast_pointer).va_extinfo = (len) | (cm) << VARLENA_RAWSIZE_BITS); \
352-
} while (0)
353-
354-
#define VARATT_EXTERNAL_GET_COMPRESSION(PTR) \
355-
((toast_pointer).va_extinfo >> VARLENA_RAWSIZE_BITS)
356-
357-
/*
358-
* Testing whether an externally-stored value is compressed now requires
359-
* comparing size stored in va_extinfo (the actual length of the external data)
360-
* to rawsize (the original uncompressed datum's size). The latter includes
361-
* VARHDRSZ overhead, the former doesn't. We never use compression unless it
362-
* actually saves space, so we expect either equality or less-than.
363-
*/
364-
#define VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer) \
365-
(VARATT_EXTERNAL_GET_EXTSIZE(toast_pointer) < \
366-
(toast_pointer).va_rawsize - VARHDRSZ)
367-
368339
#define VARATT_IS_SHORT(PTR) VARATT_IS_1B(PTR)
369340
#define VARATT_IS_EXTENDED(PTR) (!VARATT_IS_4B_U(PTR))
370341

@@ -390,6 +361,37 @@ typedef struct
390361
#define VARDATA_ANY(PTR) \
391362
(VARATT_IS_1B(PTR) ? VARDATA_1B(PTR) : VARDATA_4B(PTR))
392363

364+
/* Decompressed size and compression method of an external compressed Datum */
365+
#define VARDATA_COMPRESSED_GET_EXTSIZE(PTR) \
366+
(((varattrib_4b *) (PTR))->va_compressed.va_tcinfo & VARLENA_EXTSIZE_MASK)
367+
#define VARDATA_COMPRESSED_GET_COMPRESS_METHOD(PTR) \
368+
(((varattrib_4b *) (PTR))->va_compressed.va_tcinfo >> VARLENA_EXTSIZE_BITS)
369+
370+
/* Same, when working directly with a struct varatt_external */
371+
#define VARATT_EXTERNAL_GET_EXTSIZE(toast_pointer) \
372+
((toast_pointer).va_extinfo & VARLENA_EXTSIZE_MASK)
373+
#define VARATT_EXTERNAL_GET_COMPRESS_METHOD(toast_pointer) \
374+
((toast_pointer).va_extinfo >> VARLENA_EXTSIZE_BITS)
375+
376+
#define VARATT_EXTERNAL_SET_SIZE_AND_COMPRESS_METHOD(toast_pointer, len, cm) \
377+
do { \
378+
Assert((cm) == TOAST_PGLZ_COMPRESSION_ID || \
379+
(cm) == TOAST_LZ4_COMPRESSION_ID); \
380+
((toast_pointer).va_extinfo = \
381+
(len) | ((uint32) (cm) << VARLENA_EXTSIZE_BITS)); \
382+
} while (0)
383+
384+
/*
385+
* Testing whether an externally-stored value is compressed now requires
386+
* comparing size stored in va_extinfo (the actual length of the external data)
387+
* to rawsize (the original uncompressed datum's size). The latter includes
388+
* VARHDRSZ overhead, the former doesn't. We never use compression unless it
389+
* actually saves space, so we expect either equality or less-than.
390+
*/
391+
#define VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer) \
392+
(VARATT_EXTERNAL_GET_EXTSIZE(toast_pointer) < \
393+
(toast_pointer).va_rawsize - VARHDRSZ)
394+
393395

394396
/* ----------------------------------------------------------------
395397
* Section 2: Datum type + support macros

0 commit comments

Comments
 (0)