Skip to content

Commit 9ee00ef

Browse files
committed
Fill tuple before HeapSatisfiesHOTAndKeyUpdate
Failing to do this results in almost all updates to system catalogs being non-HOT updates, because the OID column would differ (not having been set for the new tuple), which is an indexed column. While at it, make sure to set the tableoid early in both old and new tuples as well. This isn't of much consequence, since that column is seldom (never?) indexed. Report and patch from Andres Freund.
1 parent 5839052 commit 9ee00ef

File tree

1 file changed

+24
-15
lines changed

1 file changed

+24
-15
lines changed

src/backend/access/heap/heapam.c

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2978,10 +2978,33 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
29782978
lp = PageGetItemId(page, ItemPointerGetOffsetNumber(otid));
29792979
Assert(ItemIdIsNormal(lp));
29802980

2981+
/*
2982+
* Fill in enough data in oldtup for HeapSatisfiesHOTandKeyUpdate to work
2983+
* properly.
2984+
*/
2985+
oldtup.t_tableOid = RelationGetRelid(relation);
29812986
oldtup.t_data = (HeapTupleHeader) PageGetItem(page, lp);
29822987
oldtup.t_len = ItemIdGetLength(lp);
29832988
oldtup.t_self = *otid;
29842989

2990+
/* the new tuple is ready, except for this: */
2991+
newtup->t_tableOid = RelationGetRelid(relation);
2992+
2993+
/* Fill in OID for newtup */
2994+
if (relation->rd_rel->relhasoids)
2995+
{
2996+
#ifdef NOT_USED
2997+
/* this is redundant with an Assert in HeapTupleSetOid */
2998+
Assert(newtup->t_data->t_infomask & HEAP_HASOID);
2999+
#endif
3000+
HeapTupleSetOid(newtup, HeapTupleGetOid(&oldtup));
3001+
}
3002+
else
3003+
{
3004+
/* check there is not space for an OID */
3005+
Assert(!(newtup->t_data->t_infomask & HEAP_HASOID));
3006+
}
3007+
29853008
/*
29863009
* If we're not updating any "key" column, we can grab a weaker lock type.
29873010
* This allows for more concurrency when we are running simultaneously with
@@ -3243,20 +3266,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
32433266
*/
32443267
CheckForSerializableConflictIn(relation, &oldtup, buffer);
32453268

3246-
/* Fill in OID and transaction status data for newtup */
3247-
if (relation->rd_rel->relhasoids)
3248-
{
3249-
#ifdef NOT_USED
3250-
/* this is redundant with an Assert in HeapTupleSetOid */
3251-
Assert(newtup->t_data->t_infomask & HEAP_HASOID);
3252-
#endif
3253-
HeapTupleSetOid(newtup, HeapTupleGetOid(&oldtup));
3254-
}
3255-
else
3256-
{
3257-
/* check there is not space for an OID */
3258-
Assert(!(newtup->t_data->t_infomask & HEAP_HASOID));
3259-
}
3269+
/* Fill in transaction status data */
32603270

32613271
/*
32623272
* If the tuple we're updating is locked, we need to preserve the locking
@@ -3318,7 +3328,6 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
33183328
newtup->t_data->t_infomask |= HEAP_UPDATED | infomask_new_tuple;
33193329
newtup->t_data->t_infomask2 |= infomask2_new_tuple;
33203330
HeapTupleHeaderSetXmax(newtup->t_data, xmax_new_tuple);
3321-
newtup->t_tableOid = RelationGetRelid(relation);
33223331

33233332
/*
33243333
* Replace cid with a combo cid if necessary. Note that we already put

0 commit comments

Comments
 (0)