diff options
Diffstat (limited to 'src/backend/catalog/index.c')
-rw-r--r-- | src/backend/catalog/index.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 061efd36a6a..df52ee9a363 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -2714,6 +2714,12 @@ IndexBuildHeapRangeScan(Relation heapRelation, * buffer continuously while visiting the page, so no pruning * operation can occur either. * + * In cases with only ShareUpdateExclusiveLock on the table, it's + * possible for some HOT tuples to appear that we didn't know about + * when we first read the page. To handle that case, we re-obtain the + * list of root offsets when a HOT tuple points to a root item that we + * don't know about. + * * Also, although our opinions about tuple liveness could change while * we scan the page (due to concurrent transaction commits/aborts), * the chain root locations won't, so this info doesn't need to be @@ -3013,6 +3019,20 @@ IndexBuildHeapRangeScan(Relation heapRelation, rootTuple = *heapTuple; offnum = ItemPointerGetOffsetNumber(&heapTuple->t_self); + /* + * If a HOT tuple points to a root that we don't know + * about, obtain root items afresh. If that still fails, + * report it as corruption. + */ + if (root_offsets[offnum - 1] == InvalidOffsetNumber) + { + Page page = BufferGetPage(scan->rs_cbuf); + + LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE); + heap_get_root_tuples(page, root_offsets); + LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK); + } + if (!OffsetNumberIsValid(root_offsets[offnum - 1])) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), |