* Given an opened sequence relation, lock the page buffer and find the tuple * * *buf receives the reference to the pinned-and-ex-locked buffer * *seqdatatuple receives the reference to the sequence tuple proper * (this arg should point to a local variable of type HeapTupleData) * * Function's return value points to the data payload of the tuple */
| 1351 | * Function's return value points to the data payload of the tuple |
| 1352 | */ |
| 1353 | static Form_pg_sequence_data |
| 1354 | read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple) |
| 1355 | { |
| 1356 | Page page; |
| 1357 | ItemId lp; |
| 1358 | sequence_magic *sm; |
| 1359 | Form_pg_sequence_data seq; |
| 1360 | |
| 1361 | *buf = ReadBuffer(rel, 0); |
| 1362 | LockBuffer(*buf, BUFFER_LOCK_EXCLUSIVE); |
| 1363 | |
| 1364 | page = BufferGetPage(*buf); |
| 1365 | sm = (sequence_magic *) PageGetSpecialPointer(page); |
| 1366 | |
| 1367 | if (sm->magic != SEQ_MAGIC) |
| 1368 | elog(ERROR, "bad magic number in sequence \"%s\": %08X", |
| 1369 | RelationGetRelationName(rel), sm->magic); |
| 1370 | |
| 1371 | lp = PageGetItemId(page, FirstOffsetNumber); |
| 1372 | Assert(ItemIdIsNormal(lp)); |
| 1373 | |
| 1374 | /* Note we currently only bother to set these two fields of *seqdatatuple */ |
| 1375 | seqdatatuple->t_data = (HeapTupleHeader) PageGetItem(page, lp); |
| 1376 | seqdatatuple->t_len = ItemIdGetLength(lp); |
| 1377 | |
| 1378 | /* |
| 1379 | * Previous releases of Postgres neglected to prevent SELECT FOR UPDATE on |
| 1380 | * a sequence, which would leave a non-frozen XID in the sequence tuple's |
| 1381 | * xmax, which eventually leads to clog access failures or worse. If we |
| 1382 | * see this has happened, clean up after it. We treat this like a hint |
| 1383 | * bit update, ie, don't bother to WAL-log it, since we can certainly do |
| 1384 | * this again if the update gets lost. |
| 1385 | */ |
| 1386 | Assert(!(seqdatatuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI)); |
| 1387 | if (HeapTupleHeaderGetRawXmax(seqdatatuple->t_data) != InvalidTransactionId) |
| 1388 | { |
| 1389 | HeapTupleHeaderSetXmax(seqdatatuple->t_data, InvalidTransactionId); |
| 1390 | seqdatatuple->t_data->t_infomask &= ~HEAP_XMAX_COMMITTED; |
| 1391 | seqdatatuple->t_data->t_infomask |= HEAP_XMAX_INVALID; |
| 1392 | MarkBufferDirtyHint(*buf, true); |
| 1393 | } |
| 1394 | |
| 1395 | seq = (Form_pg_sequence_data) GETSTRUCT(seqdatatuple); |
| 1396 | |
| 1397 | return seq; |
| 1398 | } |
| 1399 | |
| 1400 | /* |
| 1401 | * init_params: process the options list of CREATE or ALTER SEQUENCE, and |
no test coverage detected