mirror of
https://github.com/postgres/postgres.git
synced 2025-04-27 22:56:53 +03:00
Repair possible failure to update hint bits back to disk, per
http://archives.postgresql.org/pgsql-hackers/2004-10/msg00464.php. This fix is intended to be permanent: it moves the responsibility for calling SetBufferCommitInfoNeedsSave() into the tqual.c routines, eliminating the requirement for callers to test whether t_infomask changed. Also, tighten validity checking on buffer IDs in bufmgr.c --- several routines were paranoid about out-of-range shared buffer numbers but not about out-of-range local ones, which seems a tad pointless.
This commit is contained in:
parent
db9e2fd0a9
commit
9ffc8ed58b
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.16 2004/08/29 05:06:37 momjian Exp $
|
* $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.17 2004/10/15 22:39:38 tgl Exp $
|
||||||
*
|
*
|
||||||
* Copyright (c) 2001,2002 Tatsuo Ishii
|
* Copyright (c) 2001,2002 Tatsuo Ishii
|
||||||
*
|
*
|
||||||
@ -134,7 +134,10 @@ pgstattuple_real(Relation rel)
|
|||||||
/* scan the relation */
|
/* scan the relation */
|
||||||
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
|
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
|
||||||
{
|
{
|
||||||
if (HeapTupleSatisfiesNow(tuple->t_data))
|
/* must hold a buffer lock to call HeapTupleSatisfiesNow */
|
||||||
|
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
|
||||||
|
|
||||||
|
if (HeapTupleSatisfiesNow(tuple->t_data, scan->rs_cbuf))
|
||||||
{
|
{
|
||||||
tuple_len += tuple->t_len;
|
tuple_len += tuple->t_len;
|
||||||
tuple_count++;
|
tuple_count++;
|
||||||
@ -145,6 +148,8 @@ pgstattuple_real(Relation rel)
|
|||||||
dead_tuple_count++;
|
dead_tuple_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To avoid physically reading the table twice, try to do the
|
* To avoid physically reading the table twice, try to do the
|
||||||
* free-space scan in parallel with the heap scan. However,
|
* free-space scan in parallel with the heap scan. However,
|
||||||
@ -156,7 +161,9 @@ pgstattuple_real(Relation rel)
|
|||||||
while (block <= tupblock)
|
while (block <= tupblock)
|
||||||
{
|
{
|
||||||
buffer = ReadBuffer(rel, block);
|
buffer = ReadBuffer(rel, block);
|
||||||
|
LockBuffer(buffer, BUFFER_LOCK_SHARE);
|
||||||
free_space += PageGetFreeSpace((Page) BufferGetPage(buffer));
|
free_space += PageGetFreeSpace((Page) BufferGetPage(buffer));
|
||||||
|
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||||
ReleaseBuffer(buffer);
|
ReleaseBuffer(buffer);
|
||||||
block++;
|
block++;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.178 2004/10/12 21:54:34 petere Exp $
|
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.179 2004/10/15 22:39:42 tgl Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
@ -1314,7 +1314,7 @@ heap_delete(Relation relation, ItemPointer tid,
|
|||||||
tp.t_tableOid = relation->rd_id;
|
tp.t_tableOid = relation->rd_id;
|
||||||
|
|
||||||
l1:
|
l1:
|
||||||
result = HeapTupleSatisfiesUpdate(tp.t_data, cid);
|
result = HeapTupleSatisfiesUpdate(tp.t_data, cid, buffer);
|
||||||
|
|
||||||
if (result == HeapTupleInvisible)
|
if (result == HeapTupleInvisible)
|
||||||
{
|
{
|
||||||
@ -1331,7 +1331,7 @@ l1:
|
|||||||
XactLockTableWait(xwait);
|
XactLockTableWait(xwait);
|
||||||
|
|
||||||
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
|
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
|
||||||
if (TransactionIdDidAbort(xwait))
|
if (!TransactionIdDidCommit(xwait))
|
||||||
goto l1;
|
goto l1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1356,7 +1356,7 @@ l1:
|
|||||||
if (crosscheck != InvalidSnapshot && result == HeapTupleMayBeUpdated)
|
if (crosscheck != InvalidSnapshot && result == HeapTupleMayBeUpdated)
|
||||||
{
|
{
|
||||||
/* Perform additional check for serializable RI updates */
|
/* Perform additional check for serializable RI updates */
|
||||||
if (!HeapTupleSatisfiesSnapshot(tp.t_data, crosscheck))
|
if (!HeapTupleSatisfiesSnapshot(tp.t_data, crosscheck, buffer))
|
||||||
result = HeapTupleUpdated;
|
result = HeapTupleUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1543,7 +1543,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
l2:
|
l2:
|
||||||
result = HeapTupleSatisfiesUpdate(oldtup.t_data, cid);
|
result = HeapTupleSatisfiesUpdate(oldtup.t_data, cid, buffer);
|
||||||
|
|
||||||
if (result == HeapTupleInvisible)
|
if (result == HeapTupleInvisible)
|
||||||
{
|
{
|
||||||
@ -1560,7 +1560,7 @@ l2:
|
|||||||
XactLockTableWait(xwait);
|
XactLockTableWait(xwait);
|
||||||
|
|
||||||
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
|
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
|
||||||
if (TransactionIdDidAbort(xwait))
|
if (!TransactionIdDidCommit(xwait))
|
||||||
goto l2;
|
goto l2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1585,7 +1585,7 @@ l2:
|
|||||||
if (crosscheck != InvalidSnapshot && result == HeapTupleMayBeUpdated)
|
if (crosscheck != InvalidSnapshot && result == HeapTupleMayBeUpdated)
|
||||||
{
|
{
|
||||||
/* Perform additional check for serializable RI updates */
|
/* Perform additional check for serializable RI updates */
|
||||||
if (!HeapTupleSatisfiesSnapshot(oldtup.t_data, crosscheck))
|
if (!HeapTupleSatisfiesSnapshot(oldtup.t_data, crosscheck, buffer))
|
||||||
result = HeapTupleUpdated;
|
result = HeapTupleUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1871,7 +1871,7 @@ heap_mark4update(Relation relation, HeapTuple tuple, Buffer *buffer,
|
|||||||
tuple->t_len = ItemIdGetLength(lp);
|
tuple->t_len = ItemIdGetLength(lp);
|
||||||
|
|
||||||
l3:
|
l3:
|
||||||
result = HeapTupleSatisfiesUpdate(tuple->t_data, cid);
|
result = HeapTupleSatisfiesUpdate(tuple->t_data, cid, *buffer);
|
||||||
|
|
||||||
if (result == HeapTupleInvisible)
|
if (result == HeapTupleInvisible)
|
||||||
{
|
{
|
||||||
@ -1888,7 +1888,7 @@ l3:
|
|||||||
XactLockTableWait(xwait);
|
XactLockTableWait(xwait);
|
||||||
|
|
||||||
LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
|
LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
|
||||||
if (TransactionIdDidAbort(xwait))
|
if (!TransactionIdDidCommit(xwait))
|
||||||
goto l3;
|
goto l3;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.75 2004/09/30 23:21:14 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.76 2004/10/15 22:39:46 tgl Exp $
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
* index_open - open an index relation by relation OID
|
* index_open - open an index relation by relation OID
|
||||||
@ -497,7 +497,6 @@ index_getnext(IndexScanDesc scan, ScanDirection direction)
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
bool found;
|
bool found;
|
||||||
uint16 sv_infomask;
|
|
||||||
|
|
||||||
pgstat_count_index_scan(&scan->xs_pgstat_info);
|
pgstat_count_index_scan(&scan->xs_pgstat_info);
|
||||||
|
|
||||||
@ -541,19 +540,14 @@ index_getnext(IndexScanDesc scan, ScanDirection direction)
|
|||||||
* index AM to not return it on future indexscans.
|
* index AM to not return it on future indexscans.
|
||||||
*
|
*
|
||||||
* We told heap_release_fetch to keep a pin on the buffer, so we can
|
* We told heap_release_fetch to keep a pin on the buffer, so we can
|
||||||
* re-access the tuple here. But we must re-lock the buffer
|
* re-access the tuple here. But we must re-lock the buffer first.
|
||||||
* first. Also, it's just barely possible for an update of hint
|
|
||||||
* bits to occur here.
|
|
||||||
*/
|
*/
|
||||||
LockBuffer(scan->xs_cbuf, BUFFER_LOCK_SHARE);
|
LockBuffer(scan->xs_cbuf, BUFFER_LOCK_SHARE);
|
||||||
sv_infomask = heapTuple->t_data->t_infomask;
|
|
||||||
|
|
||||||
if (HeapTupleSatisfiesVacuum(heapTuple->t_data, RecentGlobalXmin) ==
|
if (HeapTupleSatisfiesVacuum(heapTuple->t_data, RecentGlobalXmin,
|
||||||
HEAPTUPLE_DEAD)
|
scan->xs_cbuf) == HEAPTUPLE_DEAD)
|
||||||
scan->kill_prior_tuple = true;
|
scan->kill_prior_tuple = true;
|
||||||
|
|
||||||
if (sv_infomask != heapTuple->t_data->t_infomask)
|
|
||||||
SetBufferCommitInfoNeedsSave(scan->xs_cbuf);
|
|
||||||
LockBuffer(scan->xs_cbuf, BUFFER_LOCK_UNLOCK);
|
LockBuffer(scan->xs_cbuf, BUFFER_LOCK_UNLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.116 2004/08/29 05:06:40 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.117 2004/10/15 22:39:49 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -261,19 +261,13 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
|
|||||||
* marked killed. This logic should match
|
* marked killed. This logic should match
|
||||||
* index_getnext and btgettuple.
|
* index_getnext and btgettuple.
|
||||||
*/
|
*/
|
||||||
uint16 sv_infomask;
|
|
||||||
|
|
||||||
LockBuffer(hbuffer, BUFFER_LOCK_SHARE);
|
LockBuffer(hbuffer, BUFFER_LOCK_SHARE);
|
||||||
sv_infomask = htup.t_data->t_infomask;
|
if (HeapTupleSatisfiesVacuum(htup.t_data, RecentGlobalXmin,
|
||||||
if (HeapTupleSatisfiesVacuum(htup.t_data,
|
hbuffer) == HEAPTUPLE_DEAD)
|
||||||
RecentGlobalXmin) ==
|
|
||||||
HEAPTUPLE_DEAD)
|
|
||||||
{
|
{
|
||||||
curitemid->lp_flags |= LP_DELETE;
|
curitemid->lp_flags |= LP_DELETE;
|
||||||
SetBufferCommitInfoNeedsSave(buf);
|
SetBufferCommitInfoNeedsSave(buf);
|
||||||
}
|
}
|
||||||
if (sv_infomask != htup.t_data->t_infomask)
|
|
||||||
SetBufferCommitInfoNeedsSave(hbuffer);
|
|
||||||
LockBuffer(hbuffer, BUFFER_LOCK_UNLOCK);
|
LockBuffer(hbuffer, BUFFER_LOCK_UNLOCK);
|
||||||
ReleaseBuffer(hbuffer);
|
ReleaseBuffer(hbuffer);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.240 2004/10/01 17:11:49 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.241 2004/10/15 22:39:53 tgl Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
@ -1472,18 +1472,16 @@ IndexBuildHeapScan(Relation heapRelation,
|
|||||||
{
|
{
|
||||||
/* do our own time qual check */
|
/* do our own time qual check */
|
||||||
bool indexIt;
|
bool indexIt;
|
||||||
uint16 sv_infomask;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* HeapTupleSatisfiesVacuum may update tuple's hint status
|
* We could possibly get away with not locking the buffer here,
|
||||||
* bits. We could possibly get away with not locking the
|
* since caller should hold ShareLock on the relation, but let's
|
||||||
* buffer here, since caller should hold ShareLock on the
|
* be conservative about it.
|
||||||
* relation, but let's be conservative about it.
|
|
||||||
*/
|
*/
|
||||||
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
|
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
|
||||||
sv_infomask = heapTuple->t_data->t_infomask;
|
|
||||||
|
|
||||||
switch (HeapTupleSatisfiesVacuum(heapTuple->t_data, OldestXmin))
|
switch (HeapTupleSatisfiesVacuum(heapTuple->t_data, OldestXmin,
|
||||||
|
scan->rs_cbuf))
|
||||||
{
|
{
|
||||||
case HEAPTUPLE_DEAD:
|
case HEAPTUPLE_DEAD:
|
||||||
indexIt = false;
|
indexIt = false;
|
||||||
@ -1544,10 +1542,6 @@ IndexBuildHeapScan(Relation heapRelation,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for hint-bit update by HeapTupleSatisfiesVacuum */
|
|
||||||
if (sv_infomask != heapTuple->t_data->t_infomask)
|
|
||||||
SetBufferCommitInfoNeedsSave(scan->rs_cbuf);
|
|
||||||
|
|
||||||
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
|
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
|
||||||
|
|
||||||
if (!indexIt)
|
if (!indexIt)
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.294 2004/10/07 14:19:58 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.295 2004/10/15 22:39:56 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1190,6 +1190,12 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
buf = ReadBuffer(onerel, blkno);
|
buf = ReadBuffer(onerel, blkno);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We don't bother to do LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE)
|
||||||
|
* because we assume that holding exclusive lock on the relation
|
||||||
|
* will keep other backends from looking at the page.
|
||||||
|
*/
|
||||||
|
|
||||||
vacpage->blkno = blkno;
|
vacpage->blkno = blkno;
|
||||||
vacpage->offsets_used = 0;
|
vacpage->offsets_used = 0;
|
||||||
vacpage->offsets_free = 0;
|
vacpage->offsets_free = 0;
|
||||||
@ -1235,7 +1241,6 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
offnum <= maxoff;
|
offnum <= maxoff;
|
||||||
offnum = OffsetNumberNext(offnum))
|
offnum = OffsetNumberNext(offnum))
|
||||||
{
|
{
|
||||||
uint16 sv_infomask;
|
|
||||||
ItemId itemid = PageGetItemId(page, offnum);
|
ItemId itemid = PageGetItemId(page, offnum);
|
||||||
bool tupgone = false;
|
bool tupgone = false;
|
||||||
|
|
||||||
@ -1255,9 +1260,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
tuple.t_len = ItemIdGetLength(itemid);
|
tuple.t_len = ItemIdGetLength(itemid);
|
||||||
ItemPointerSet(&(tuple.t_self), blkno, offnum);
|
ItemPointerSet(&(tuple.t_self), blkno, offnum);
|
||||||
|
|
||||||
sv_infomask = tuple.t_data->t_infomask;
|
switch (HeapTupleSatisfiesVacuum(tuple.t_data, OldestXmin, buf))
|
||||||
|
|
||||||
switch (HeapTupleSatisfiesVacuum(tuple.t_data, OldestXmin))
|
|
||||||
{
|
{
|
||||||
case HEAPTUPLE_DEAD:
|
case HEAPTUPLE_DEAD:
|
||||||
tupgone = true; /* we can delete the tuple */
|
tupgone = true; /* we can delete the tuple */
|
||||||
@ -1348,10 +1351,6 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for hint-bit update by HeapTupleSatisfiesVacuum */
|
|
||||||
if (sv_infomask != tuple.t_data->t_infomask)
|
|
||||||
pgchanged = true;
|
|
||||||
|
|
||||||
if (tupgone)
|
if (tupgone)
|
||||||
{
|
{
|
||||||
ItemId lpp;
|
ItemId lpp;
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.46 2004/09/30 23:21:19 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.47 2004/10/15 22:39:56 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -291,7 +291,6 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
|
|||||||
offnum = OffsetNumberNext(offnum))
|
offnum = OffsetNumberNext(offnum))
|
||||||
{
|
{
|
||||||
ItemId itemid;
|
ItemId itemid;
|
||||||
uint16 sv_infomask;
|
|
||||||
|
|
||||||
itemid = PageGetItemId(page, offnum);
|
itemid = PageGetItemId(page, offnum);
|
||||||
|
|
||||||
@ -307,9 +306,8 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
|
|||||||
ItemPointerSet(&(tuple.t_self), blkno, offnum);
|
ItemPointerSet(&(tuple.t_self), blkno, offnum);
|
||||||
|
|
||||||
tupgone = false;
|
tupgone = false;
|
||||||
sv_infomask = tuple.t_data->t_infomask;
|
|
||||||
|
|
||||||
switch (HeapTupleSatisfiesVacuum(tuple.t_data, OldestXmin))
|
switch (HeapTupleSatisfiesVacuum(tuple.t_data, OldestXmin, buf))
|
||||||
{
|
{
|
||||||
case HEAPTUPLE_DEAD:
|
case HEAPTUPLE_DEAD:
|
||||||
tupgone = true; /* we can delete the tuple */
|
tupgone = true; /* we can delete the tuple */
|
||||||
@ -364,10 +362,6 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for hint-bit update by HeapTupleSatisfiesVacuum */
|
|
||||||
if (sv_infomask != tuple.t_data->t_infomask)
|
|
||||||
pgchanged = true;
|
|
||||||
|
|
||||||
if (tupgone)
|
if (tupgone)
|
||||||
{
|
{
|
||||||
lazy_record_dead_tuple(vacrelstats, &(tuple.t_self));
|
lazy_record_dead_tuple(vacrelstats, &(tuple.t_self));
|
||||||
@ -399,8 +393,8 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
|
|||||||
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
|
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
|
||||||
|
|
||||||
if (pgchanged)
|
if (pgchanged)
|
||||||
SetBufferCommitInfoNeedsSave(buf);
|
WriteBuffer(buf);
|
||||||
|
else
|
||||||
ReleaseBuffer(buf);
|
ReleaseBuffer(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -790,8 +784,7 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
|
|||||||
Page page;
|
Page page;
|
||||||
OffsetNumber offnum,
|
OffsetNumber offnum,
|
||||||
maxoff;
|
maxoff;
|
||||||
bool pgchanged,
|
bool tupgone,
|
||||||
tupgone,
|
|
||||||
hastup;
|
hastup;
|
||||||
|
|
||||||
vacuum_delay_point();
|
vacuum_delay_point();
|
||||||
@ -813,7 +806,6 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pgchanged = false;
|
|
||||||
hastup = false;
|
hastup = false;
|
||||||
maxoff = PageGetMaxOffsetNumber(page);
|
maxoff = PageGetMaxOffsetNumber(page);
|
||||||
for (offnum = FirstOffsetNumber;
|
for (offnum = FirstOffsetNumber;
|
||||||
@ -821,7 +813,6 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
|
|||||||
offnum = OffsetNumberNext(offnum))
|
offnum = OffsetNumberNext(offnum))
|
||||||
{
|
{
|
||||||
ItemId itemid;
|
ItemId itemid;
|
||||||
uint16 sv_infomask;
|
|
||||||
|
|
||||||
itemid = PageGetItemId(page, offnum);
|
itemid = PageGetItemId(page, offnum);
|
||||||
|
|
||||||
@ -834,9 +825,8 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
|
|||||||
ItemPointerSet(&(tuple.t_self), blkno, offnum);
|
ItemPointerSet(&(tuple.t_self), blkno, offnum);
|
||||||
|
|
||||||
tupgone = false;
|
tupgone = false;
|
||||||
sv_infomask = tuple.t_data->t_infomask;
|
|
||||||
|
|
||||||
switch (HeapTupleSatisfiesVacuum(tuple.t_data, OldestXmin))
|
switch (HeapTupleSatisfiesVacuum(tuple.t_data, OldestXmin, buf))
|
||||||
{
|
{
|
||||||
case HEAPTUPLE_DEAD:
|
case HEAPTUPLE_DEAD:
|
||||||
tupgone = true; /* we can delete the tuple */
|
tupgone = true; /* we can delete the tuple */
|
||||||
@ -862,10 +852,6 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for hint-bit update by HeapTupleSatisfiesVacuum */
|
|
||||||
if (sv_infomask != tuple.t_data->t_infomask)
|
|
||||||
pgchanged = true;
|
|
||||||
|
|
||||||
if (!tupgone)
|
if (!tupgone)
|
||||||
{
|
{
|
||||||
hastup = true;
|
hastup = true;
|
||||||
@ -875,9 +861,6 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
|
|||||||
|
|
||||||
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
|
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
|
||||||
|
|
||||||
if (pgchanged)
|
|
||||||
WriteBuffer(buf);
|
|
||||||
else
|
|
||||||
ReleaseBuffer(buf);
|
ReleaseBuffer(buf);
|
||||||
|
|
||||||
/* Done scanning if we found a tuple here */
|
/* Done scanning if we found a tuple here */
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.177 2004/09/06 17:31:32 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.178 2004/10/15 22:39:59 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -477,15 +477,15 @@ write_buffer(Buffer buffer, bool release)
|
|||||||
{
|
{
|
||||||
BufferDesc *bufHdr;
|
BufferDesc *bufHdr;
|
||||||
|
|
||||||
|
if (!BufferIsValid(buffer))
|
||||||
|
elog(ERROR, "bad buffer id: %d", buffer);
|
||||||
|
|
||||||
if (BufferIsLocal(buffer))
|
if (BufferIsLocal(buffer))
|
||||||
{
|
{
|
||||||
WriteLocalBuffer(buffer, release);
|
WriteLocalBuffer(buffer, release);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BAD_BUFFER_ID(buffer))
|
|
||||||
elog(ERROR, "bad buffer id: %d", buffer);
|
|
||||||
|
|
||||||
bufHdr = &BufferDescriptors[buffer - 1];
|
bufHdr = &BufferDescriptors[buffer - 1];
|
||||||
|
|
||||||
Assert(PrivateRefCount[buffer - 1] > 0);
|
Assert(PrivateRefCount[buffer - 1] > 0);
|
||||||
@ -1465,6 +1465,9 @@ ReleaseBuffer(Buffer buffer)
|
|||||||
{
|
{
|
||||||
BufferDesc *bufHdr;
|
BufferDesc *bufHdr;
|
||||||
|
|
||||||
|
if (!BufferIsValid(buffer))
|
||||||
|
elog(ERROR, "bad buffer id: %d", buffer);
|
||||||
|
|
||||||
ResourceOwnerForgetBuffer(CurrentResourceOwner, buffer);
|
ResourceOwnerForgetBuffer(CurrentResourceOwner, buffer);
|
||||||
|
|
||||||
if (BufferIsLocal(buffer))
|
if (BufferIsLocal(buffer))
|
||||||
@ -1474,9 +1477,6 @@ ReleaseBuffer(Buffer buffer)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BAD_BUFFER_ID(buffer))
|
|
||||||
elog(ERROR, "bad buffer id: %d", buffer);
|
|
||||||
|
|
||||||
bufHdr = &BufferDescriptors[buffer - 1];
|
bufHdr = &BufferDescriptors[buffer - 1];
|
||||||
|
|
||||||
Assert(PrivateRefCount[buffer - 1] > 0);
|
Assert(PrivateRefCount[buffer - 1] > 0);
|
||||||
@ -1503,17 +1503,16 @@ ReleaseBuffer(Buffer buffer)
|
|||||||
void
|
void
|
||||||
IncrBufferRefCount(Buffer buffer)
|
IncrBufferRefCount(Buffer buffer)
|
||||||
{
|
{
|
||||||
|
Assert(BufferIsValid(buffer));
|
||||||
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
|
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
|
||||||
ResourceOwnerRememberBuffer(CurrentResourceOwner, buffer);
|
ResourceOwnerRememberBuffer(CurrentResourceOwner, buffer);
|
||||||
if (BufferIsLocal(buffer))
|
if (BufferIsLocal(buffer))
|
||||||
{
|
{
|
||||||
Assert(buffer >= -NLocBuffer);
|
|
||||||
Assert(LocalRefCount[-buffer - 1] > 0);
|
Assert(LocalRefCount[-buffer - 1] > 0);
|
||||||
LocalRefCount[-buffer - 1]++;
|
LocalRefCount[-buffer - 1]++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Assert(!BAD_BUFFER_ID(buffer));
|
|
||||||
Assert(PrivateRefCount[buffer - 1] > 0);
|
Assert(PrivateRefCount[buffer - 1] > 0);
|
||||||
PrivateRefCount[buffer - 1]++;
|
PrivateRefCount[buffer - 1]++;
|
||||||
}
|
}
|
||||||
@ -1606,9 +1605,12 @@ ReleaseAndReadBuffer_Debug(char *file,
|
|||||||
*
|
*
|
||||||
* Mark a buffer dirty when we have updated tuple commit-status bits in it.
|
* Mark a buffer dirty when we have updated tuple commit-status bits in it.
|
||||||
*
|
*
|
||||||
* This is similar to WriteNoReleaseBuffer, except that we have not made a
|
* This is essentially the same as WriteNoReleaseBuffer. We preserve the
|
||||||
* critical change that has to be flushed to disk before xact commit --- the
|
* distinction as a way of documenting that the caller has not made a critical
|
||||||
* status-bit update could be redone by someone else just as easily.
|
* data change --- the status-bit update could be redone by someone else just
|
||||||
|
* as easily. Therefore, no WAL log record need be generated, whereas calls
|
||||||
|
* to WriteNoReleaseBuffer really ought to be associated with a WAL-entry-
|
||||||
|
* creating action.
|
||||||
*
|
*
|
||||||
* This routine might get called many times on the same page, if we are making
|
* This routine might get called many times on the same page, if we are making
|
||||||
* the first scan after commit of an xact that added/deleted many tuples.
|
* the first scan after commit of an xact that added/deleted many tuples.
|
||||||
@ -1623,15 +1625,15 @@ SetBufferCommitInfoNeedsSave(Buffer buffer)
|
|||||||
{
|
{
|
||||||
BufferDesc *bufHdr;
|
BufferDesc *bufHdr;
|
||||||
|
|
||||||
|
if (!BufferIsValid(buffer))
|
||||||
|
elog(ERROR, "bad buffer id: %d", buffer);
|
||||||
|
|
||||||
if (BufferIsLocal(buffer))
|
if (BufferIsLocal(buffer))
|
||||||
{
|
{
|
||||||
WriteLocalBuffer(buffer, false);
|
WriteLocalBuffer(buffer, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BAD_BUFFER_ID(buffer))
|
|
||||||
elog(ERROR, "bad buffer id: %d", buffer);
|
|
||||||
|
|
||||||
bufHdr = &BufferDescriptors[buffer - 1];
|
bufHdr = &BufferDescriptors[buffer - 1];
|
||||||
|
|
||||||
if ((bufHdr->flags & (BM_DIRTY | BM_JUST_DIRTIED)) !=
|
if ((bufHdr->flags & (BM_DIRTY | BM_JUST_DIRTIED)) !=
|
||||||
@ -1662,7 +1664,6 @@ UnlockBuffers(void)
|
|||||||
if (buflocks == 0)
|
if (buflocks == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Assert(BufferIsValid(i + 1));
|
|
||||||
buf = &(BufferDescriptors[i]);
|
buf = &(BufferDescriptors[i]);
|
||||||
|
|
||||||
HOLD_INTERRUPTS(); /* don't want to die() partway through... */
|
HOLD_INTERRUPTS(); /* don't want to die() partway through... */
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.73 2004/09/13 20:07:13 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.74 2004/10/15 22:40:11 tgl Exp $
|
||||||
*
|
*
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
@ -224,10 +224,15 @@ RI_FKey_check(PG_FUNCTION_ARGS)
|
|||||||
* We should not even consider checking the row if it is no longer
|
* We should not even consider checking the row if it is no longer
|
||||||
* valid since it was either deleted (doesn't matter) or updated (in
|
* valid since it was either deleted (doesn't matter) or updated (in
|
||||||
* which case it'll be checked with its final values).
|
* which case it'll be checked with its final values).
|
||||||
|
*
|
||||||
|
* We do not know what buffer the new_row is in, but it doesn't matter
|
||||||
|
* since it's not possible for a hint-bit update to occur here (the
|
||||||
|
* new_row could only contain our own XID, and we haven't yet committed
|
||||||
|
* or aborted...)
|
||||||
*/
|
*/
|
||||||
if (new_row)
|
if (new_row)
|
||||||
{
|
{
|
||||||
if (!HeapTupleSatisfiesItself(new_row->t_data))
|
if (!HeapTupleSatisfiesItself(new_row->t_data, InvalidBuffer))
|
||||||
{
|
{
|
||||||
heap_close(pk_rel, RowShareLock);
|
heap_close(pk_rel, RowShareLock);
|
||||||
return PointerGetDatum(NULL);
|
return PointerGetDatum(NULL);
|
||||||
|
@ -3,20 +3,20 @@
|
|||||||
* tqual.c
|
* tqual.c
|
||||||
* POSTGRES "time" qualification code, ie, tuple visibility rules.
|
* POSTGRES "time" qualification code, ie, tuple visibility rules.
|
||||||
*
|
*
|
||||||
* NOTE: all the HeapTupleSatisfies routines will update the tuple's
|
* The caller must hold at least a shared buffer context lock on the buffer
|
||||||
* "hint" status bits if we see that the inserting or deleting transaction
|
|
||||||
* has now committed or aborted. The caller is responsible for noticing any
|
|
||||||
* change in t_infomask and scheduling a disk write if so. Note that the
|
|
||||||
* caller must hold at least a shared buffer context lock on the buffer
|
|
||||||
* containing the tuple. (VACUUM FULL assumes it's sufficient to have
|
* containing the tuple. (VACUUM FULL assumes it's sufficient to have
|
||||||
* exclusive lock on the containing relation, instead.)
|
* exclusive lock on the containing relation, instead.)
|
||||||
*
|
*
|
||||||
|
* NOTE: all the HeapTupleSatisfies routines will update the tuple's
|
||||||
|
* "hint" status bits if we see that the inserting or deleting transaction
|
||||||
|
* has now committed or aborted.
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.79 2004/09/16 18:35:22 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.80 2004/10/15 22:40:16 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -78,7 +78,7 @@ TransactionId RecentGlobalXmin = InvalidTransactionId;
|
|||||||
* Xmax is not committed))) that has not been committed
|
* Xmax is not committed))) that has not been committed
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
HeapTupleSatisfiesItself(HeapTupleHeader tuple)
|
HeapTupleSatisfiesItself(HeapTupleHeader tuple, Buffer buffer)
|
||||||
{
|
{
|
||||||
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
|
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
|
||||||
{
|
{
|
||||||
@ -96,9 +96,11 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
|
|||||||
if (TransactionIdDidCommit(xvac))
|
if (TransactionIdDidCommit(xvac))
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tuple->t_infomask & HEAP_MOVED_IN)
|
else if (tuple->t_infomask & HEAP_MOVED_IN)
|
||||||
@ -110,10 +112,14 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
|
|||||||
if (TransactionIdIsInProgress(xvac))
|
if (TransactionIdIsInProgress(xvac))
|
||||||
return false;
|
return false;
|
||||||
if (TransactionIdDidCommit(xvac))
|
if (TransactionIdDidCommit(xvac))
|
||||||
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,6 +133,7 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
|
|||||||
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,11 +147,17 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
|
|||||||
else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
|
else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
|
||||||
{
|
{
|
||||||
if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
|
if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
|
{
|
||||||
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* by here, the inserting transaction has committed */
|
/* by here, the inserting transaction has committed */
|
||||||
@ -169,7 +182,10 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
|
|||||||
if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
|
if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
|
||||||
{
|
{
|
||||||
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
||||||
tuple->t_infomask |= HEAP_XMAX_INVALID; /* aborted */
|
{
|
||||||
|
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,10 +194,12 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
|
|||||||
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
|
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
|
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +246,7 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
|
|||||||
* that do catalog accesses. this is unfortunate, but not critical.
|
* that do catalog accesses. this is unfortunate, but not critical.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
HeapTupleSatisfiesNow(HeapTupleHeader tuple)
|
HeapTupleSatisfiesNow(HeapTupleHeader tuple, Buffer buffer)
|
||||||
{
|
{
|
||||||
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
|
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
|
||||||
{
|
{
|
||||||
@ -246,9 +264,11 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
|
|||||||
if (TransactionIdDidCommit(xvac))
|
if (TransactionIdDidCommit(xvac))
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tuple->t_infomask & HEAP_MOVED_IN)
|
else if (tuple->t_infomask & HEAP_MOVED_IN)
|
||||||
@ -260,10 +280,14 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
|
|||||||
if (TransactionIdIsInProgress(xvac))
|
if (TransactionIdIsInProgress(xvac))
|
||||||
return false;
|
return false;
|
||||||
if (TransactionIdDidCommit(xvac))
|
if (TransactionIdDidCommit(xvac))
|
||||||
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -280,6 +304,7 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
|
|||||||
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,11 +321,17 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
|
|||||||
else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
|
else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
|
||||||
{
|
{
|
||||||
if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
|
if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
|
{
|
||||||
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* by here, the inserting transaction has committed */
|
/* by here, the inserting transaction has committed */
|
||||||
@ -328,7 +359,10 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
|
|||||||
if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
|
if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
|
||||||
{
|
{
|
||||||
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
||||||
tuple->t_infomask |= HEAP_XMAX_INVALID; /* aborted */
|
{
|
||||||
|
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,10 +371,12 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
|
|||||||
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
|
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
|
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,7 +395,7 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
|
|||||||
* table.
|
* table.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
HeapTupleSatisfiesToast(HeapTupleHeader tuple)
|
HeapTupleSatisfiesToast(HeapTupleHeader tuple, Buffer buffer)
|
||||||
{
|
{
|
||||||
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
|
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
|
||||||
{
|
{
|
||||||
@ -377,9 +413,11 @@ HeapTupleSatisfiesToast(HeapTupleHeader tuple)
|
|||||||
if (TransactionIdDidCommit(xvac))
|
if (TransactionIdDidCommit(xvac))
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tuple->t_infomask & HEAP_MOVED_IN)
|
else if (tuple->t_infomask & HEAP_MOVED_IN)
|
||||||
@ -391,10 +429,14 @@ HeapTupleSatisfiesToast(HeapTupleHeader tuple)
|
|||||||
if (TransactionIdIsInProgress(xvac))
|
if (TransactionIdIsInProgress(xvac))
|
||||||
return false;
|
return false;
|
||||||
if (TransactionIdDidCommit(xvac))
|
if (TransactionIdDidCommit(xvac))
|
||||||
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -414,7 +456,8 @@ HeapTupleSatisfiesToast(HeapTupleHeader tuple)
|
|||||||
* CurrentCommandId.
|
* CurrentCommandId.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid)
|
HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
|
||||||
|
Buffer buffer)
|
||||||
{
|
{
|
||||||
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
|
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
|
||||||
{
|
{
|
||||||
@ -432,9 +475,11 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid)
|
|||||||
if (TransactionIdDidCommit(xvac))
|
if (TransactionIdDidCommit(xvac))
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return HeapTupleInvisible;
|
return HeapTupleInvisible;
|
||||||
}
|
}
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tuple->t_infomask & HEAP_MOVED_IN)
|
else if (tuple->t_infomask & HEAP_MOVED_IN)
|
||||||
@ -446,10 +491,14 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid)
|
|||||||
if (TransactionIdIsInProgress(xvac))
|
if (TransactionIdIsInProgress(xvac))
|
||||||
return HeapTupleInvisible;
|
return HeapTupleInvisible;
|
||||||
if (TransactionIdDidCommit(xvac))
|
if (TransactionIdDidCommit(xvac))
|
||||||
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return HeapTupleInvisible;
|
return HeapTupleInvisible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -467,6 +516,7 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid)
|
|||||||
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return HeapTupleMayBeUpdated;
|
return HeapTupleMayBeUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,11 +535,17 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid)
|
|||||||
else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
|
else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
|
||||||
{
|
{
|
||||||
if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
|
if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
|
{
|
||||||
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
return HeapTupleInvisible;
|
return HeapTupleInvisible;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* by here, the inserting transaction has committed */
|
/* by here, the inserting transaction has committed */
|
||||||
@ -519,7 +575,8 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid)
|
|||||||
{
|
{
|
||||||
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMAX_INVALID; /* aborted */
|
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return HeapTupleMayBeUpdated;
|
return HeapTupleMayBeUpdated;
|
||||||
}
|
}
|
||||||
/* running xact */
|
/* running xact */
|
||||||
@ -531,10 +588,12 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid)
|
|||||||
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
|
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return HeapTupleMayBeUpdated;
|
return HeapTupleMayBeUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
|
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return HeapTupleUpdated; /* updated by other */
|
return HeapTupleUpdated; /* updated by other */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -556,7 +615,7 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid)
|
|||||||
* t_ctid (forward link) is returned if it's being updated.
|
* t_ctid (forward link) is returned if it's being updated.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
|
HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Buffer buffer)
|
||||||
{
|
{
|
||||||
SnapshotDirty->xmin = SnapshotDirty->xmax = InvalidTransactionId;
|
SnapshotDirty->xmin = SnapshotDirty->xmax = InvalidTransactionId;
|
||||||
ItemPointerSetInvalid(&(SnapshotDirty->tid));
|
ItemPointerSetInvalid(&(SnapshotDirty->tid));
|
||||||
@ -577,9 +636,11 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
|
|||||||
if (TransactionIdDidCommit(xvac))
|
if (TransactionIdDidCommit(xvac))
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tuple->t_infomask & HEAP_MOVED_IN)
|
else if (tuple->t_infomask & HEAP_MOVED_IN)
|
||||||
@ -591,10 +652,14 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
|
|||||||
if (TransactionIdIsInProgress(xvac))
|
if (TransactionIdIsInProgress(xvac))
|
||||||
return false;
|
return false;
|
||||||
if (TransactionIdDidCommit(xvac))
|
if (TransactionIdDidCommit(xvac))
|
||||||
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -608,6 +673,7 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
|
|||||||
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,6 +689,7 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
|
|||||||
if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
|
if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SnapshotDirty->xmin = HeapTupleHeaderGetXmin(tuple);
|
SnapshotDirty->xmin = HeapTupleHeaderGetXmin(tuple);
|
||||||
@ -630,7 +697,10 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
|
|||||||
return true; /* in insertion by other */
|
return true; /* in insertion by other */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* by here, the inserting transaction has committed */
|
/* by here, the inserting transaction has committed */
|
||||||
@ -657,7 +727,8 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
|
|||||||
{
|
{
|
||||||
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMAX_INVALID; /* aborted */
|
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/* running xact */
|
/* running xact */
|
||||||
@ -670,10 +741,12 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
|
|||||||
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
|
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
|
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
SnapshotDirty->tid = tuple->t_ctid;
|
SnapshotDirty->tid = tuple->t_ctid;
|
||||||
return false; /* updated by other */
|
return false; /* updated by other */
|
||||||
}
|
}
|
||||||
@ -700,7 +773,8 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
|
|||||||
* can't see it.)
|
* can't see it.)
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
|
HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot,
|
||||||
|
Buffer buffer)
|
||||||
{
|
{
|
||||||
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
|
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
|
||||||
{
|
{
|
||||||
@ -718,9 +792,11 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
|
|||||||
if (TransactionIdDidCommit(xvac))
|
if (TransactionIdDidCommit(xvac))
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tuple->t_infomask & HEAP_MOVED_IN)
|
else if (tuple->t_infomask & HEAP_MOVED_IN)
|
||||||
@ -732,10 +808,14 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
|
|||||||
if (TransactionIdIsInProgress(xvac))
|
if (TransactionIdIsInProgress(xvac))
|
||||||
return false;
|
return false;
|
||||||
if (TransactionIdDidCommit(xvac))
|
if (TransactionIdDidCommit(xvac))
|
||||||
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -753,6 +833,7 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
|
|||||||
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -769,11 +850,17 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
|
|||||||
else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
|
else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
|
||||||
{
|
{
|
||||||
if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
|
if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
|
||||||
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -831,12 +918,16 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
|
|||||||
if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
|
if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
|
||||||
{
|
{
|
||||||
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
|
||||||
tuple->t_infomask |= HEAP_XMAX_INVALID; /* aborted */
|
{
|
||||||
|
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* xmax transaction committed */
|
/* xmax transaction committed */
|
||||||
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
|
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -886,7 +977,8 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
|
|||||||
* even if we see that the deleting transaction has committed.
|
* even if we see that the deleting transaction has committed.
|
||||||
*/
|
*/
|
||||||
HTSV_Result
|
HTSV_Result
|
||||||
HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
|
HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin,
|
||||||
|
Buffer buffer)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Has inserting transaction committed?
|
* Has inserting transaction committed?
|
||||||
@ -916,9 +1008,11 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
|
|||||||
if (TransactionIdDidCommit(xvac))
|
if (TransactionIdDidCommit(xvac))
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return HEAPTUPLE_DEAD;
|
return HEAPTUPLE_DEAD;
|
||||||
}
|
}
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
}
|
}
|
||||||
else if (tuple->t_infomask & HEAP_MOVED_IN)
|
else if (tuple->t_infomask & HEAP_MOVED_IN)
|
||||||
{
|
{
|
||||||
@ -929,10 +1023,14 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
|
|||||||
if (TransactionIdIsInProgress(xvac))
|
if (TransactionIdIsInProgress(xvac))
|
||||||
return HEAPTUPLE_INSERT_IN_PROGRESS;
|
return HEAPTUPLE_INSERT_IN_PROGRESS;
|
||||||
if (TransactionIdDidCommit(xvac))
|
if (TransactionIdDidCommit(xvac))
|
||||||
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return HEAPTUPLE_DEAD;
|
return HEAPTUPLE_DEAD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -946,7 +1044,10 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
|
|||||||
return HEAPTUPLE_DELETE_IN_PROGRESS;
|
return HEAPTUPLE_DELETE_IN_PROGRESS;
|
||||||
}
|
}
|
||||||
else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
|
else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
|
||||||
|
{
|
||||||
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -954,6 +1055,7 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
|
|||||||
* crashed
|
* crashed
|
||||||
*/
|
*/
|
||||||
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
tuple->t_infomask |= HEAP_XMIN_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return HEAPTUPLE_DEAD;
|
return HEAPTUPLE_DEAD;
|
||||||
}
|
}
|
||||||
/* Should only get here if we set XMIN_COMMITTED */
|
/* Should only get here if we set XMIN_COMMITTED */
|
||||||
@ -986,6 +1088,7 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
|
|||||||
* it did not and will never actually update it.
|
* it did not and will never actually update it.
|
||||||
*/
|
*/
|
||||||
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
}
|
}
|
||||||
return HEAPTUPLE_LIVE;
|
return HEAPTUPLE_LIVE;
|
||||||
}
|
}
|
||||||
@ -995,7 +1098,10 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
|
|||||||
if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
|
if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
|
||||||
return HEAPTUPLE_DELETE_IN_PROGRESS;
|
return HEAPTUPLE_DELETE_IN_PROGRESS;
|
||||||
else if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
|
else if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
|
||||||
|
{
|
||||||
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
|
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -1003,6 +1109,7 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
|
|||||||
* crashed
|
* crashed
|
||||||
*/
|
*/
|
||||||
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
tuple->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
SetBufferCommitInfoNeedsSave(buffer);
|
||||||
return HEAPTUPLE_LIVE;
|
return HEAPTUPLE_LIVE;
|
||||||
}
|
}
|
||||||
/* Should only get here if we set XMAX_COMMITTED */
|
/* Should only get here if we set XMAX_COMMITTED */
|
||||||
|
@ -7,20 +7,18 @@
|
|||||||
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/access/valid.h,v 1.34 2004/08/29 04:13:04 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/access/valid.h,v 1.35 2004/10/15 22:40:21 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
#ifndef VALID_H
|
#ifndef VALID_H
|
||||||
#define VALID_H
|
#define VALID_H
|
||||||
|
|
||||||
/* ----------------
|
/*
|
||||||
* HeapKeyTest
|
* HeapKeyTest
|
||||||
*
|
*
|
||||||
* Test a heap tuple with respect to a scan key.
|
* Test a heap tuple to see if it satisfies a scan key.
|
||||||
* ----------------
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define HeapKeyTest(tuple, \
|
#define HeapKeyTest(tuple, \
|
||||||
tupdesc, \
|
tupdesc, \
|
||||||
nkeys, \
|
nkeys, \
|
||||||
@ -28,9 +26,7 @@
|
|||||||
result) \
|
result) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
/* We use underscores to protect the variable passed in as parameters */ \
|
/* Use underscores to protect the variables passed in as parameters */ \
|
||||||
/* We use two underscore here because this macro is included in the \
|
|
||||||
macro below */ \
|
|
||||||
int __cur_nkeys = (nkeys); \
|
int __cur_nkeys = (nkeys); \
|
||||||
ScanKey __cur_keys = (keys); \
|
ScanKey __cur_keys = (keys); \
|
||||||
\
|
\
|
||||||
@ -40,6 +36,12 @@ do \
|
|||||||
Datum __atp; \
|
Datum __atp; \
|
||||||
bool __isnull; \
|
bool __isnull; \
|
||||||
Datum __test; \
|
Datum __test; \
|
||||||
|
\
|
||||||
|
if (__cur_keys->sk_flags & SK_ISNULL) \
|
||||||
|
{ \
|
||||||
|
(result) = false; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
\
|
\
|
||||||
__atp = heap_getattr((tuple), \
|
__atp = heap_getattr((tuple), \
|
||||||
__cur_keys->sk_attno, \
|
__cur_keys->sk_attno, \
|
||||||
@ -47,13 +49,6 @@ do \
|
|||||||
&__isnull); \
|
&__isnull); \
|
||||||
\
|
\
|
||||||
if (__isnull) \
|
if (__isnull) \
|
||||||
{ \
|
|
||||||
/* XXX eventually should check if SK_ISNULL */ \
|
|
||||||
(result) = false; \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
if (__cur_keys->sk_flags & SK_ISNULL) \
|
|
||||||
{ \
|
{ \
|
||||||
(result) = false; \
|
(result) = false; \
|
||||||
break; \
|
break; \
|
||||||
@ -70,7 +65,7 @@ do \
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/* ----------------
|
/*
|
||||||
* HeapTupleSatisfies
|
* HeapTupleSatisfies
|
||||||
*
|
*
|
||||||
* res is set TRUE if the HeapTuple satisfies the timequal and keytest,
|
* res is set TRUE if the HeapTuple satisfies the timequal and keytest,
|
||||||
@ -83,7 +78,6 @@ do \
|
|||||||
* least likely to fail, too. we should really add the time qual test to
|
* least likely to fail, too. we should really add the time qual test to
|
||||||
* the restriction and optimize it in the normal way. this has interactions
|
* the restriction and optimize it in the normal way. this has interactions
|
||||||
* with joey's expensive function work.
|
* with joey's expensive function work.
|
||||||
* ----------------
|
|
||||||
*/
|
*/
|
||||||
#define HeapTupleSatisfies(tuple, \
|
#define HeapTupleSatisfies(tuple, \
|
||||||
relation, \
|
relation, \
|
||||||
@ -95,24 +89,13 @@ do \
|
|||||||
res) \
|
res) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
/* We use underscores to protect the variable passed in as parameters */ \
|
|
||||||
if ((key) != NULL) \
|
if ((key) != NULL) \
|
||||||
HeapKeyTest(tuple, RelationGetDescr(relation), \
|
HeapKeyTest(tuple, RelationGetDescr(relation), nKeys, key, res); \
|
||||||
(nKeys), (key), (res)); \
|
|
||||||
else \
|
else \
|
||||||
(res) = true; \
|
(res) = true; \
|
||||||
\
|
\
|
||||||
if (res) \
|
if ((res) && (relation)->rd_rel->relkind != RELKIND_UNCATALOGED) \
|
||||||
{ \
|
(res) = HeapTupleSatisfiesVisibility(tuple, snapshot, buffer); \
|
||||||
if ((relation)->rd_rel->relkind != RELKIND_UNCATALOGED) \
|
|
||||||
{ \
|
|
||||||
uint16 _infomask = (tuple)->t_data->t_infomask; \
|
|
||||||
\
|
|
||||||
(res) = HeapTupleSatisfiesVisibility((tuple), (snapshot)); \
|
|
||||||
if ((tuple)->t_data->t_infomask != _infomask) \
|
|
||||||
SetBufferCommitInfoNeedsSave(buffer); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#endif /* VALID_H */
|
#endif /* VALID_H */
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/storage/bufmgr.h,v 1.86 2004/08/29 05:06:58 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/storage/bufmgr.h,v 1.87 2004/10/15 22:40:25 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -51,13 +51,14 @@ extern int32 *LocalRefCount;
|
|||||||
* These routines are beaten on quite heavily, hence the macroization.
|
* These routines are beaten on quite heavily, hence the macroization.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define BAD_BUFFER_ID(bid) ((bid) < 1 || (bid) > NBuffers)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* BufferIsValid
|
* BufferIsValid
|
||||||
* True iff the given buffer number is valid (either as a shared
|
* True iff the given buffer number is valid (either as a shared
|
||||||
* or local buffer).
|
* or local buffer).
|
||||||
*
|
*
|
||||||
|
* This is not quite the inverse of the BufferIsInvalid() macro, since this
|
||||||
|
* adds sanity rangechecks on the buffer number.
|
||||||
|
*
|
||||||
* Note: For a long time this was defined the same as BufferIsPinned,
|
* Note: For a long time this was defined the same as BufferIsPinned,
|
||||||
* that is it would say False if you didn't hold a pin on the buffer.
|
* that is it would say False if you didn't hold a pin on the buffer.
|
||||||
* I believe this was bogus and served only to mask logic errors.
|
* I believe this was bogus and served only to mask logic errors.
|
||||||
@ -66,10 +67,9 @@ extern int32 *LocalRefCount;
|
|||||||
*/
|
*/
|
||||||
#define BufferIsValid(bufnum) \
|
#define BufferIsValid(bufnum) \
|
||||||
( \
|
( \
|
||||||
BufferIsLocal(bufnum) ? \
|
(bufnum) != InvalidBuffer && \
|
||||||
((bufnum) >= -NLocBuffer) \
|
(bufnum) >= -NLocBuffer && \
|
||||||
: \
|
(bufnum) <= NBuffers \
|
||||||
(! BAD_BUFFER_ID(bufnum)) \
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -81,15 +81,13 @@ extern int32 *LocalRefCount;
|
|||||||
*/
|
*/
|
||||||
#define BufferIsPinned(bufnum) \
|
#define BufferIsPinned(bufnum) \
|
||||||
( \
|
( \
|
||||||
BufferIsLocal(bufnum) ? \
|
!BufferIsValid(bufnum) ? \
|
||||||
((bufnum) >= -NLocBuffer && LocalRefCount[-(bufnum) - 1] > 0) \
|
|
||||||
: \
|
|
||||||
( \
|
|
||||||
BAD_BUFFER_ID(bufnum) ? \
|
|
||||||
false \
|
false \
|
||||||
|
: \
|
||||||
|
BufferIsLocal(bufnum) ? \
|
||||||
|
(LocalRefCount[-(bufnum) - 1] > 0) \
|
||||||
: \
|
: \
|
||||||
(PrivateRefCount[(bufnum) - 1] > 0) \
|
(PrivateRefCount[(bufnum) - 1] > 0) \
|
||||||
) \
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* tqual.h
|
* tqual.h
|
||||||
* POSTGRES "time" qualification definitions, ie, tuple visibility rules.
|
* POSTGRES "time qualification" definitions, ie, tuple visibility rules.
|
||||||
*
|
*
|
||||||
* Should be moved/renamed... - vadim 07/28/98
|
* Should be moved/renamed... - vadim 07/28/98
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/utils/tqual.h,v 1.53 2004/09/16 18:35:23 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/utils/tqual.h,v 1.54 2004/10/15 22:40:29 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "access/htup.h"
|
#include "access/htup.h"
|
||||||
#include "access/xact.h"
|
#include "access/xact.h"
|
||||||
|
#include "storage/buf.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -72,23 +73,23 @@ extern TransactionId RecentGlobalXmin;
|
|||||||
* Assumes heap tuple is valid.
|
* Assumes heap tuple is valid.
|
||||||
* Beware of multiple evaluations of snapshot argument.
|
* Beware of multiple evaluations of snapshot argument.
|
||||||
*/
|
*/
|
||||||
#define HeapTupleSatisfiesVisibility(tuple, snapshot) \
|
#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer) \
|
||||||
((snapshot) == SnapshotNow ? \
|
((snapshot) == SnapshotNow ? \
|
||||||
HeapTupleSatisfiesNow((tuple)->t_data) \
|
HeapTupleSatisfiesNow((tuple)->t_data, buffer) \
|
||||||
: \
|
: \
|
||||||
((snapshot) == SnapshotSelf ? \
|
((snapshot) == SnapshotSelf ? \
|
||||||
HeapTupleSatisfiesItself((tuple)->t_data) \
|
HeapTupleSatisfiesItself((tuple)->t_data, buffer) \
|
||||||
: \
|
: \
|
||||||
((snapshot) == SnapshotAny ? \
|
((snapshot) == SnapshotAny ? \
|
||||||
true \
|
true \
|
||||||
: \
|
: \
|
||||||
((snapshot) == SnapshotToast ? \
|
((snapshot) == SnapshotToast ? \
|
||||||
HeapTupleSatisfiesToast((tuple)->t_data) \
|
HeapTupleSatisfiesToast((tuple)->t_data, buffer) \
|
||||||
: \
|
: \
|
||||||
((snapshot) == SnapshotDirty ? \
|
((snapshot) == SnapshotDirty ? \
|
||||||
HeapTupleSatisfiesDirty((tuple)->t_data) \
|
HeapTupleSatisfiesDirty((tuple)->t_data, buffer) \
|
||||||
: \
|
: \
|
||||||
HeapTupleSatisfiesSnapshot((tuple)->t_data, snapshot) \
|
HeapTupleSatisfiesSnapshot((tuple)->t_data, snapshot, buffer) \
|
||||||
) \
|
) \
|
||||||
) \
|
) \
|
||||||
) \
|
) \
|
||||||
@ -108,21 +109,20 @@ typedef enum
|
|||||||
HEAPTUPLE_DEAD, /* tuple is dead and deletable */
|
HEAPTUPLE_DEAD, /* tuple is dead and deletable */
|
||||||
HEAPTUPLE_LIVE, /* tuple is live (committed, no deleter) */
|
HEAPTUPLE_LIVE, /* tuple is live (committed, no deleter) */
|
||||||
HEAPTUPLE_RECENTLY_DEAD, /* tuple is dead, but not deletable yet */
|
HEAPTUPLE_RECENTLY_DEAD, /* tuple is dead, but not deletable yet */
|
||||||
HEAPTUPLE_INSERT_IN_PROGRESS, /* inserting xact is still in
|
HEAPTUPLE_INSERT_IN_PROGRESS, /* inserting xact is still in progress */
|
||||||
* progress */
|
|
||||||
HEAPTUPLE_DELETE_IN_PROGRESS /* deleting xact is still in progress */
|
HEAPTUPLE_DELETE_IN_PROGRESS /* deleting xact is still in progress */
|
||||||
} HTSV_Result;
|
} HTSV_Result;
|
||||||
|
|
||||||
extern bool HeapTupleSatisfiesItself(HeapTupleHeader tuple);
|
extern bool HeapTupleSatisfiesItself(HeapTupleHeader tuple, Buffer buffer);
|
||||||
extern bool HeapTupleSatisfiesNow(HeapTupleHeader tuple);
|
extern bool HeapTupleSatisfiesNow(HeapTupleHeader tuple, Buffer buffer);
|
||||||
extern bool HeapTupleSatisfiesDirty(HeapTupleHeader tuple);
|
extern bool HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Buffer buffer);
|
||||||
extern bool HeapTupleSatisfiesToast(HeapTupleHeader tuple);
|
extern bool HeapTupleSatisfiesToast(HeapTupleHeader tuple, Buffer buffer);
|
||||||
extern bool HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple,
|
extern bool HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple,
|
||||||
Snapshot snapshot);
|
Snapshot snapshot, Buffer buffer);
|
||||||
extern int HeapTupleSatisfiesUpdate(HeapTupleHeader tuple,
|
extern int HeapTupleSatisfiesUpdate(HeapTupleHeader tuple,
|
||||||
CommandId curcid);
|
CommandId curcid, Buffer buffer);
|
||||||
extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTupleHeader tuple,
|
extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTupleHeader tuple,
|
||||||
TransactionId OldestXmin);
|
TransactionId OldestXmin, Buffer buffer);
|
||||||
|
|
||||||
extern Snapshot GetTransactionSnapshot(void);
|
extern Snapshot GetTransactionSnapshot(void);
|
||||||
extern Snapshot GetLatestSnapshot(void);
|
extern Snapshot GetLatestSnapshot(void);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user