Commit 9ffc8ed5 authored by Tom Lane's avatar Tom Lane

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.
parent db9e2fd0
/* /*
* $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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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, ...@@ -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: ...@@ -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: ...@@ -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, ...@@ -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: ...@@ -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: ...@@ -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, ...@@ -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: ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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, ...@@ -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 @@ ...@@ -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, ...@@ -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, ...@@ -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 @@ ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 @@ ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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) ...@@ -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 @@ ...@@ -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; ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 \ ...@@ -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 \ ...@@ -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 \ ...@@ -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 \ ...@@ -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 \ ...@@ -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 @@ ...@@ -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; ...@@ -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; ...@@ -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; ...@@ -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) \
) \
) )
/* /*
......
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* 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 @@ ...@@ -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; ...@@ -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 ...@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment