Header And Logo

PostgreSQL
| The world's most advanced open source database.

Functions | Variables

tqual.c File Reference

#include "postgres.h"
#include "access/htup_details.h"
#include "access/multixact.h"
#include "access/subtrans.h"
#include "access/transam.h"
#include "access/xact.h"
#include "storage/bufmgr.h"
#include "storage/procarray.h"
#include "utils/tqual.h"
Include dependency graph for tqual.c:

Go to the source code of this file.

Functions

static bool XidInMVCCSnapshot (TransactionId xid, Snapshot snapshot)
static void SetHintBits (HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
void HeapTupleSetHintBits (HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
bool HeapTupleSatisfiesSelf (HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
bool HeapTupleSatisfiesNow (HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
bool HeapTupleSatisfiesAny (HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
bool HeapTupleSatisfiesToast (HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
HTSU_Result HeapTupleSatisfiesUpdate (HeapTupleHeader tuple, CommandId curcid, Buffer buffer)
bool HeapTupleSatisfiesDirty (HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
bool HeapTupleSatisfiesMVCC (HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer)
HTSV_Result HeapTupleSatisfiesVacuum (HeapTupleHeader tuple, TransactionId OldestXmin, Buffer buffer)
bool HeapTupleIsSurelyDead (HeapTupleHeader tuple, TransactionId OldestXmin)
bool HeapTupleHeaderIsOnlyLocked (HeapTupleHeader tuple)

Variables

SnapshotData SnapshotNowData = {HeapTupleSatisfiesNow}
SnapshotData SnapshotSelfData = {HeapTupleSatisfiesSelf}
SnapshotData SnapshotAnyData = {HeapTupleSatisfiesAny}
SnapshotData SnapshotToastData = {HeapTupleSatisfiesToast}

Function Documentation

bool HeapTupleHeaderIsOnlyLocked ( HeapTupleHeader  tuple  ) 

Definition at line 1630 of file tqual.c.

References HEAP_XMAX_INVALID, HEAP_XMAX_IS_MULTI, HEAP_XMAX_LOCK_ONLY, HeapTupleGetUpdateXid(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderData::t_infomask, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), and TransactionIdIsValid.

Referenced by heap_delete(), heap_get_latest_tid(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), and rewrite_heap_tuple().

{
    TransactionId   xmax;

    /* if there's no valid Xmax, then there's obviously no update either */
    if (tuple->t_infomask & HEAP_XMAX_INVALID)
        return true;

    if (tuple->t_infomask & HEAP_XMAX_LOCK_ONLY)
        return true;

    /* invalid xmax means no update */
    if (!TransactionIdIsValid(HeapTupleHeaderGetRawXmax(tuple)))
        return true;

    /*
     * if HEAP_XMAX_LOCK_ONLY is not set and not a multi, then this
     * must necessarily have been updated
     */
    if (!(tuple->t_infomask & HEAP_XMAX_IS_MULTI))
        return false;

    /* ... but if it's a multi, then perhaps the updating Xid aborted. */
    xmax = HeapTupleGetUpdateXid(tuple);
    if (!TransactionIdIsValid(xmax))    /* shouldn't happen .. */
        return true;

    if (TransactionIdIsCurrentTransactionId(xmax))
        return false;
    if (TransactionIdIsInProgress(xmax))
        return false;
    if (TransactionIdDidCommit(xmax))
        return false;

    /*
     * not current, not in progress, not committed -- must have aborted or
     * crashed
     */
    return true;
}

bool HeapTupleIsSurelyDead ( HeapTupleHeader  tuple,
TransactionId  OldestXmin 
)

Definition at line 1466 of file tqual.c.

References HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleHeaderGetRawXmax, HeapTupleHeaderData::t_infomask, and TransactionIdPrecedes().

Referenced by heap_hot_search_buffer().

{
    /*
     * If the inserting transaction is marked invalid, then it aborted, and
     * the tuple is definitely dead.  If it's marked neither committed nor
     * invalid, then we assume it's still alive (since the presumption is that
     * all relevant hint bits were just set moments ago).
     */
    if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
        return (tuple->t_infomask & HEAP_XMIN_INVALID) != 0 ? true : false;

    /*
     * If the inserting transaction committed, but any deleting transaction
     * aborted, the tuple is still alive.
     */
    if (tuple->t_infomask & HEAP_XMAX_INVALID)
        return false;

    /*
     * If the XMAX is just a lock, the tuple is still alive.
     */
    if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
        return false;

    /*
     * If the Xmax is a MultiXact, it might be dead or alive, but we cannot
     * know without checking pg_multixact.
     */
    if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
        return false;

    /* If deleter isn't known to have committed, assume it's still running. */
    if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
        return false;

    /* Deleter committed, so tuple is dead if the XID is old enough. */
    return TransactionIdPrecedes(HeapTupleHeaderGetRawXmax(tuple), OldestXmin);
}

bool HeapTupleSatisfiesAny ( HeapTupleHeader  tuple,
Snapshot  snapshot,
Buffer  buffer 
)

Definition at line 529 of file tqual.c.

{
    return true;
}

bool HeapTupleSatisfiesDirty ( HeapTupleHeader  tuple,
Snapshot  snapshot,
Buffer  buffer 
)

Definition at line 851 of file tqual.c.

References HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleGetUpdateXid(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetXmin, HeapTupleHeaderGetXvac, InvalidTransactionId, SetHintBits(), HeapTupleHeaderData::t_infomask, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), TransactionIdIsValid, SnapshotData::xmax, and SnapshotData::xmin.

{
    snapshot->xmin = snapshot->xmax = InvalidTransactionId;

    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 (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;
            }

            return false;
        }
        else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
        {
            snapshot->xmin = HeapTupleHeaderGetXmin(tuple);
            /* XXX shouldn't we fall through to look at xmax? */
            return true;        /* in insertion by other */
        }
        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;           /* updated by other */
    }

    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))
            return false;
        if (TransactionIdIsInProgress(xmax))
        {
            snapshot->xmax = 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;
        return false;
    }

    if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
    {
        snapshot->xmax = 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;               /* updated by other */
}

bool HeapTupleSatisfiesMVCC ( HeapTupleHeader  tuple,
Snapshot  snapshot,
Buffer  buffer 
)

Definition at line 1042 of file tqual.c.

References Assert, SnapshotData::curcid, HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleGetUpdateXid(), HeapTupleHeaderGetCmax(), HeapTupleHeaderGetCmin(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetXmin, HeapTupleHeaderGetXvac, InvalidTransactionId, SetHintBits(), HeapTupleHeaderData::t_infomask, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), TransactionIdIsValid, and XidInMVCCSnapshot().

{
    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) >= snapshot->curcid)
                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 if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
                    return true;    /* updated after scan started */
                else
                    return false;   /* updated before scan started */
            }

            if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
            {
                /* deleting subtransaction must have aborted */
                SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                            InvalidTransactionId);
                return true;
            }

            if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
                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 - have to check
     * when...
     */
    if (XidInMVCCSnapshot(HeapTupleHeaderGetXmin(tuple), snapshot))
        return false;           /* treat as still in progress */

    if (tuple->t_infomask & HEAP_XMAX_INVALID)  /* xid invalid or aborted */
        return true;

    if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
        return true;

    if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
    {
        TransactionId   xmax;

        /* already checked above */
        Assert(!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask));

        xmax = HeapTupleGetUpdateXid(tuple);
        if (!TransactionIdIsValid(xmax))
            return true;
        if (TransactionIdIsCurrentTransactionId(xmax))
        {
            if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
                return true;    /* deleted after scan started */
            else
                return false;   /* deleted before scan started */
        }
        if (TransactionIdIsInProgress(xmax))
            return true;
        if (TransactionIdDidCommit(xmax))
        {
            /* updating transaction committed, but when? */
            if (XidInMVCCSnapshot(xmax, snapshot))
                return true;    /* treat as still in progress */
            return false;
        }
        return true;
    }

    if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
    {
        if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
        {
            if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
                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 */
        SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
                    HeapTupleHeaderGetRawXmax(tuple));
    }

    /*
     * OK, the deleting transaction committed too ... but when?
     */
    if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot))
        return true;            /* treat as still in progress */

    return false;
}

bool HeapTupleSatisfiesNow ( HeapTupleHeader  tuple,
Snapshot  snapshot,
Buffer  buffer 
)

Definition at line 354 of file tqual.c.

References GetCurrentCommandId(), HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleGetUpdateXid(), HeapTupleHeaderGetCmax(), HeapTupleHeaderGetCmin(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetXmin, HeapTupleHeaderGetXvac, InvalidTransactionId, SetHintBits(), HeapTupleHeaderData::t_infomask, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), and TransactionIdIsValid.

{
    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;
}

bool HeapTupleSatisfiesSelf ( HeapTupleHeader  tuple,
Snapshot  snapshot,
Buffer  buffer 
)

Definition at line 166 of file tqual.c.

References HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleGetUpdateXid(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetXmin, HeapTupleHeaderGetXvac, InvalidTransactionId, SetHintBits(), HeapTupleHeaderData::t_infomask, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), and TransactionIdIsValid.

{
    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 (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;
            }

            return false;
        }
        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;           /* updated by other */
    }

    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))
            return false;
        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;
        return false;
    }

    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;
}

bool HeapTupleSatisfiesToast ( HeapTupleHeader  tuple,
Snapshot  snapshot,
Buffer  buffer 
)

Definition at line 549 of file tqual.c.

References HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleHeaderGetXvac, InvalidTransactionId, SetHintBits(), HeapTupleHeaderData::t_infomask, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), and TransactionIdIsInProgress().

{
    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;
                }
            }
        }
    }

    /* otherwise assume the tuple is valid for TOAST. */
    return true;
}

HTSU_Result HeapTupleSatisfiesUpdate ( HeapTupleHeader  tuple,
CommandId  curcid,
Buffer  buffer 
)

Definition at line 630 of file tqual.c.

References HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMAX_COMMITTED, HEAP_XMAX_EXCL_LOCK, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMAX_KEYSHR_LOCK, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleGetUpdateXid(), HeapTupleHeaderGetCmax(), HeapTupleHeaderGetCmin(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetXmin, HeapTupleHeaderGetXvac, InvalidTransactionId, MultiXactIdIsRunning(), SetHintBits(), HeapTupleHeaderData::t_infomask, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), and TransactionIdIsValid.

Referenced by heap_delete(), heap_lock_tuple(), heap_update(), and pgrowlocks().

{
    if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
    {
        if (tuple->t_infomask & HEAP_XMIN_INVALID)
            return HeapTupleInvisible;

        /* Used by pre-9.0 binary upgrades */
        if (tuple->t_infomask & HEAP_MOVED_OFF)
        {
            TransactionId xvac = HeapTupleHeaderGetXvac(tuple);

            if (TransactionIdIsCurrentTransactionId(xvac))
                return HeapTupleInvisible;
            if (!TransactionIdIsInProgress(xvac))
            {
                if (TransactionIdDidCommit(xvac))
                {
                    SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                                InvalidTransactionId);
                    return HeapTupleInvisible;
                }
                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 HeapTupleInvisible;
                if (TransactionIdDidCommit(xvac))
                    SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
                                InvalidTransactionId);
                else
                {
                    SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                                InvalidTransactionId);
                    return HeapTupleInvisible;
                }
            }
        }
        else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
        {
            if (HeapTupleHeaderGetCmin(tuple) >= curcid)
                return HeapTupleInvisible;      /* inserted after scan started */

            if (tuple->t_infomask & HEAP_XMAX_INVALID)  /* xid invalid */
                return HeapTupleMayBeUpdated;

            if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))         /* not deleter */
                return HeapTupleMayBeUpdated;

            if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
            {
                TransactionId   xmax;

                xmax = HeapTupleGetUpdateXid(tuple);
                if (!TransactionIdIsValid(xmax))
                    return HeapTupleMayBeUpdated;

                /* updating subtransaction must have aborted */
                if (!TransactionIdIsCurrentTransactionId(xmax))
                    return HeapTupleMayBeUpdated;
                else
                {
                    if (HeapTupleHeaderGetCmax(tuple) >= curcid)
                        return HeapTupleSelfUpdated;    /* updated after scan started */
                    else
                        return HeapTupleInvisible;  /* updated before scan started */
                }
            }

            if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
            {
                /* deleting subtransaction must have aborted */
                SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                            InvalidTransactionId);
                return HeapTupleMayBeUpdated;
            }

            if (HeapTupleHeaderGetCmax(tuple) >= curcid)
                return HeapTupleSelfUpdated;    /* updated after scan started */
            else
                return HeapTupleInvisible;      /* updated before scan started */
        }
        else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
            return HeapTupleInvisible;
        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 HeapTupleInvisible;
        }
    }

    /* by here, the inserting transaction has committed */

    if (tuple->t_infomask & HEAP_XMAX_INVALID)  /* xid invalid or aborted */
        return HeapTupleMayBeUpdated;

    if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
    {
        if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
            return HeapTupleMayBeUpdated;
        return HeapTupleUpdated;    /* updated by other */
    }

    if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
    {
        TransactionId   xmax;

        if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
        {
            /*
             * If it's only locked but neither EXCL_LOCK nor KEYSHR_LOCK
             * is set, it cannot possibly be running.  Otherwise need to
             * check.
             */
            if ((tuple->t_infomask & (HEAP_XMAX_EXCL_LOCK |
                                      HEAP_XMAX_KEYSHR_LOCK)) &&
                MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple)))
                return HeapTupleBeingUpdated;

            SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
            return HeapTupleMayBeUpdated;
        }

        xmax = HeapTupleGetUpdateXid(tuple);
        if (!TransactionIdIsValid(xmax))
        {
            if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple)))
                return HeapTupleBeingUpdated;

            SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
            return HeapTupleMayBeUpdated;
        }

        if (TransactionIdIsCurrentTransactionId(xmax))
        {
            if (HeapTupleHeaderGetCmax(tuple) >= curcid)
                return HeapTupleSelfUpdated;        /* updated after scan started */
            else
                return HeapTupleInvisible;  /* updated before scan started */
        }

        if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple)))
            return HeapTupleBeingUpdated;

        if (TransactionIdDidCommit(xmax))
            return HeapTupleUpdated;
        /* it must have aborted or crashed */
        SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
        return HeapTupleMayBeUpdated;
    }

    if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
    {
        if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
            return HeapTupleMayBeUpdated;
        if (HeapTupleHeaderGetCmax(tuple) >= curcid)
            return HeapTupleSelfUpdated;        /* updated after scan started */
        else
            return HeapTupleInvisible;  /* updated before scan started */
    }

    if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
        return HeapTupleBeingUpdated;

    if (!TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
    {
        /* it must have aborted or crashed */
        SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                    InvalidTransactionId);
        return HeapTupleMayBeUpdated;
    }

    /* xmax transaction committed */

    if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
    {
        SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                    InvalidTransactionId);
        return HeapTupleMayBeUpdated;
    }

    SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
                HeapTupleHeaderGetRawXmax(tuple));
    return HeapTupleUpdated;    /* updated by other */
}

HTSV_Result HeapTupleSatisfiesVacuum ( HeapTupleHeader  tuple,
TransactionId  OldestXmin,
Buffer  buffer 
)

Definition at line 1235 of file tqual.c.

References Assert, HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMAX_COMMITTED, HEAP_XMAX_EXCL_LOCK, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMAX_KEYSHR_LOCK, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleGetUpdateXid(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetXmin, HeapTupleHeaderGetXvac, InvalidTransactionId, MultiXactIdIsRunning(), SetHintBits(), HeapTupleHeaderData::t_infomask, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), TransactionIdIsValid, and TransactionIdPrecedes().

Referenced by acquire_sample_rows(), CheckForSerializableConflictOut(), copy_heap_data(), heap_page_is_all_visible(), heap_prune_chain(), IndexBuildHeapScan(), and lazy_scan_heap().

{
    /*
     * Has inserting transaction committed?
     *
     * If the inserting transaction aborted, then the tuple was never visible
     * to any other transaction, so we can delete it immediately.
     */
    if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
    {
        if (tuple->t_infomask & HEAP_XMIN_INVALID)
            return HEAPTUPLE_DEAD;
        /* Used by pre-9.0 binary upgrades */
        else if (tuple->t_infomask & HEAP_MOVED_OFF)
        {
            TransactionId xvac = HeapTupleHeaderGetXvac(tuple);

            if (TransactionIdIsCurrentTransactionId(xvac))
                return HEAPTUPLE_DELETE_IN_PROGRESS;
            if (TransactionIdIsInProgress(xvac))
                return HEAPTUPLE_DELETE_IN_PROGRESS;
            if (TransactionIdDidCommit(xvac))
            {
                SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                            InvalidTransactionId);
                return HEAPTUPLE_DEAD;
            }
            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))
                return HEAPTUPLE_INSERT_IN_PROGRESS;
            if (TransactionIdIsInProgress(xvac))
                return HEAPTUPLE_INSERT_IN_PROGRESS;
            if (TransactionIdDidCommit(xvac))
                SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
                            InvalidTransactionId);
            else
            {
                SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                            InvalidTransactionId);
                return HEAPTUPLE_DEAD;
            }
        }
        else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
        {
            if (tuple->t_infomask & HEAP_XMAX_INVALID)  /* xid invalid */
                return HEAPTUPLE_INSERT_IN_PROGRESS;
            if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
                return HEAPTUPLE_INSERT_IN_PROGRESS;
            /* inserted and then deleted by same xact */
            return HEAPTUPLE_DELETE_IN_PROGRESS;
        }
        else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
            SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
                        HeapTupleHeaderGetXmin(tuple));
        else
        {
            /*
             * Not in Progress, Not Committed, so either Aborted or crashed
             */
            SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                        InvalidTransactionId);
            return HEAPTUPLE_DEAD;
        }

        /*
         * At this point the xmin is known committed, but we might not have
         * been able to set the hint bit yet; so we can no longer Assert that
         * it's set.
         */
    }

    /*
     * Okay, the inserter committed, so it was good at some point.  Now what
     * about the deleting transaction?
     */
    if (tuple->t_infomask & HEAP_XMAX_INVALID)
        return HEAPTUPLE_LIVE;

    if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
    {
        /*
         * "Deleting" xact really only locked it, so the tuple is live in any
         * case.  However, we should make sure that either XMAX_COMMITTED or
         * XMAX_INVALID gets set once the xact is gone, to reduce the costs of
         * examining the tuple for future xacts.  Also, marking dead
         * MultiXacts as invalid here provides defense against MultiXactId
         * wraparound (see also comments in heap_freeze_tuple()).
         */
        if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
        {
            if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
            {
                /*
                 * If it's only locked but neither EXCL_LOCK nor KEYSHR_LOCK
                 * are set, it cannot possibly be running; otherwise have to
                 * check.
                 */
                if ((tuple->t_infomask & (HEAP_XMAX_EXCL_LOCK |
                                          HEAP_XMAX_KEYSHR_LOCK)) &&
                    MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple)))
                    return HEAPTUPLE_LIVE;
                SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);

            }
            else
            {
                if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
                    return HEAPTUPLE_LIVE;
                SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                            InvalidTransactionId);
            }
        }

        /*
         * We don't really care whether xmax did commit, abort or crash.
         * We know that xmax did lock the tuple, but it did not and will
         * never actually update it.
         */

        return HEAPTUPLE_LIVE;
    }

    if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
    {
        TransactionId xmax;

        if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple)))
        {
            /* already checked above */
            Assert(!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask));

            xmax = HeapTupleGetUpdateXid(tuple);
            if (!TransactionIdIsValid(xmax))
                return HEAPTUPLE_LIVE;
            if (TransactionIdIsInProgress(xmax))
                return HEAPTUPLE_DELETE_IN_PROGRESS;
            else if (TransactionIdDidCommit(xmax))
                /* there are still lockers around -- can't return DEAD here */
                return HEAPTUPLE_RECENTLY_DEAD;
            /* updating transaction aborted */
            return HEAPTUPLE_LIVE;
        }

        Assert(!(tuple->t_infomask & HEAP_XMAX_COMMITTED));

        xmax = HeapTupleGetUpdateXid(tuple);
        if (!TransactionIdIsValid(xmax))
            return HEAPTUPLE_LIVE;
        /* multi is not running -- updating xact cannot be */
        Assert(!TransactionIdIsInProgress(xmax));
        if (TransactionIdDidCommit(xmax))
        {
            if (!TransactionIdPrecedes(xmax, OldestXmin))
                return HEAPTUPLE_RECENTLY_DEAD;
            else
                return HEAPTUPLE_DEAD;
        }
        else
        {
            /*
             * Not in Progress, Not Committed, so either Aborted or crashed.
             */
            SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
            return HEAPTUPLE_LIVE;
        }

        /*
         * Deleter committed, but perhaps it was recent enough that some open
         * transactions could still see the tuple.
         */

        /* Otherwise, it's dead and removable */
        return HEAPTUPLE_DEAD;
    }

    if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
    {
        if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
            return HEAPTUPLE_DELETE_IN_PROGRESS;
        else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
            SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
                        HeapTupleHeaderGetRawXmax(tuple));
        else
        {
            /*
             * Not in Progress, Not Committed, so either Aborted or crashed
             */
            SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                        InvalidTransactionId);
            return HEAPTUPLE_LIVE;
        }

        /*
         * At this point the xmax is known committed, but we might not have
         * been able to set the hint bit yet; so we can no longer Assert that
         * it's set.
         */
    }

    /*
     * Deleter committed, but perhaps it was recent enough that some open
     * transactions could still see the tuple.
     */
    if (!TransactionIdPrecedes(HeapTupleHeaderGetRawXmax(tuple), OldestXmin))
        return HEAPTUPLE_RECENTLY_DEAD;

    /* Otherwise, it's dead and removable */
    return HEAPTUPLE_DEAD;
}

void HeapTupleSetHintBits ( HeapTupleHeader  tuple,
Buffer  buffer,
uint16  infomask,
TransactionId  xid 
)

Definition at line 134 of file tqual.c.

References SetHintBits().

Referenced by UpdateXmaxHintBits().

{
    SetHintBits(tuple, buffer, infomask, xid);
}

static void SetHintBits ( HeapTupleHeader  tuple,
Buffer  buffer,
uint16  infomask,
TransactionId  xid 
) [inline, static]
static bool XidInMVCCSnapshot ( TransactionId  xid,
Snapshot  snapshot 
) [static]

Definition at line 1515 of file tqual.c.

References i, SnapshotData::suboverflowed, SubTransGetTopmostTransaction(), SnapshotData::subxcnt, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TransactionIdEquals, TransactionIdFollowsOrEquals(), TransactionIdPrecedes(), SnapshotData::xcnt, SnapshotData::xip, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by HeapTupleSatisfiesMVCC().

{
    uint32      i;

    /*
     * Make a quick range check to eliminate most XIDs without looking at the
     * xip arrays.  Note that this is OK even if we convert a subxact XID to
     * its parent below, because a subxact with XID < xmin has surely also got
     * a parent with XID < xmin, while one with XID >= xmax must belong to a
     * parent that was not yet committed at the time of this snapshot.
     */

    /* Any xid < xmin is not in-progress */
    if (TransactionIdPrecedes(xid, snapshot->xmin))
        return false;
    /* Any xid >= xmax is in-progress */
    if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
        return true;

    /*
     * Snapshot information is stored slightly differently in snapshots taken
     * during recovery.
     */
    if (!snapshot->takenDuringRecovery)
    {
        /*
         * If the snapshot contains full subxact data, the fastest way to
         * check things is just to compare the given XID against both subxact
         * XIDs and top-level XIDs.  If the snapshot overflowed, we have to
         * use pg_subtrans to convert a subxact XID to its parent XID, but
         * then we need only look at top-level XIDs not subxacts.
         */
        if (!snapshot->suboverflowed)
        {
            /* full data, so search subxip */
            int32       j;

            for (j = 0; j < snapshot->subxcnt; j++)
            {
                if (TransactionIdEquals(xid, snapshot->subxip[j]))
                    return true;
            }

            /* not there, fall through to search xip[] */
        }
        else
        {
            /* overflowed, so convert xid to top-level */
            xid = SubTransGetTopmostTransaction(xid);

            /*
             * If xid was indeed a subxact, we might now have an xid < xmin,
             * so recheck to avoid an array scan.  No point in rechecking
             * xmax.
             */
            if (TransactionIdPrecedes(xid, snapshot->xmin))
                return false;
        }

        for (i = 0; i < snapshot->xcnt; i++)
        {
            if (TransactionIdEquals(xid, snapshot->xip[i]))
                return true;
        }
    }
    else
    {
        int32       j;

        /*
         * In recovery we store all xids in the subxact array because it is by
         * far the bigger array, and we mostly don't know which xids are
         * top-level and which are subxacts. The xip array is empty.
         *
         * We start by searching subtrans, if we overflowed.
         */
        if (snapshot->suboverflowed)
        {
            /* overflowed, so convert xid to top-level */
            xid = SubTransGetTopmostTransaction(xid);

            /*
             * If xid was indeed a subxact, we might now have an xid < xmin,
             * so recheck to avoid an array scan.  No point in rechecking
             * xmax.
             */
            if (TransactionIdPrecedes(xid, snapshot->xmin))
                return false;
        }

        /*
         * We now have either a top-level xid higher than xmin or an
         * indeterminate xid. We don't know whether it's top level or subxact
         * but it doesn't matter. If it's present, the xid is visible.
         */
        for (j = 0; j < snapshot->subxcnt; j++)
        {
            if (TransactionIdEquals(xid, snapshot->subxip[j]))
                return true;
        }
    }

    return false;
}


Variable Documentation

SnapshotData SnapshotAnyData = {HeapTupleSatisfiesAny}

Definition at line 73 of file tqual.c.

SnapshotData SnapshotNowData = {HeapTupleSatisfiesNow}

Definition at line 71 of file tqual.c.

SnapshotData SnapshotSelfData = {HeapTupleSatisfiesSelf}

Definition at line 72 of file tqual.c.

SnapshotData SnapshotToastData = {HeapTupleSatisfiesToast}

Definition at line 74 of file tqual.c.