diff options
Diffstat (limited to 'src/backend/access/heap/heapam_handler.c')
-rw-r--r-- | src/backend/access/heap/heapam_handler.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index bd5faf0c1fb..7b475f2950c 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -19,6 +19,7 @@ */ #include "postgres.h" +#include "access/detoast.h" #include "access/genam.h" #include "access/heapam.h" #include "access/heaptoast.h" @@ -26,6 +27,7 @@ #include "access/rewriteheap.h" #include "access/syncscan.h" #include "access/tableam.h" +#include "access/toast_compression.h" #include "access/tsmapi.h" #include "access/xact.h" #include "catalog/catalog.h" @@ -2469,6 +2471,44 @@ reform_and_rewrite_tuple(HeapTuple tuple, { if (TupleDescAttr(newTupDesc, i)->attisdropped) isnull[i] = true; + + /* + * Use this opportunity to force recompression of any data that's + * compressed with some TOAST compression method other than the one + * configured for the column. We don't actually need to perform the + * compression here; we just need to decompress. That will trigger + * recompression later on. + */ + else if (!isnull[i] && TupleDescAttr(newTupDesc, i)->attlen == -1) + { + struct varlena *new_value; + ToastCompressionId cmid; + char cmethod; + + new_value = (struct varlena *) DatumGetPointer(values[i]); + cmid = toast_get_compression_id(new_value); + + /* nothing to be done for uncompressed data */ + if (cmid == TOAST_INVALID_COMPRESSION_ID) + continue; + + /* convert compression id to compression method */ + switch (cmid) + { + case TOAST_PGLZ_COMPRESSION_ID: + cmethod = TOAST_PGLZ_COMPRESSION; + break; + case TOAST_LZ4_COMPRESSION_ID: + cmethod = TOAST_LZ4_COMPRESSION; + break; + default: + elog(ERROR, "invalid compression method id %d", cmid); + } + + /* if compression method doesn't match then detoast the value */ + if (TupleDescAttr(newTupDesc, i)->attcompression != cmethod) + values[i] = PointerGetDatum(detoast_attr(new_value)); + } } copiedTuple = heap_form_tuple(newTupDesc, values, isnull); |