tqual.c

来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 1,436 行 · 第 1/3 页

C
1,436
字号
/* * HeapTupleSatisfiesAny *		Dummy "satisfies" routine: any tuple satisfies SnapshotAny. */boolHeapTupleSatisfiesAny(HeapTupleHeader tuple, Snapshot snapshot, Buffer buffer){	return true;}/* * HeapTupleSatisfiesToast *		True iff heap tuple is valid as a TOAST row. * * This is a simplified version that only checks for VACUUM moving conditions. * It's appropriate for TOAST usage because TOAST really doesn't want to do * its own time qual checks; if you can see the main table row that contains * a TOAST reference, you should be able to see the TOASTed value.	However, * vacuuming a TOAST table is independent of the main table, and in case such * a vacuum fails partway through, we'd better do this much checking. * * Among other things, this means you can't do UPDATEs of rows in a TOAST * table. */boolHeapTupleSatisfiesToast(HeapTupleHeader tuple, Snapshot snapshot,						Buffer buffer){	if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))	{		if (tuple->t_infomask & HEAP_XMIN_INVALID)			return false;		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);			}		}		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;}/* * HeapTupleSatisfiesUpdate * *	Same logic as HeapTupleSatisfiesNow, but returns a more detailed result *	code, since UPDATE needs to know more than "is it visible?".  Also, *	tuples of my own xact are tested against the passed CommandId not *	CurrentCommandId. * *	The possible return codes are: * *	HeapTupleInvisible: the tuple didn't exist at all when the scan started, *	e.g. it was created by a later CommandId. * *	HeapTupleMayBeUpdated: The tuple is valid and visible, so it may be *	updated. * *	HeapTupleSelfUpdated: The tuple was updated by the current transaction, *	after the current scan started. * *	HeapTupleUpdated: The tuple was updated by a committed transaction. * *	HeapTupleBeingUpdated: The tuple is being updated by an in-progress *	transaction other than the current transaction.  (Note: this includes *	the case where the tuple is share-locked by a MultiXact, even if the *	MultiXact includes the current transaction.  Callers that want to *	distinguish that case must test for it themselves.) */HTSU_ResultHeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,						 Buffer buffer){	if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))	{		if (tuple->t_infomask & HEAP_XMIN_INVALID)			return HeapTupleInvisible;		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);			}		}		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 (tuple->t_infomask & HEAP_IS_LOCKED)		/* not deleter */				return HeapTupleMayBeUpdated;			Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI));			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(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 (tuple->t_infomask & HEAP_IS_LOCKED)			return HeapTupleMayBeUpdated;		return HeapTupleUpdated;	/* updated by other */	}	if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)	{		/* MultiXacts are currently only allowed to lock tuples */		Assert(tuple->t_infomask & HEAP_IS_LOCKED);		if (MultiXactIdIsRunning(HeapTupleHeaderGetXmax(tuple)))			return HeapTupleBeingUpdated;		SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,					InvalidTransactionId);		return HeapTupleMayBeUpdated;	}	if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))	{		if (tuple->t_infomask & HEAP_IS_LOCKED)			return HeapTupleMayBeUpdated;		if (HeapTupleHeaderGetCmax(tuple) >= curcid)			return HeapTupleSelfUpdated;		/* updated after scan started */		else			return HeapTupleInvisible;	/* updated before scan started */	}	if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))		return HeapTupleBeingUpdated;	if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))	{		/* it must have aborted or crashed */		SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,					InvalidTransactionId);		return HeapTupleMayBeUpdated;	}	/* xmax transaction committed */	if (tuple->t_infomask & HEAP_IS_LOCKED)	{		SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,					InvalidTransactionId);		return HeapTupleMayBeUpdated;	}	SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,				HeapTupleHeaderGetXmax(tuple));	return HeapTupleUpdated;	/* updated by other */}/* * HeapTupleSatisfiesDirty *		True iff heap tuple is valid including effects of open transactions. * *	Here, we consider the effects of: *		all committed and in-progress transactions (as of the current instant) *		previous commands of this transaction *		changes made by the current command * * This is essentially like HeapTupleSatisfiesSelf as far as effects of * the current transaction and committed/aborted xacts are concerned. * However, we also include the effects of other xacts still in progress. * * A special hack is that the passed-in snapshot struct is used as an * output argument to return the xids of concurrent xacts that affected the * tuple.  snapshot->xmin is set to the tuple's xmin if that is another * transaction that's still in progress; or to InvalidTransactionId if the * tuple's xmin is committed good, committed dead, or my own xact.  Similarly * for snapshot->xmax and the tuple's xmax. */boolHeapTupleSatisfiesDirty(HeapTupleHeader tuple, Snapshot snapshot,						Buffer buffer){	snapshot->xmin = snapshot->xmax = InvalidTransactionId;	if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))	{		if (tuple->t_infomask & HEAP_XMIN_INVALID)			return false;		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);			}		}		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 (tuple->t_infomask & HEAP_IS_LOCKED)		/* not deleter */				return true;			Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI));			if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(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 (tuple->t_infomask & HEAP_IS_LOCKED)			return true;		return false;			/* updated by other */	}	if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)	{		/* MultiXacts are currently only allowed to lock tuples */		Assert(tuple->t_infomask & HEAP_IS_LOCKED);		return true;	}	if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))	{		if (tuple->t_infomask & HEAP_IS_LOCKED)			return true;		return false;	}	if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))	{		snapshot->xmax = HeapTupleHeaderGetXmax(tuple);		return true;	}	if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))	{		/* it must have aborted or crashed */		SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,					InvalidTransactionId);		return true;	}	/* xmax transaction committed */	if (tuple->t_infomask & HEAP_IS_LOCKED)	{		SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,					InvalidTransactionId);		return true;	}	SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,				HeapTupleHeaderGetXmax(tuple));	return false;				/* updated by other */}/* * HeapTupleSatisfiesMVCC *		True iff heap tuple is valid for the given MVCC snapshot. * *	Here, we consider the effects of: *		all transactions committed as of the time of the given snapshot *		previous commands of this transaction * *	Does _not_ include: *		transactions shown as in-progress by the 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.) */boolHeapTupleSatisfiesMVCC(HeapTupleHeader tuple, Snapshot snapshot,					   Buffer buffer){	if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))	{		if (tuple->t_infomask & HEAP_XMIN_INVALID)			return false;		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);			}		}		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)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?