summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/access/heap/tuptoaster.c38
-rw-r--r--src/backend/access/transam/xlogreader.c2
-rw-r--r--src/backend/utils/adt/varlena.c22
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));
}
/*