diff options
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/access/heap/tuptoaster.c | 38 | ||||
| -rw-r--r-- | src/backend/access/transam/xlogreader.c | 2 | ||||
| -rw-r--r-- | src/backend/utils/adt/varlena.c | 22 |
3 files changed, 50 insertions, 12 deletions
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index a40cfcf1954..74e957abb72 100644 --- a/src/backend/access/heap/tuptoaster.c +++ b/src/backend/access/heap/tuptoaster.c @@ -75,6 +75,7 @@ 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 struct varlena *toast_decompress_datum_slice(struct varlena *attr, int32 slicelength); static int toast_open_indexes(Relation toastrel, LOCKMODE lock, Relation **toastidxs, @@ -301,7 +302,11 @@ heap_tuple_untoast_attr_slice(struct varlena *attr, { struct varlena *tmp = preslice; - preslice = toast_decompress_datum(tmp); + /* Decompress enough to encompass the slice and the offset */ + if (slicelength > 0 && sliceoffset >= 0) + preslice = toast_decompress_datum_slice(tmp, slicelength + sliceoffset); + else + preslice = toast_decompress_datum(tmp); if (tmp != attr) pfree(tmp); @@ -2272,9 +2277,38 @@ toast_decompress_datum(struct varlena *attr) if (pglz_decompress(TOAST_COMPRESS_RAWDATA(attr), VARSIZE(attr) - TOAST_COMPRESS_HDRSZ, VARDATA(result), - TOAST_COMPRESS_RAWSIZE(attr)) < 0) + TOAST_COMPRESS_RAWSIZE(attr), true) < 0) + elog(ERROR, "compressed data is corrupted"); + + return result; +} + + +/* ---------- + * toast_decompress_datum_slice - + * + * Decompress the front of a compressed version of a varlena datum. + * offset handling happens in heap_tuple_untoast_attr_slice. + * Here we just decompress a slice from the front. + */ +static struct varlena * +toast_decompress_datum_slice(struct varlena *attr, int32 slicelength) +{ + struct varlena *result; + int32 rawsize; + + Assert(VARATT_IS_COMPRESSED(attr)); + + result = (struct varlena *) palloc(slicelength + VARHDRSZ); + + rawsize = pglz_decompress(TOAST_COMPRESS_RAWDATA(attr), + VARSIZE(attr) - TOAST_COMPRESS_HDRSZ, + VARDATA(result), + slicelength, false); + if (rawsize < 0) elog(ERROR, "compressed data is corrupted"); + SET_VARSIZE(result, rawsize + VARHDRSZ); return result; } diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c index cbc7e4e7ead..9196aa3aaef 100644 --- a/src/backend/access/transam/xlogreader.c +++ b/src/backend/access/transam/xlogreader.c @@ -1425,7 +1425,7 @@ RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page) { /* If a backup block image is compressed, decompress it */ if (pglz_decompress(ptr, bkpb->bimg_len, tmp.data, - BLCKSZ - bkpb->hole_length) < 0) + BLCKSZ - bkpb->hole_length, true) < 0) { report_invalid_record(record, "invalid compressed image at %X/%X, block %d", (uint32) (record->ReadRecPtr >> 32), diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index 68a6e49aeb4..f82ce92ce3d 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -1894,7 +1894,7 @@ text_starts_with(PG_FUNCTION_ARGS) result = false; else { - text *targ1 = DatumGetTextPP(arg1); + text *targ1 = text_substring(arg1, 1, len2, false); text *targ2 = DatumGetTextPP(arg2); result = (memcmp(VARDATA_ANY(targ1), VARDATA_ANY(targ2), @@ -5346,17 +5346,21 @@ text_concat_ws(PG_FUNCTION_ARGS) Datum text_left(PG_FUNCTION_ARGS) { - text *str = PG_GETARG_TEXT_PP(0); - const char *p = VARDATA_ANY(str); - int len = VARSIZE_ANY_EXHDR(str); - int n = PG_GETARG_INT32(1); - int rlen; + int n = PG_GETARG_INT32(1); if (n < 0) - n = pg_mbstrlen_with_len(p, len) + n; - rlen = pg_mbcharcliplen(p, len, n); + { + text *str = PG_GETARG_TEXT_PP(0); + const char *p = VARDATA_ANY(str); + int len = VARSIZE_ANY_EXHDR(str); + int rlen; - PG_RETURN_TEXT_P(cstring_to_text_with_len(p, rlen)); + n = pg_mbstrlen_with_len(p, len) + n; + rlen = pg_mbcharcliplen(p, len, n); + PG_RETURN_TEXT_P(cstring_to_text_with_len(p, rlen)); + } + else + PG_RETURN_TEXT_P(text_substring(PG_GETARG_DATUM(0), 1, n, false)); } /* |
