|
|
|
|
@ -2063,12 +2063,8 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid, |
|
|
|
|
TransactionId xid = GetCurrentTransactionId(); |
|
|
|
|
HeapTuple heaptup; |
|
|
|
|
Buffer buffer; |
|
|
|
|
Page page = NULL; |
|
|
|
|
Buffer vmbuffer = InvalidBuffer; |
|
|
|
|
bool starting_with_empty_page; |
|
|
|
|
bool all_visible_cleared = false; |
|
|
|
|
bool all_frozen_set = false; |
|
|
|
|
uint8 vmstatus = 0; |
|
|
|
|
|
|
|
|
|
/* Cheap, simplistic check that the tuple matches the rel's rowtype. */ |
|
|
|
|
Assert(HeapTupleHeaderGetNatts(tup->t_data) <= |
|
|
|
|
@ -2085,36 +2081,11 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid, |
|
|
|
|
/*
|
|
|
|
|
* Find buffer to insert this tuple into. If the page is all visible, |
|
|
|
|
* this will also pin the requisite visibility map page. |
|
|
|
|
* |
|
|
|
|
* Also pin visibility map page if COPY FREEZE inserts tuples into an |
|
|
|
|
* empty page. See all_frozen_set below. |
|
|
|
|
*/ |
|
|
|
|
buffer = RelationGetBufferForTuple(relation, heaptup->t_len, |
|
|
|
|
InvalidBuffer, options, bistate, |
|
|
|
|
&vmbuffer, NULL); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If we're inserting frozen entry into an empty page, set visibility map |
|
|
|
|
* bits and PageAllVisible() hint. |
|
|
|
|
* |
|
|
|
|
* If we're inserting frozen entry into already all_frozen page, preserve |
|
|
|
|
* this state. |
|
|
|
|
*/ |
|
|
|
|
if (options & HEAP_INSERT_FROZEN) |
|
|
|
|
{ |
|
|
|
|
page = BufferGetPage(buffer); |
|
|
|
|
|
|
|
|
|
starting_with_empty_page = PageGetMaxOffsetNumber(page) == 0; |
|
|
|
|
|
|
|
|
|
if (visibilitymap_pin_ok(BufferGetBlockNumber(buffer), vmbuffer)) |
|
|
|
|
vmstatus = visibilitymap_get_status(relation, |
|
|
|
|
BufferGetBlockNumber(buffer), &vmbuffer); |
|
|
|
|
|
|
|
|
|
if ((starting_with_empty_page || vmstatus & VISIBILITYMAP_ALL_FROZEN)) |
|
|
|
|
all_frozen_set = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We're about to do the actual insert -- but check for conflict first, to |
|
|
|
|
* avoid possibly having to roll back work we've just done. |
|
|
|
|
@ -2138,14 +2109,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid, |
|
|
|
|
RelationPutHeapTuple(relation, buffer, heaptup, |
|
|
|
|
(options & HEAP_INSERT_SPECULATIVE) != 0); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If the page is all visible, need to clear that, unless we're only going |
|
|
|
|
* to add further frozen rows to it. |
|
|
|
|
* |
|
|
|
|
* If we're only adding already frozen rows to a page that was empty or |
|
|
|
|
* marked as all visible, mark it as all-visible. |
|
|
|
|
*/ |
|
|
|
|
if (PageIsAllVisible(BufferGetPage(buffer)) && !(options & HEAP_INSERT_FROZEN)) |
|
|
|
|
if (PageIsAllVisible(BufferGetPage(buffer))) |
|
|
|
|
{ |
|
|
|
|
all_visible_cleared = true; |
|
|
|
|
PageClearAllVisible(BufferGetPage(buffer)); |
|
|
|
|
@ -2153,13 +2117,6 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid, |
|
|
|
|
ItemPointerGetBlockNumber(&(heaptup->t_self)), |
|
|
|
|
vmbuffer, VISIBILITYMAP_VALID_BITS); |
|
|
|
|
} |
|
|
|
|
else if (all_frozen_set) |
|
|
|
|
{ |
|
|
|
|
/* We only ever set all_frozen_set after reading the page. */ |
|
|
|
|
Assert(page); |
|
|
|
|
|
|
|
|
|
PageSetAllVisible(page); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* XXX Should we set PageSetPrunable on this page ? |
|
|
|
|
@ -2207,8 +2164,6 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid, |
|
|
|
|
xlrec.flags = 0; |
|
|
|
|
if (all_visible_cleared) |
|
|
|
|
xlrec.flags |= XLH_INSERT_ALL_VISIBLE_CLEARED; |
|
|
|
|
if (all_frozen_set) |
|
|
|
|
xlrec.flags = XLH_INSERT_ALL_FROZEN_SET; |
|
|
|
|
if (options & HEAP_INSERT_SPECULATIVE) |
|
|
|
|
xlrec.flags |= XLH_INSERT_IS_SPECULATIVE; |
|
|
|
|
Assert(ItemPointerGetBlockNumber(&heaptup->t_self) == BufferGetBlockNumber(buffer)); |
|
|
|
|
@ -2257,29 +2212,6 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid, |
|
|
|
|
|
|
|
|
|
END_CRIT_SECTION(); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If we've frozen everything on the page, update the visibilitymap. We're |
|
|
|
|
* already holding pin on the vmbuffer. |
|
|
|
|
* |
|
|
|
|
* No need to update the visibilitymap if it had all_frozen bit set before |
|
|
|
|
* this insertion. |
|
|
|
|
*/ |
|
|
|
|
if (all_frozen_set && ((vmstatus & VISIBILITYMAP_ALL_FROZEN) == 0)) |
|
|
|
|
{ |
|
|
|
|
Assert(PageIsAllVisible(page)); |
|
|
|
|
Assert(visibilitymap_pin_ok(BufferGetBlockNumber(buffer), vmbuffer)); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* It's fine to use InvalidTransactionId here - this is only used when |
|
|
|
|
* HEAP_INSERT_FROZEN is specified, which intentionally violates |
|
|
|
|
* visibility rules. |
|
|
|
|
*/ |
|
|
|
|
visibilitymap_set(relation, BufferGetBlockNumber(buffer), buffer, |
|
|
|
|
InvalidXLogRecPtr, vmbuffer, |
|
|
|
|
InvalidTransactionId, |
|
|
|
|
VISIBILITYMAP_ALL_VISIBLE | VISIBILITYMAP_ALL_FROZEN); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
UnlockReleaseBuffer(buffer); |
|
|
|
|
if (vmbuffer != InvalidBuffer) |
|
|
|
|
ReleaseBuffer(vmbuffer); |
|
|
|
|
@ -8946,10 +8878,6 @@ heap_xlog_insert(XLogReaderState *record) |
|
|
|
|
ItemPointerSetBlockNumber(&target_tid, blkno); |
|
|
|
|
ItemPointerSetOffsetNumber(&target_tid, xlrec->offnum); |
|
|
|
|
|
|
|
|
|
/* check that the mutually exclusive flags are not both set */ |
|
|
|
|
Assert(!((xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) && |
|
|
|
|
(xlrec->flags & XLH_INSERT_ALL_FROZEN_SET))); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The visibility map may need to be fixed even if the heap page is |
|
|
|
|
* already up-to-date. |
|
|
|
|
|