multi_insert_fail.diff
text/x-patch
Filename: multi_insert_fail.diff
Type: text/x-patch
Part: 1
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: context
| File | + | − |
|---|---|---|
| src/backend/access/heap/heapam.c | 107 | 98 |
*** postgresql-9.2.2/src/backend/access/heap/heapam.c 2012-12-03 12:16:10.000000000 -0800
--- postgresql-9.2.2dg/src/backend/access/heap/heapam.c 2012-12-12 01:55:58.174653706 -0800
***************
*** 2158,2163 ****
--- 2158,2164 ----
Buffer buffer;
Buffer vmbuffer = InvalidBuffer;
bool all_visible_cleared = false;
+ bool page_is_empty;
int nthispage;
/*
***************
*** 2173,2299 ****
START_CRIT_SECTION();
/* Put as many tuples as fit on this page */
for (nthispage = 0; ndone + nthispage < ntuples; nthispage++)
{
HeapTuple heaptup = heaptuples[ndone + nthispage];
! if (PageGetHeapFreeSpace(page) < MAXALIGN(heaptup->t_len) + saveFreeSpace)
break;
!
RelationPutHeapTuple(relation, buffer, heaptup);
}
- if (PageIsAllVisible(page))
- {
- all_visible_cleared = true;
- PageClearAllVisible(page);
- visibilitymap_clear(relation,
- BufferGetBlockNumber(buffer),
- vmbuffer);
- }
-
/*
! * XXX Should we set PageSetPrunable on this page ? See heap_insert()
*/
!
! MarkBufferDirty(buffer);
!
! /* XLOG stuff */
! if (needwal)
{
! XLogRecPtr recptr;
! xl_heap_multi_insert *xlrec;
! XLogRecData rdata[2];
! uint8 info = XLOG_HEAP2_MULTI_INSERT;
! char *tupledata;
! int totaldatalen;
! char *scratchptr = scratch;
! bool init;
/*
! * If the page was previously empty, we can reinit the page
! * instead of restoring the whole thing.
*/
- init = (ItemPointerGetOffsetNumber(&(heaptuples[ndone]->t_self)) == FirstOffsetNumber &&
- PageGetMaxOffsetNumber(page) == FirstOffsetNumber + nthispage - 1);
! /* allocate xl_heap_multi_insert struct from the scratch area */
! xlrec = (xl_heap_multi_insert *) scratchptr;
! scratchptr += SizeOfHeapMultiInsert;
! /*
! * Allocate offsets array. Unless we're reinitializing the page,
! * in that case the tuples are stored in order starting at
! * FirstOffsetNumber and we don't need to store the offsets
! * explicitly.
! */
! if (!init)
! scratchptr += nthispage * sizeof(OffsetNumber);
! /* the rest of the scratch space is used for tuple data */
! tupledata = scratchptr;
! xlrec->all_visible_cleared = all_visible_cleared;
! xlrec->node = relation->rd_node;
! xlrec->blkno = BufferGetBlockNumber(buffer);
! xlrec->ntuples = nthispage;
!
! /*
! * Write out an xl_multi_insert_tuple and the tuple data itself
! * for each tuple.
! */
! for (i = 0; i < nthispage; i++)
! {
! HeapTuple heaptup = heaptuples[ndone + i];
! xl_multi_insert_tuple *tuphdr;
! int datalen;
if (!init)
! xlrec->offsets[i] = ItemPointerGetOffsetNumber(&heaptup->t_self);
! /* xl_multi_insert_tuple needs two-byte alignment. */
! tuphdr = (xl_multi_insert_tuple *) SHORTALIGN(scratchptr);
! scratchptr = ((char *) tuphdr) + SizeOfMultiInsertTuple;
!
! tuphdr->t_infomask2 = heaptup->t_data->t_infomask2;
! tuphdr->t_infomask = heaptup->t_data->t_infomask;
! tuphdr->t_hoff = heaptup->t_data->t_hoff;
!
! /* write bitmap [+ padding] [+ oid] + data */
! datalen = heaptup->t_len - offsetof(HeapTupleHeaderData, t_bits);
! memcpy(scratchptr,
! (char *) heaptup->t_data + offsetof(HeapTupleHeaderData, t_bits),
! datalen);
! tuphdr->datalen = datalen;
! scratchptr += datalen;
! }
! totaldatalen = scratchptr - tupledata;
! Assert((scratchptr - scratch) < BLCKSZ);
! rdata[0].data = (char *) xlrec;
! rdata[0].len = tupledata - scratch;
! rdata[0].buffer = InvalidBuffer;
! rdata[0].next = &rdata[1];
!
! rdata[1].data = tupledata;
! rdata[1].len = totaldatalen;
! rdata[1].buffer = buffer;
! rdata[1].buffer_std = true;
! rdata[1].next = NULL;
! /*
! * If we're going to reinitialize the whole page using the WAL
! * record, hide buffer reference from XLogInsert.
! */
! if (init)
! {
! rdata[1].buffer = InvalidBuffer;
! info |= XLOG_HEAP_INIT_PAGE;
! }
! recptr = XLogInsert(RM_HEAP2_ID, info, rdata);
! PageSetLSN(page, recptr);
! PageSetTLI(page, ThisTimeLineID);
}
END_CRIT_SECTION();
--- 2174,2309 ----
START_CRIT_SECTION();
/* Put as many tuples as fit on this page */
+ page_is_empty = PageGetMaxOffsetNumber(page) == 0;
for (nthispage = 0; ndone + nthispage < ntuples; nthispage++)
{
HeapTuple heaptup = heaptuples[ndone + nthispage];
! if (PageGetHeapFreeSpace(page) <
! MAXALIGN(heaptup->t_len) + (page_is_empty ? 0 : saveFreeSpace))
break;
! page_is_empty = false;
RelationPutHeapTuple(relation, buffer, heaptup);
}
/*
! * If nthispage > 0 then we modified the (possibly new) page,
! * otherwise there was not enough space for even one new tuple.
*/
! if (nthispage > 0)
{
! if (PageIsAllVisible(page))
! {
! all_visible_cleared = true;
! PageClearAllVisible(page);
! visibilitymap_clear(relation,
! BufferGetBlockNumber(buffer),
! vmbuffer);
! }
/*
! * XXX Should we set PageSetPrunable on this page ? See heap_insert()
*/
! MarkBufferDirty(buffer);
! /* XLOG stuff */
! if (needwal)
! {
! XLogRecPtr recptr;
! xl_heap_multi_insert *xlrec;
! XLogRecData rdata[2];
! uint8 info = XLOG_HEAP2_MULTI_INSERT;
! char *tupledata;
! int totaldatalen;
! char *scratchptr = scratch;
! bool init;
! /*
! * If the page was previously empty, we can reinit the page
! * instead of restoring the whole thing.
! */
! init = (ItemPointerGetOffsetNumber(&(heaptuples[ndone]->t_self)) == FirstOffsetNumber &&
! PageGetMaxOffsetNumber(page) == FirstOffsetNumber + nthispage - 1);
! /* allocate xl_heap_multi_insert struct from the scratch area */
! xlrec = (xl_heap_multi_insert *) scratchptr;
! scratchptr += SizeOfHeapMultiInsert;
+ /*
+ * Allocate offsets array. Unless we're reinitializing the page,
+ * in that case the tuples are stored in order starting at
+ * FirstOffsetNumber and we don't need to store the offsets
+ * explicitly.
+ */
if (!init)
! scratchptr += nthispage * sizeof(OffsetNumber);
! /* the rest of the scratch space is used for tuple data */
! tupledata = scratchptr;
! xlrec->all_visible_cleared = all_visible_cleared;
! xlrec->node = relation->rd_node;
! xlrec->blkno = BufferGetBlockNumber(buffer);
! xlrec->ntuples = nthispage;
! /*
! * Write out an xl_multi_insert_tuple and the tuple data itself
! * for each tuple.
! */
! for (i = 0; i < nthispage; i++)
! {
! HeapTuple heaptup = heaptuples[ndone + i];
! xl_multi_insert_tuple *tuphdr;
! int datalen;
!
! if (!init)
! xlrec->offsets[i] = ItemPointerGetOffsetNumber(&heaptup->t_self);
! /* xl_multi_insert_tuple needs two-byte alignment. */
! tuphdr = (xl_multi_insert_tuple *) SHORTALIGN(scratchptr);
! scratchptr = ((char *) tuphdr) + SizeOfMultiInsertTuple;
!
! tuphdr->t_infomask2 = heaptup->t_data->t_infomask2;
! tuphdr->t_infomask = heaptup->t_data->t_infomask;
! tuphdr->t_hoff = heaptup->t_data->t_hoff;
!
! /* write bitmap [+ padding] [+ oid] + data */
! datalen = heaptup->t_len - offsetof(HeapTupleHeaderData, t_bits);
! memcpy(scratchptr,
! (char *) heaptup->t_data + offsetof(HeapTupleHeaderData, t_bits),
! datalen);
! tuphdr->datalen = datalen;
! scratchptr += datalen;
! }
! totaldatalen = scratchptr - tupledata;
! Assert((scratchptr - scratch) < BLCKSZ);
!
! rdata[0].data = (char *) xlrec;
! rdata[0].len = tupledata - scratch;
! rdata[0].buffer = InvalidBuffer;
! rdata[0].next = &rdata[1];
!
! rdata[1].data = tupledata;
! rdata[1].len = totaldatalen;
! rdata[1].buffer = buffer;
! rdata[1].buffer_std = true;
! rdata[1].next = NULL;
!
! /*
! * If we're going to reinitialize the whole page using the WAL
! * record, hide buffer reference from XLogInsert.
! */
! if (init)
! {
! rdata[1].buffer = InvalidBuffer;
! info |= XLOG_HEAP_INIT_PAGE;
! }
!
! recptr = XLogInsert(RM_HEAP2_ID, info, rdata);
! PageSetLSN(page, recptr);
! PageSetTLI(page, ThisTimeLineID);
! }
}
END_CRIT_SECTION();
***************
*** 2304,2310 ****
ndone += nthispage;
}
-
/*
* If tuples are cachable, mark them for invalidation from the caches in
* case we abort. Note it is OK to do this after releasing the buffer,
--- 2314,2319 ----