@ -30,10 +30,8 @@
*
* HeapTupleSatisfiesMVCC ( )
* visible to supplied snapshot , excludes current command
* HeapTupleSatisfiesNow ( )
* visible to instant snapshot , excludes current command
* HeapTupleSatisfiesUpdate ( )
* like HeapTupleSatisfiesNow ( ) , but with user - supplied command
* visible to instant snapshot , with user - supplied command
* counter and more complex result
* HeapTupleSatisfiesSelf ( )
* visible to instant snapshot and current command
@ -68,7 +66,6 @@
/* Static variables representing various special snapshot semantics */
SnapshotData SnapshotNowData = { HeapTupleSatisfiesNow } ;
SnapshotData SnapshotSelfData = { HeapTupleSatisfiesSelf } ;
SnapshotData SnapshotAnyData = { HeapTupleSatisfiesAny } ;
SnapshotData SnapshotToastData = { HeapTupleSatisfiesToast } ;
@ -323,212 +320,6 @@ HeapTupleSatisfiesSelf(HeapTuple htup, Snapshot snapshot, Buffer buffer)
return false ;
}
/*
* HeapTupleSatisfiesNow
* True iff heap tuple is valid " now " .
*
* Here , we consider the effects of :
* all committed transactions ( as of the current instant )
* previous commands of this transaction
*
* Note we do _not_ include changes made by the current command . This
* solves the " Halloween problem " wherein an UPDATE might try to re - update
* its own output tuples , http : //en.wikipedia.org/wiki/Halloween_Problem.
*
* Note :
* Assumes heap tuple is valid .
*
* The satisfaction of " now " requires the following :
*
* ( ( Xmin = = my - transaction & & inserted by the current transaction
* Cmin < my - command & & before this command , and
* ( Xmax is null | | the row has not been deleted , or
* ( Xmax = = my - transaction & & it was deleted by the current transaction
* Cmax > = my - command ) ) ) but not before this command ,
* | | or
* ( Xmin is committed & & the row was inserted by a committed transaction , and
* ( Xmax is null | | the row has not been deleted , or
* ( Xmax = = my - transaction & & the row is being deleted by this transaction
* Cmax > = my - command ) | | but it ' s not deleted " yet " , or
* ( Xmax ! = my - transaction & & the row was deleted by another transaction
* Xmax is not committed ) ) ) ) that has not been committed
*
*/
bool
HeapTupleSatisfiesNow ( HeapTuple htup , Snapshot snapshot , Buffer buffer )
{
HeapTupleHeader tuple = htup - > t_data ;
Assert ( ItemPointerIsValid ( & htup - > t_self ) ) ;
Assert ( htup - > t_tableOid ! = InvalidOid ) ;
if ( ! ( tuple - > t_infomask & HEAP_XMIN_COMMITTED ) )
{
if ( tuple - > t_infomask & HEAP_XMIN_INVALID )
return false ;
/* Used by pre-9.0 binary upgrades */
if ( tuple - > t_infomask & HEAP_MOVED_OFF )
{
TransactionId xvac = HeapTupleHeaderGetXvac ( tuple ) ;
if ( TransactionIdIsCurrentTransactionId ( xvac ) )
return false ;
if ( ! TransactionIdIsInProgress ( xvac ) )
{
if ( TransactionIdDidCommit ( xvac ) )
{
SetHintBits ( tuple , buffer , HEAP_XMIN_INVALID ,
InvalidTransactionId ) ;
return false ;
}
SetHintBits ( tuple , buffer , HEAP_XMIN_COMMITTED ,
InvalidTransactionId ) ;
}
}
/* Used by pre-9.0 binary upgrades */
else if ( tuple - > t_infomask & HEAP_MOVED_IN )
{
TransactionId xvac = HeapTupleHeaderGetXvac ( tuple ) ;
if ( ! TransactionIdIsCurrentTransactionId ( xvac ) )
{
if ( TransactionIdIsInProgress ( xvac ) )
return false ;
if ( TransactionIdDidCommit ( xvac ) )
SetHintBits ( tuple , buffer , HEAP_XMIN_COMMITTED ,
InvalidTransactionId ) ;
else
{
SetHintBits ( tuple , buffer , HEAP_XMIN_INVALID ,
InvalidTransactionId ) ;
return false ;
}
}
}
else if ( TransactionIdIsCurrentTransactionId ( HeapTupleHeaderGetXmin ( tuple ) ) )
{
if ( HeapTupleHeaderGetCmin ( tuple ) > = GetCurrentCommandId ( false ) )
return false ; /* inserted after scan started */
if ( tuple - > t_infomask & HEAP_XMAX_INVALID ) /* xid invalid */
return true ;
if ( HEAP_XMAX_IS_LOCKED_ONLY ( tuple - > t_infomask ) ) /* not deleter */
return true ;
if ( tuple - > t_infomask & HEAP_XMAX_IS_MULTI )
{
TransactionId xmax ;
xmax = HeapTupleGetUpdateXid ( tuple ) ;
if ( ! TransactionIdIsValid ( xmax ) )
return true ;
/* updating subtransaction must have aborted */
if ( ! TransactionIdIsCurrentTransactionId ( xmax ) )
return true ;
else
return false ;
}
if ( ! TransactionIdIsCurrentTransactionId ( HeapTupleHeaderGetRawXmax ( tuple ) ) )
{
/* deleting subtransaction must have aborted */
SetHintBits ( tuple , buffer , HEAP_XMAX_INVALID ,
InvalidTransactionId ) ;
return true ;
}
if ( HeapTupleHeaderGetCmax ( tuple ) > = GetCurrentCommandId ( false ) )
return true ; /* deleted after scan started */
else
return false ; /* deleted before scan started */
}
else if ( TransactionIdIsInProgress ( HeapTupleHeaderGetXmin ( tuple ) ) )
return false ;
else if ( TransactionIdDidCommit ( HeapTupleHeaderGetXmin ( tuple ) ) )
SetHintBits ( tuple , buffer , HEAP_XMIN_COMMITTED ,
HeapTupleHeaderGetXmin ( tuple ) ) ;
else
{
/* it must have aborted or crashed */
SetHintBits ( tuple , buffer , HEAP_XMIN_INVALID ,
InvalidTransactionId ) ;
return false ;
}
}
/* by here, the inserting transaction has committed */
if ( tuple - > t_infomask & HEAP_XMAX_INVALID ) /* xid invalid or aborted */
return true ;
if ( tuple - > t_infomask & HEAP_XMAX_COMMITTED )
{
if ( HEAP_XMAX_IS_LOCKED_ONLY ( tuple - > t_infomask ) )
return true ;
return false ;
}
if ( tuple - > t_infomask & HEAP_XMAX_IS_MULTI )
{
TransactionId xmax ;
if ( HEAP_XMAX_IS_LOCKED_ONLY ( tuple - > t_infomask ) )
return true ;
xmax = HeapTupleGetUpdateXid ( tuple ) ;
if ( ! TransactionIdIsValid ( xmax ) )
return true ;
if ( TransactionIdIsCurrentTransactionId ( xmax ) )
{
if ( HeapTupleHeaderGetCmax ( tuple ) > = GetCurrentCommandId ( false ) )
return true ; /* deleted after scan started */
else
return false ; /* deleted before scan started */
}
if ( TransactionIdIsInProgress ( xmax ) )
return true ;
if ( TransactionIdDidCommit ( xmax ) )
return false ;
return true ;
}
if ( TransactionIdIsCurrentTransactionId ( HeapTupleHeaderGetRawXmax ( tuple ) ) )
{
if ( HEAP_XMAX_IS_LOCKED_ONLY ( tuple - > t_infomask ) )
return true ;
if ( HeapTupleHeaderGetCmax ( tuple ) > = GetCurrentCommandId ( false ) )
return true ; /* deleted after scan started */
else
return false ; /* deleted before scan started */
}
if ( TransactionIdIsInProgress ( HeapTupleHeaderGetRawXmax ( tuple ) ) )
return true ;
if ( ! TransactionIdDidCommit ( HeapTupleHeaderGetRawXmax ( tuple ) ) )
{
/* it must have aborted or crashed */
SetHintBits ( tuple , buffer , HEAP_XMAX_INVALID ,
InvalidTransactionId ) ;
return true ;
}
/* xmax transaction committed */
if ( HEAP_XMAX_IS_LOCKED_ONLY ( tuple - > t_infomask ) )
{
SetHintBits ( tuple , buffer , HEAP_XMAX_INVALID ,
InvalidTransactionId ) ;
return true ;
}
SetHintBits ( tuple , buffer , HEAP_XMAX_COMMITTED ,
HeapTupleHeaderGetRawXmax ( tuple ) ) ;
return false ;
}
/*
* HeapTupleSatisfiesAny
* Dummy " satisfies " routine : any tuple satisfies SnapshotAny .
@ -614,10 +405,10 @@ HeapTupleSatisfiesToast(HeapTuple htup, Snapshot snapshot,
/*
* HeapTupleSatisfiesUpdate
*
* Same logic as HeapTupleSatisfiesNow , but returns a more detailed result
* cod e, since UPDATE needs to know more than " is it visible? " . Also ,
* tuples of my own xact are tested against the passed CommandId not
* CurrentCommandId .
* This function returns a more detailed result code than most of the
* functions in this fil e, since UPDATE needs to know more than " is it
* visible ? " . It also allows for user-supplied CommandId rather than
* relying on CurrentCommandId .
*
* The possible return codes are :
*
@ -1051,10 +842,6 @@ HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot,
* transactions started after the snapshot was taken
* changes made by the current command
*
* This is the same as HeapTupleSatisfiesNow , except that transactions that
* were in progress or as yet unstarted when the snapshot was taken will
* be treated as uncommitted , even if they have committed by now .
*
* ( Notice , however , that the tuple status hint bits will be updated on the
* basis of the true state of the transaction , even if we then pretend we
* can ' t see it . )