aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/heap/heapam.c8
-rw-r--r--src/backend/replication/logical/decode.c19
2 files changed, 23 insertions, 4 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 1848bc5f2c0..26d96fd7fc0 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -7086,7 +7086,13 @@ log_heap_update(Relation reln, Buffer oldbuf,
/* We need to log a tuple identity */
if (old_key_tuple)
{
- /* don't really need this, but its more comfy to decode */
+ /*
+ * This isn't needed, and can't actually capture the contents of
+ * the tuple accurately (because t_len isn't guaranteed to be big
+ * enough to contain old tuples which can be up to 1 GB long). But
+ * previous versions of 9.4 used this, so we can't change the WAL
+ * format.
+ */
xlhdr_idx.header.t_infomask2 = old_key_tuple->t_data->t_infomask2;
xlhdr_idx.header.t_infomask = old_key_tuple->t_data->t_infomask;
xlhdr_idx.header.t_hoff = old_key_tuple->t_data->t_hoff;
diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c
index 3a6d6ffab1a..09a334232e1 100644
--- a/src/backend/replication/logical/decode.c
+++ b/src/backend/replication/logical/decode.c
@@ -653,6 +653,7 @@ DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
xl_heap_update *xlrec;
ReorderBufferChange *change;
char *data;
+ size_t remlen = r->xl_len;
xlrec = (xl_heap_update *) buf->record_data;
@@ -666,6 +667,7 @@ DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
/* caution, remaining data in record is not aligned */
data = buf->record_data + SizeOfHeapUpdate;
+ remlen -= SizeOfHeapUpdate;
if (xlrec->flags & XLOG_HEAP_CONTAINS_NEW_TUPLE)
{
@@ -677,6 +679,7 @@ DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
memcpy(&xlhdr, data, sizeof(xlhdr));
data += offsetof(xl_heap_header_len, header);
+ remlen -= offsetof(xl_heap_header_len, header);
datalen = xlhdr.t_len + SizeOfHeapHeader;
tuplelen = xlhdr.t_len;
@@ -687,8 +690,10 @@ DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
DecodeXLogTuple(data, datalen, change->data.tp.newtuple);
/* skip over the rest of the tuple header */
data += SizeOfHeapHeader;
+ remlen -= SizeOfHeapHeader;
/* skip over the tuple data */
data += xlhdr.t_len;
+ remlen -= xlhdr.t_len;
}
if (xlrec->flags & XLOG_HEAP_CONTAINS_OLD)
@@ -699,10 +704,17 @@ DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
memcpy(&xlhdr, data, sizeof(xlhdr));
data += offsetof(xl_heap_header_len, header);
+ remlen -= offsetof(xl_heap_header_len, header);
- /* t_len is inconsistent with other cases, see log_heap_update */
- tuplelen = xlhdr.t_len - offsetof(HeapTupleHeaderData, t_bits);
- datalen = tuplelen + SizeOfHeapHeader;
+ /*
+ * NB: Even though xl_heap_header_len contains the tuple's length,
+ * it's length field is not wide enough. Use the whole record length
+ * minus the new tuple's length instead. We can't remove the record
+ * length from the WAL record format in 9.4 due to compatibility
+ * concerns - later versions don't have it anyway.
+ */
+ datalen = remlen;
+ tuplelen = datalen - SizeOfHeapHeader;
change->data.tp.oldtuple =
ReorderBufferGetTupleBuf(ctx->reorder, tuplelen);
@@ -710,6 +722,7 @@ DecodeUpdate(LogicalDecodingContext *ctx, XLogRecordBuffer *buf)
DecodeXLogTuple(data, datalen, change->data.tp.oldtuple);
#ifdef NOT_USED
data += datalen;
+ remlen -= datalen;
#endif
}