mirror of
https://github.com/postgres/postgres.git
synced 2025-11-06 07:49:08 +03:00
Postgres95 1.01 Distribution - Virgin Sources
This commit is contained in:
14
src/backend/utils/time/Makefile.inc
Normal file
14
src/backend/utils/time/Makefile.inc
Normal file
@@ -0,0 +1,14 @@
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Makefile.inc--
|
||||
# Makefile for utils/time
|
||||
#
|
||||
# Copyright (c) 1994, Regents of the University of California
|
||||
#
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $Header: /cvsroot/pgsql/src/backend/utils/time/Attic/Makefile.inc,v 1.1.1.1 1996/07/09 06:22:10 scrappy Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
SUBSRCS+= tqual.c
|
||||
815
src/backend/utils/time/tqual.c
Normal file
815
src/backend/utils/time/tqual.c
Normal file
@@ -0,0 +1,815 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* tqual.c--
|
||||
* POSTGRES time qualification code.
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.1.1.1 1996/07/09 06:22:10 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* #define TQUALDEBUG 1 */
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/htup.h"
|
||||
#include "access/xact.h"
|
||||
#include "storage/bufmgr.h"
|
||||
#include "access/transam.h"
|
||||
#include "utils/elog.h"
|
||||
#include "utils/palloc.h"
|
||||
#include "utils/nabstime.h"
|
||||
|
||||
#include "utils/tqual.h"
|
||||
|
||||
/*
|
||||
* TimeQualMode --
|
||||
* Mode indicator for treatment of time qualifications.
|
||||
*/
|
||||
typedef uint16 TimeQualMode;
|
||||
|
||||
#define TimeQualAt 0x1
|
||||
#define TimeQualNewer 0x2
|
||||
#define TimeQualOlder 0x4
|
||||
#define TimeQualAll 0x8
|
||||
|
||||
#define TimeQualMask 0xf
|
||||
|
||||
#define TimeQualEvery 0x0
|
||||
#define TimeQualRange (TimeQualNewer | TimeQualOlder)
|
||||
#define TimeQualAllAt (TimeQualAt | TimeQualAll)
|
||||
|
||||
typedef struct TimeQualData {
|
||||
AbsoluteTime start;
|
||||
AbsoluteTime end;
|
||||
TimeQualMode mode;
|
||||
} TimeQualData;
|
||||
|
||||
typedef TimeQualData *InternalTimeQual;
|
||||
|
||||
static TimeQualData SelfTimeQualData;
|
||||
TimeQual SelfTimeQual = (Pointer)&SelfTimeQualData;
|
||||
|
||||
extern bool PostgresIsInitialized;
|
||||
|
||||
/*
|
||||
* XXX Transaction system override hacks start here
|
||||
*/
|
||||
#ifndef GOODAMI
|
||||
|
||||
static TransactionId HeapSpecialTransactionId = InvalidTransactionId;
|
||||
static CommandId HeapSpecialCommandId = FirstCommandId;
|
||||
|
||||
void
|
||||
setheapoverride(bool on)
|
||||
{
|
||||
if (on) {
|
||||
TransactionIdStore(GetCurrentTransactionId(),
|
||||
&HeapSpecialTransactionId);
|
||||
HeapSpecialCommandId = GetCurrentCommandId();
|
||||
} else {
|
||||
HeapSpecialTransactionId = InvalidTransactionId;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
heapisoverride()
|
||||
{
|
||||
if (!TransactionIdIsValid(HeapSpecialTransactionId)) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (!TransactionIdEquals(GetCurrentTransactionId(),
|
||||
HeapSpecialTransactionId) ||
|
||||
GetCurrentCommandId() != HeapSpecialCommandId) {
|
||||
HeapSpecialTransactionId = InvalidTransactionId;
|
||||
|
||||
return (false);
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
#endif /* !defined(GOODAMI) */
|
||||
/*
|
||||
* XXX Transaction system override hacks end here
|
||||
*/
|
||||
|
||||
static bool HeapTupleSatisfiesItself(HeapTuple tuple);
|
||||
static bool HeapTupleSatisfiesNow(HeapTuple tuple);
|
||||
static bool HeapTupleSatisfiesSnapshotInternalTimeQual(HeapTuple tuple,
|
||||
InternalTimeQual qual);
|
||||
static bool HeapTupleSatisfiesUpperBoundedInternalTimeQual(HeapTuple tuple,
|
||||
InternalTimeQual qual);
|
||||
static bool HeapTupleSatisfiesUpperUnboundedInternalTimeQual(HeapTuple tuple,
|
||||
InternalTimeQual qual);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* TimeQualIsValid --
|
||||
* True iff time qualification is valid.
|
||||
*/
|
||||
bool
|
||||
TimeQualIsValid(TimeQual qual)
|
||||
{
|
||||
bool hasStartTime;
|
||||
|
||||
if (!PointerIsValid(qual) || qual == SelfTimeQual) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
if (((InternalTimeQual)qual)->mode & ~TimeQualMask) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (((InternalTimeQual)qual)->mode & TimeQualAt) {
|
||||
return (AbsoluteTimeIsBackwardCompatiblyValid(((InternalTimeQual)qual)->start));
|
||||
}
|
||||
|
||||
hasStartTime = false;
|
||||
|
||||
if (((InternalTimeQual)qual)->mode & TimeQualNewer) {
|
||||
if (!AbsoluteTimeIsBackwardCompatiblyValid(((InternalTimeQual)qual)->start)) {
|
||||
return (false);
|
||||
}
|
||||
hasStartTime = true;
|
||||
}
|
||||
|
||||
if (((InternalTimeQual)qual)->mode & TimeQualOlder) {
|
||||
if (!AbsoluteTimeIsBackwardCompatiblyValid(((InternalTimeQual)qual)->end)) {
|
||||
return (false);
|
||||
}
|
||||
if (hasStartTime) {
|
||||
return ((bool)!AbsoluteTimeIsBefore(
|
||||
((InternalTimeQual)qual)->end,
|
||||
((InternalTimeQual)qual)->start));
|
||||
}
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* TimeQualIsLegal --
|
||||
* True iff time qualification is legal.
|
||||
* I.e., true iff time qualification does not intersects the future,
|
||||
* relative to the transaction start time.
|
||||
*
|
||||
* Note:
|
||||
* Assumes time qualification is valid.
|
||||
*/
|
||||
bool
|
||||
TimeQualIsLegal(TimeQual qual)
|
||||
{
|
||||
Assert(TimeQualIsValid(qual));
|
||||
|
||||
if (qual == NowTimeQual || qual == SelfTimeQual) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* TimeQualAt */
|
||||
if (((InternalTimeQual)qual)->mode & TimeQualAt) {
|
||||
AbsoluteTime a, b;
|
||||
|
||||
a = ((InternalTimeQual)qual)->start;
|
||||
b = GetCurrentTransactionStartTime();
|
||||
|
||||
if (AbsoluteTimeIsAfter(a, b))
|
||||
return (false);
|
||||
else
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* TimeQualOlder or TimeQualRange */
|
||||
if (((InternalTimeQual)qual)->mode & TimeQualOlder) {
|
||||
AbsoluteTime a, b;
|
||||
|
||||
a = ((InternalTimeQual)qual)->end;
|
||||
b = GetCurrentTransactionStartTime();
|
||||
|
||||
if (AbsoluteTimeIsAfter(a, b))
|
||||
return (false);
|
||||
else
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* TimeQualNewer */
|
||||
if (((InternalTimeQual)qual)->mode & TimeQualNewer) {
|
||||
AbsoluteTime a, b;
|
||||
|
||||
a = ((InternalTimeQual)qual)->start;
|
||||
b = GetCurrentTransactionStartTime();
|
||||
|
||||
if (AbsoluteTimeIsAfter(a, b))
|
||||
return (false);
|
||||
else
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* TimeQualEvery */
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* TimeQualIncludesNow --
|
||||
* True iff time qualification includes "now."
|
||||
*
|
||||
* Note:
|
||||
* Assumes time qualification is valid.
|
||||
*/
|
||||
bool
|
||||
TimeQualIncludesNow(TimeQual qual)
|
||||
{
|
||||
Assert(TimeQualIsValid(qual));
|
||||
|
||||
if (qual == NowTimeQual || qual == SelfTimeQual) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
if (((InternalTimeQual)qual)->mode & TimeQualAt) {
|
||||
return (false);
|
||||
}
|
||||
if (((InternalTimeQual)qual)->mode & TimeQualOlder &&
|
||||
!AbsoluteTimeIsAfter(
|
||||
((InternalTimeQual)qual)->end,
|
||||
GetCurrentTransactionStartTime())) {
|
||||
|
||||
return (false);
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* TimeQualIncludesPast --
|
||||
* True iff time qualification includes some time in the past.
|
||||
*
|
||||
* Note:
|
||||
* Assumes time qualification is valid.
|
||||
* XXX may not be needed?
|
||||
*/
|
||||
bool
|
||||
TimeQualIncludesPast(TimeQual qual)
|
||||
{
|
||||
Assert(TimeQualIsValid(qual));
|
||||
|
||||
if (qual == NowTimeQual || qual == SelfTimeQual) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
/* otherwise, must check archive (setting locks as appropriate) */
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* TimeQualIsSnapshot --
|
||||
* True iff time qualification is a snapshot qualification.
|
||||
*
|
||||
* Note:
|
||||
* Assumes time qualification is valid.
|
||||
*/
|
||||
bool
|
||||
TimeQualIsSnapshot(TimeQual qual)
|
||||
{
|
||||
Assert(TimeQualIsValid(qual));
|
||||
|
||||
if (qual == NowTimeQual || qual == SelfTimeQual) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
return ((bool)!!(((InternalTimeQual)qual)->mode & TimeQualAt));
|
||||
}
|
||||
|
||||
/*
|
||||
* TimeQualIsRanged --
|
||||
* True iff time qualification is a ranged qualification.
|
||||
*
|
||||
* Note:
|
||||
* Assumes time qualification is valid.
|
||||
*/
|
||||
bool
|
||||
TimeQualIsRanged(TimeQual qual)
|
||||
{
|
||||
Assert(TimeQualIsValid(qual));
|
||||
|
||||
if (qual == NowTimeQual || qual == SelfTimeQual) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
return ((bool)!(((InternalTimeQual)qual)->mode & TimeQualAt));
|
||||
}
|
||||
|
||||
/*
|
||||
* TimeQualIndicatesDisableValidityChecking --
|
||||
* True iff time qualification indicates validity checking should be
|
||||
* disabled.
|
||||
*
|
||||
* Note:
|
||||
* XXX This should not be implemented since this does not make sense.
|
||||
*/
|
||||
bool
|
||||
TimeQualIndicatesDisableValidityChecking(TimeQual qual)
|
||||
{
|
||||
Assert (TimeQualIsValid(qual));
|
||||
|
||||
if (qual == NowTimeQual || qual == SelfTimeQual) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (((InternalTimeQual)qual)->mode & TimeQualAll) {
|
||||
return (true);
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
/*
|
||||
* TimeQualGetSnapshotTime --
|
||||
* Returns time for a snapshot time qual.
|
||||
*
|
||||
* Note:
|
||||
* Assumes time qual is valid snapshot time qual.
|
||||
*/
|
||||
AbsoluteTime
|
||||
TimeQualGetSnapshotTime(TimeQual qual)
|
||||
{
|
||||
Assert(TimeQualIsSnapshot(qual));
|
||||
|
||||
return (((InternalTimeQual)qual)->start);
|
||||
}
|
||||
|
||||
/*
|
||||
* TimeQualGetStartTime --
|
||||
* Returns start time for a ranged time qual.
|
||||
*
|
||||
* Note:
|
||||
* Assumes time qual is valid ranged time qual.
|
||||
*/
|
||||
AbsoluteTime
|
||||
TimeQualGetStartTime(TimeQual qual)
|
||||
{
|
||||
Assert(TimeQualIsRanged(qual));
|
||||
|
||||
return (((InternalTimeQual)qual)->start);
|
||||
}
|
||||
|
||||
/*
|
||||
* TimeQualGetEndTime --
|
||||
* Returns end time for a ranged time qual.
|
||||
*
|
||||
* Note:
|
||||
* Assumes time qual is valid ranged time qual.
|
||||
*/
|
||||
AbsoluteTime
|
||||
TimeQualGetEndTime(TimeQual qual)
|
||||
{
|
||||
Assert(TimeQualIsRanged(qual));
|
||||
|
||||
return (((InternalTimeQual)qual)->end);
|
||||
}
|
||||
|
||||
/*
|
||||
* TimeFormSnapshotTimeQual --
|
||||
* Returns snapshot time qual for a time.
|
||||
*
|
||||
* Note:
|
||||
* Assumes time is valid.
|
||||
*/
|
||||
TimeQual
|
||||
TimeFormSnapshotTimeQual(AbsoluteTime time)
|
||||
{
|
||||
InternalTimeQual qual;
|
||||
|
||||
Assert(AbsoluteTimeIsBackwardCompatiblyValid(time));
|
||||
|
||||
qual = (InternalTimeQual)palloc(sizeof *qual);
|
||||
|
||||
qual->start = time;
|
||||
qual->end = INVALID_ABSTIME;
|
||||
qual->mode = TimeQualAt;
|
||||
|
||||
return ((TimeQual)qual);
|
||||
}
|
||||
|
||||
/*
|
||||
* TimeFormRangedTimeQual --
|
||||
* Returns ranged time qual for a pair of times.
|
||||
*
|
||||
* Note:
|
||||
* If start time is invalid, it is regarded as the epoch.
|
||||
* If end time is invalid, it is regarded as "now."
|
||||
* Assumes start time is before (or the same as) end time.
|
||||
*/
|
||||
TimeQual
|
||||
TimeFormRangedTimeQual(AbsoluteTime startTime,
|
||||
AbsoluteTime endTime)
|
||||
{
|
||||
InternalTimeQual qual;
|
||||
|
||||
qual = (InternalTimeQual)palloc(sizeof *qual);
|
||||
|
||||
qual->start = startTime;
|
||||
qual->end = endTime;
|
||||
qual->mode = TimeQualEvery;
|
||||
|
||||
if (AbsoluteTimeIsBackwardCompatiblyValid(startTime)) {
|
||||
qual->mode |= TimeQualNewer;
|
||||
}
|
||||
if (AbsoluteTimeIsBackwardCompatiblyValid(endTime)) {
|
||||
qual->mode |= TimeQualOlder;
|
||||
}
|
||||
|
||||
return ((TimeQual)qual);
|
||||
}
|
||||
|
||||
/*
|
||||
* HeapTupleSatisfiesTimeQual --
|
||||
* True iff heap tuple satsifies a time qual.
|
||||
*
|
||||
* Note:
|
||||
* Assumes heap tuple is valid.
|
||||
* Assumes time qual is valid.
|
||||
* XXX Many of the checks may be simplified and still remain correct.
|
||||
* XXX Partial answers to the checks may be cached in an ItemId.
|
||||
*/
|
||||
bool
|
||||
HeapTupleSatisfiesTimeQual(HeapTuple tuple, TimeQual qual)
|
||||
{
|
||||
/* extern TransactionId AmiTransactionId; */
|
||||
|
||||
Assert(HeapTupleIsValid(tuple));
|
||||
Assert(TimeQualIsValid(qual));
|
||||
|
||||
if (TransactionIdEquals(tuple->t_xmax, AmiTransactionId))
|
||||
return(false);
|
||||
|
||||
if (qual == SelfTimeQual || heapisoverride()) {
|
||||
return (HeapTupleSatisfiesItself(tuple));
|
||||
}
|
||||
|
||||
if (qual == NowTimeQual) {
|
||||
return (HeapTupleSatisfiesNow(tuple));
|
||||
}
|
||||
|
||||
if (!TimeQualIsLegal(qual)) {
|
||||
elog(WARN, "HeapTupleSatisfiesTimeQual: illegal time qual");
|
||||
}
|
||||
|
||||
if (TimeQualIndicatesDisableValidityChecking(qual)) {
|
||||
elog(WARN, "HeapTupleSatisfiesTimeQual: no disabled validity checking (yet)");
|
||||
}
|
||||
|
||||
if (TimeQualIsSnapshot(qual)) {
|
||||
return (HeapTupleSatisfiesSnapshotInternalTimeQual(tuple,
|
||||
(InternalTimeQual)qual));
|
||||
}
|
||||
|
||||
if (TimeQualIncludesNow(qual)) {
|
||||
return (HeapTupleSatisfiesUpperUnboundedInternalTimeQual(tuple,
|
||||
(InternalTimeQual)qual));
|
||||
}
|
||||
|
||||
return (HeapTupleSatisfiesUpperBoundedInternalTimeQual(tuple,
|
||||
(InternalTimeQual)qual));
|
||||
}
|
||||
|
||||
/*
|
||||
* HeapTupleSatisfiesItself --
|
||||
* True iff heap tuple is valid for "itself."
|
||||
*
|
||||
* Note:
|
||||
* Assumes heap tuple is valid.
|
||||
*/
|
||||
/*
|
||||
* The satisfaction of "itself" requires the following:
|
||||
*
|
||||
* ((Xmin == my-transaction && (Xmax is null [|| Xmax != my-transaction)])
|
||||
* ||
|
||||
*
|
||||
* (Xmin is committed &&
|
||||
* (Xmax is null || (Xmax != my-transaction && Xmax is not committed)))
|
||||
*/
|
||||
static bool
|
||||
HeapTupleSatisfiesItself(HeapTuple tuple)
|
||||
{
|
||||
/*
|
||||
* XXX Several evil casts are made in this routine. Casting XID to be
|
||||
* TransactionId works only because TransactionId->data is the first
|
||||
* (and only) field of the structure.
|
||||
*/
|
||||
if (!AbsoluteTimeIsBackwardCompatiblyValid(tuple->t_tmin)) {
|
||||
if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin) &&
|
||||
!TransactionIdIsValid((TransactionId)tuple->t_xmax)) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) {
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
/* the tuple was inserted validly */
|
||||
|
||||
if (AbsoluteTimeIsBackwardCompatiblyReal(tuple->t_tmax)) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (!TransactionIdIsValid((TransactionId)tuple->t_xmax)) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax)) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
return ((bool)!TransactionIdDidCommit((TransactionId)tuple->t_xmax));
|
||||
}
|
||||
|
||||
/*
|
||||
* HeapTupleSatisfiesNow --
|
||||
* True iff heap tuple is valid "now."
|
||||
*
|
||||
* Note:
|
||||
* Assumes heap tuple is valid.
|
||||
*/
|
||||
/*
|
||||
* The satisfaction of "now" requires the following:
|
||||
*
|
||||
* ((Xmin == my-transaction && Cmin != my-command &&
|
||||
* (Xmax is null || (Xmax == my-transaction && Cmax != my-command)))
|
||||
* ||
|
||||
*
|
||||
* (Xmin is committed &&
|
||||
* (Xmax is null || (Xmax == my-transaction && Cmax == my-command) ||
|
||||
* (Xmax is not committed && Xmax != my-transaction))))
|
||||
*
|
||||
* mao says 17 march 1993: the tests in this routine are correct;
|
||||
* if you think they're not, you're wrong, and you should think
|
||||
* about it again. i know, it happened to me. we don't need to
|
||||
* check commit time against the start time of this transaction
|
||||
* because 2ph locking protects us from doing the wrong thing.
|
||||
* if you mess around here, you'll break serializability. the only
|
||||
* problem with this code is that it does the wrong thing for system
|
||||
* catalog updates, because the catalogs aren't subject to 2ph, so
|
||||
* the serializability guarantees we provide don't extend to xacts
|
||||
* that do catalog accesses. this is unfortunate, but not critical.
|
||||
*/
|
||||
static bool
|
||||
HeapTupleSatisfiesNow(HeapTuple tuple)
|
||||
{
|
||||
if (AMI_OVERRIDE)
|
||||
return true;
|
||||
/*
|
||||
* If the transaction system isn't yet initialized, then we assume
|
||||
* that transactions committed. We only look at system catalogs
|
||||
* during startup, so this is less awful than it seems, but it's
|
||||
* still pretty awful.
|
||||
*/
|
||||
|
||||
if (!PostgresIsInitialized)
|
||||
return ((bool)(TransactionIdIsValid((TransactionId)tuple->t_xmin) &&
|
||||
!TransactionIdIsValid((TransactionId)tuple->t_xmax)));
|
||||
|
||||
/*
|
||||
* XXX Several evil casts are made in this routine. Casting XID to be
|
||||
* TransactionId works only because TransactionId->data is the first
|
||||
* (and only) field of the structure.
|
||||
*/
|
||||
if (!AbsoluteTimeIsBackwardCompatiblyValid(tuple->t_tmin)) {
|
||||
|
||||
if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin)
|
||||
&& CommandIdIsCurrentCommandId(tuple->t_cmin)) {
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin)
|
||||
&& !CommandIdIsCurrentCommandId(tuple->t_cmin)) {
|
||||
|
||||
if (!TransactionIdIsValid((TransactionId)tuple->t_xmax)) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
Assert(TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax));
|
||||
|
||||
if (CommandIdIsCurrentCommandId(tuple->t_cmax)) {
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* this call is VERY expensive - requires a log table lookup.
|
||||
*/
|
||||
|
||||
if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) {
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
/* by here, the inserting transaction has committed */
|
||||
if (!TransactionIdIsValid((TransactionId)tuple->t_xmax)) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax)) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (!TransactionIdDidCommit((TransactionId)tuple->t_xmax)) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
/* by here, deleting transaction has committed */
|
||||
return (false);
|
||||
}
|
||||
|
||||
/*
|
||||
* HeapTupleSatisfiesSnapshotInternalTimeQual --
|
||||
* True iff heap tuple is valid at the snapshot time qualification.
|
||||
*
|
||||
* Note:
|
||||
* Assumes heap tuple is valid.
|
||||
* Assumes internal time qualification is valid snapshot qualification.
|
||||
*/
|
||||
/*
|
||||
* The satisfaction of Rel[T] requires the following:
|
||||
*
|
||||
* (Xmin is committed && Tmin <= T &&
|
||||
* (Xmax is null || (Xmax is not committed && Xmax != my-transaction) ||
|
||||
* Tmax >= T))
|
||||
*/
|
||||
static bool
|
||||
HeapTupleSatisfiesSnapshotInternalTimeQual(HeapTuple tuple,
|
||||
InternalTimeQual qual)
|
||||
{
|
||||
/*
|
||||
* XXX Several evil casts are made in this routine. Casting XID to be
|
||||
* TransactionId works only because TransactionId->data is the first
|
||||
* (and only) field of the structure.
|
||||
*/
|
||||
if (!AbsoluteTimeIsBackwardCompatiblyValid(tuple->t_tmin)) {
|
||||
|
||||
if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
tuple->t_tmin = TransactionIdGetCommitTime(tuple->t_xmin);
|
||||
}
|
||||
|
||||
if (AbsoluteTimeIsBefore(TimeQualGetSnapshotTime((TimeQual)qual), tuple->t_tmin)) {
|
||||
return (false);
|
||||
}
|
||||
/* the tuple was inserted validly before the snapshot time */
|
||||
|
||||
if (!AbsoluteTimeIsBackwardCompatiblyReal(tuple->t_tmax)) {
|
||||
|
||||
if (!TransactionIdIsValid((TransactionId)tuple->t_xmax) ||
|
||||
!TransactionIdDidCommit((TransactionId)tuple->t_xmax)) {
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
tuple->t_tmax = TransactionIdGetCommitTime(tuple->t_xmax);
|
||||
}
|
||||
|
||||
return ((bool)
|
||||
AbsoluteTimeIsAfter(tuple->t_tmax,
|
||||
TimeQualGetSnapshotTime((TimeQual)qual)));
|
||||
}
|
||||
|
||||
/*
|
||||
* HeapTupleSatisfiesUpperBoundedInternalTimeQual --
|
||||
* True iff heap tuple is valid within a upper bounded time qualification.
|
||||
*
|
||||
* Note:
|
||||
* Assumes heap tuple is valid.
|
||||
* Assumes time qualification is valid ranged qualification with fixed
|
||||
* upper bound.
|
||||
*/
|
||||
/*
|
||||
* The satisfaction of [T1,T2] requires the following:
|
||||
*
|
||||
* (Xmin is committed && Tmin <= T2 &&
|
||||
* (Xmax is null || (Xmax is not committed && Xmax != my-transaction) ||
|
||||
* T1 is null || Tmax >= T1))
|
||||
*/
|
||||
static bool
|
||||
HeapTupleSatisfiesUpperBoundedInternalTimeQual(HeapTuple tuple,
|
||||
InternalTimeQual qual)
|
||||
{
|
||||
/*
|
||||
* XXX Several evil casts are made in this routine. Casting XID to be
|
||||
* TransactionId works only because TransactionId->data is the first
|
||||
* (and only) field of the structure.
|
||||
*/
|
||||
if (!AbsoluteTimeIsBackwardCompatiblyValid(tuple->t_tmin)) {
|
||||
|
||||
if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
tuple->t_tmin = TransactionIdGetCommitTime(tuple->t_xmin);
|
||||
}
|
||||
|
||||
if (AbsoluteTimeIsBefore(TimeQualGetEndTime((TimeQual)qual), tuple->t_tmin)) {
|
||||
return (false);
|
||||
}
|
||||
/* the tuple was inserted validly before the range end */
|
||||
|
||||
if (!AbsoluteTimeIsBackwardCompatiblyValid(TimeQualGetStartTime((TimeQual)qual))) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
if (!AbsoluteTimeIsBackwardCompatiblyReal(tuple->t_tmax)) {
|
||||
|
||||
if (!TransactionIdIsValid((TransactionId)tuple->t_xmax) ||
|
||||
!TransactionIdDidCommit((TransactionId)tuple->t_xmax)) {
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
tuple->t_tmax = TransactionIdGetCommitTime(tuple->t_xmax);
|
||||
}
|
||||
|
||||
return ((bool)AbsoluteTimeIsAfter(tuple->t_tmax,
|
||||
TimeQualGetStartTime((TimeQual)qual)));
|
||||
}
|
||||
|
||||
/*
|
||||
* HeapTupleSatisfiesUpperUnboundedInternalTimeQual --
|
||||
* True iff heap tuple is valid within a upper bounded time qualification.
|
||||
*
|
||||
* Note:
|
||||
* Assumes heap tuple is valid.
|
||||
* Assumes time qualification is valid ranged qualification with no
|
||||
* upper bound.
|
||||
*/
|
||||
/*
|
||||
* The satisfaction of [T1,] requires the following:
|
||||
*
|
||||
* ((Xmin == my-transaction && Cmin != my-command &&
|
||||
* (Xmax is null || (Xmax == my-transaction && Cmax != my-command)))
|
||||
* ||
|
||||
*
|
||||
* (Xmin is committed &&
|
||||
* (Xmax is null || (Xmax == my-transaction && Cmax == my-command) ||
|
||||
* (Xmax is not committed && Xmax != my-transaction) ||
|
||||
* T1 is null || Tmax >= T1)))
|
||||
*/
|
||||
static bool
|
||||
HeapTupleSatisfiesUpperUnboundedInternalTimeQual(HeapTuple tuple,
|
||||
InternalTimeQual qual)
|
||||
{
|
||||
if (!AbsoluteTimeIsBackwardCompatiblyValid(tuple->t_tmin)) {
|
||||
|
||||
if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin) &&
|
||||
CommandIdIsCurrentCommandId(tuple->t_cmin)) {
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin) &&
|
||||
!CommandIdIsCurrentCommandId(tuple->t_cmin)) {
|
||||
|
||||
if (!TransactionIdIsValid((TransactionId)tuple->t_xmax)) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
Assert(TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax));
|
||||
|
||||
return ((bool) !CommandIdIsCurrentCommandId(tuple->t_cmax));
|
||||
}
|
||||
|
||||
if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
tuple->t_tmin = TransactionIdGetCommitTime(tuple->t_xmin);
|
||||
}
|
||||
/* the tuple was inserted validly */
|
||||
|
||||
if (!AbsoluteTimeIsBackwardCompatiblyValid(TimeQualGetStartTime((TimeQual)qual))) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
if (!AbsoluteTimeIsBackwardCompatiblyReal(tuple->t_tmax)) {
|
||||
|
||||
if (!TransactionIdIsValid((TransactionId)tuple->t_xmax)) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax)) {
|
||||
return (CommandIdIsCurrentCommandId(tuple->t_cmin));
|
||||
}
|
||||
|
||||
if (!TransactionIdDidCommit((TransactionId)tuple->t_xmax)) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
tuple->t_tmax = TransactionIdGetCommitTime(tuple->t_xmax);
|
||||
}
|
||||
|
||||
return ((bool)AbsoluteTimeIsAfter(tuple->t_tmax,
|
||||
TimeQualGetStartTime((TimeQual)qual)));
|
||||
}
|
||||
Reference in New Issue
Block a user