mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-04 00:57:20 +02:00
Fix WAL-logging of B-tree "unlink halfdead page" operation.
There was some confusion on how to record the case that the operation unlinks the last non-leaf page in the branch being deleted. _bt_unlink_halfdead_page set the "topdead" field in the WAL record to the leaf page, but the redo routine assumed that it would be an invalid block number in that case. This commit fixes _bt_unlink_halfdead_page to do what the redo routine expected. This code is new in 9.4, so backpatch there.
This commit is contained in:
parent
d8a7cdde58
commit
8607fdf033
@ -1565,7 +1565,6 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, bool *rightsib_empty)
|
|||||||
int targetlevel;
|
int targetlevel;
|
||||||
ItemPointer leafhikey;
|
ItemPointer leafhikey;
|
||||||
BlockNumber nextchild;
|
BlockNumber nextchild;
|
||||||
BlockNumber topblkno;
|
|
||||||
|
|
||||||
page = BufferGetPage(leafbuf);
|
page = BufferGetPage(leafbuf);
|
||||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||||
@ -1589,11 +1588,10 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, bool *rightsib_empty)
|
|||||||
*/
|
*/
|
||||||
if (ItemPointerIsValid(leafhikey))
|
if (ItemPointerIsValid(leafhikey))
|
||||||
{
|
{
|
||||||
topblkno = ItemPointerGetBlockNumber(leafhikey);
|
target = ItemPointerGetBlockNumber(leafhikey);
|
||||||
target = topblkno;
|
|
||||||
|
|
||||||
/* fetch the block number of the topmost parent's left sibling */
|
/* fetch the block number of the topmost parent's left sibling */
|
||||||
buf = _bt_getbuf(rel, topblkno, BT_READ);
|
buf = _bt_getbuf(rel, target, BT_READ);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||||
leftsib = opaque->btpo_prev;
|
leftsib = opaque->btpo_prev;
|
||||||
@ -1607,7 +1605,6 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, bool *rightsib_empty)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
topblkno = InvalidBlockNumber;
|
|
||||||
target = leafblkno;
|
target = leafblkno;
|
||||||
|
|
||||||
buf = leafbuf;
|
buf = leafbuf;
|
||||||
@ -1692,9 +1689,11 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, bool *rightsib_empty)
|
|||||||
elog(ERROR, "half-dead page changed status unexpectedly in block %u of index \"%s\"",
|
elog(ERROR, "half-dead page changed status unexpectedly in block %u of index \"%s\"",
|
||||||
target, RelationGetRelationName(rel));
|
target, RelationGetRelationName(rel));
|
||||||
|
|
||||||
/* remember the next child down in the branch. */
|
/* remember the next non-leaf child down in the branch. */
|
||||||
itemid = PageGetItemId(page, P_FIRSTDATAKEY(opaque));
|
itemid = PageGetItemId(page, P_FIRSTDATAKEY(opaque));
|
||||||
nextchild = ItemPointerGetBlockNumber(&((IndexTuple) PageGetItem(page, itemid))->t_tid);
|
nextchild = ItemPointerGetBlockNumber(&((IndexTuple) PageGetItem(page, itemid))->t_tid);
|
||||||
|
if (nextchild == leafblkno)
|
||||||
|
nextchild = InvalidBlockNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1780,7 +1779,7 @@ _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, bool *rightsib_empty)
|
|||||||
*/
|
*/
|
||||||
if (target != leafblkno)
|
if (target != leafblkno)
|
||||||
{
|
{
|
||||||
if (nextchild == leafblkno)
|
if (nextchild == InvalidBlockNumber)
|
||||||
ItemPointerSetInvalid(leafhikey);
|
ItemPointerSetInvalid(leafhikey);
|
||||||
else
|
else
|
||||||
ItemPointerSet(leafhikey, nextchild, P_HIKEY);
|
ItemPointerSet(leafhikey, nextchild, P_HIKEY);
|
||||||
|
Loading…
Reference in New Issue
Block a user