diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/heap/heapam.c | 8 | ||||
-rw-r--r-- | src/backend/replication/logical/decode.c | 19 |
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 } |