aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/time
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/time')
-rw-r--r--src/backend/utils/time/snapmgr.c12
-rw-r--r--src/backend/utils/time/tqual.c90
2 files changed, 75 insertions, 27 deletions
diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index 41ff3405a39..cf3479e0640 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -19,7 +19,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/time/snapmgr.c,v 1.12 2009/10/07 16:27:18 alvherre Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/time/snapmgr.c,v 1.13 2009/12/19 01:32:37 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -224,8 +224,14 @@ CopySnapshot(Snapshot snapshot)
else
newsnap->xip = NULL;
- /* setup subXID array */
- if (snapshot->subxcnt > 0)
+ /*
+ * Setup subXID array. Don't bother to copy it if it had overflowed,
+ * though, because it's not used anywhere in that case. Except if it's
+ * a snapshot taken during recovery; all the top-level XIDs are in subxip
+ * as well in that case, so we mustn't lose them.
+ */
+ if (snapshot->subxcnt > 0 &&
+ (!snapshot->suboverflowed || snapshot->takenDuringRecovery))
{
newsnap->subxip = (TransactionId *) ((char *) newsnap + subxipoff);
memcpy(newsnap->subxip, snapshot->subxip,
diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c
index 6d8f86acc96..32eeabb9994 100644
--- a/src/backend/utils/time/tqual.c
+++ b/src/backend/utils/time/tqual.c
@@ -50,7 +50,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.113 2009/06/11 14:49:06 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.114 2009/12/19 01:32:37 sriggs Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1257,42 +1257,84 @@ XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
return true;
/*
- * 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.
+ * Snapshot information is stored slightly differently in snapshots
+ * taken during recovery.
*/
- if (snapshot->subxcnt >= 0)
+ if (!snapshot->takenDuringRecovery)
{
- /* full data, so search subxip */
- int32 j;
+ /*
+ * 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++)
+ for (j = 0; j < snapshot->subxcnt; j++)
+ {
+ if (TransactionIdEquals(xid, snapshot->subxip[j]))
+ return true;
+ }
+
+ /* not there, fall through to search xip[] */
+ }
+ else
{
- if (TransactionIdEquals(xid, snapshot->subxip[j]))
- return true;
+ /* 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;
}
- /* not there, fall through to search xip[] */
+ for (i = 0; i < snapshot->xcnt; i++)
+ {
+ if (TransactionIdEquals(xid, snapshot->xip[i]))
+ return true;
+ }
}
else
{
- /* overflowed, so convert xid to top-level */
- xid = SubTransGetTopmostTransaction(xid);
+ int32 j;
/*
- * 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.
+ * 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 (TransactionIdPrecedes(xid, snapshot->xmin))
- return false;
- }
+ if (snapshot->suboverflowed)
+ {
+ /* overflowed, so convert xid to top-level */
+ xid = SubTransGetTopmostTransaction(xid);
- for (i = 0; i < snapshot->xcnt; i++)
- {
- if (TransactionIdEquals(xid, snapshot->xip[i]))
- return true;
+ /*
+ * 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;