From 22ccce5206717036a06aefdf3f9f78ed9ffaab2f Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Sat, 12 Jul 2014 14:28:19 +0200 Subject: Fix decoding of consecutive MULTI_INSERTs emitted by one heap_multi_insert(). Commit 1b86c81d2d fixed the decoding of toasted columns for the rows contained in one xl_heap_multi_insert record. But that's not actually enough, because heap_multi_insert() will actually first toast all passed in rows and then emit several *_multi_insert records; one for each page it fills with tuples. Add a XLOG_HEAP_LAST_MULTI_INSERT flag which is set in xl_heap_multi_insert->flag denoting that this multi_insert record is the last emitted by one heap_multi_insert() call. Then use that flag in decode.c to only set clear_toast_afterwards in the right situation. Expand the number of rows inserted via COPY in the corresponding regression test to make sure that more than one heap page is filled with tuples by one heap_multi_insert() call. Backpatch to 9.4 like the previous commit. --- src/backend/access/heap/heapam.c | 8 ++++++++ src/backend/replication/logical/decode.c | 12 ++++++++++-- src/include/access/heapam_xlog.h | 2 ++ 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 1accdd9d99a..e8199b309b7 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -2513,6 +2513,14 @@ heap_multi_insert(Relation relation, HeapTuple *tuples, int ntuples, info |= XLOG_HEAP_INIT_PAGE; } + /* + * Signal that this is the last xl_heap_multi_insert record + * emitted by this call to heap_multi_insert(). Needed for logical + * decoding so it knows when to cleanup temporary data. + */ + if (ndone + nthispage == ntuples) + xlrec->flags |= XLOG_HEAP_LAST_MULTI_INSERT; + recptr = XLogInsert(RM_HEAP2_ID, info, rdata); PageSetLSN(page, recptr); diff --git a/src/backend/replication/logical/decode.c b/src/backend/replication/logical/decode.c index 1734ec96599..8f8732afdce 100644 --- a/src/backend/replication/logical/decode.c +++ b/src/backend/replication/logical/decode.c @@ -802,8 +802,16 @@ DecodeMultiInsert(LogicalDecodingContext *ctx, XLogRecordBuffer *buf) tuple->header.t_hoff = xlhdr->t_hoff; } - /* reset toast reassembly only after the last chunk */ - change->data.tp.clear_toast_afterwards = (i + 1) == xlrec->ntuples; + /* + * Reset toast reassembly state only after the last row in the last + * xl_multi_insert_tuple record emitted by one heap_multi_insert() + * call. + */ + if (xlrec->flags & XLOG_HEAP_LAST_MULTI_INSERT && + (i + 1) == xlrec->ntuples) + change->data.tp.clear_toast_afterwards = true; + else + change->data.tp.clear_toast_afterwards = false; ReorderBufferQueueChange(ctx->reorder, r->xl_xid, buf->origptr, change); diff --git a/src/include/access/heapam_xlog.h b/src/include/access/heapam_xlog.h index cfdd1ffbefc..9557486635a 100644 --- a/src/include/access/heapam_xlog.h +++ b/src/include/access/heapam_xlog.h @@ -69,6 +69,8 @@ #define XLOG_HEAP_CONTAINS_NEW_TUPLE (1<<4) #define XLOG_HEAP_PREFIX_FROM_OLD (1<<5) #define XLOG_HEAP_SUFFIX_FROM_OLD (1<<6) +/* last xl_heap_multi_insert record for one heap_multi_insert() call */ +#define XLOG_HEAP_LAST_MULTI_INSERT (1<<7) /* convenience macro for checking whether any form of old tuple was logged */ #define XLOG_HEAP_CONTAINS_OLD \ -- cgit v1.2.3