/* t_xmin status = ABORTED */ Rule 1: IF t_xmin status is 'ABORTED' THEN RETURN 'Invisible' END IF /* t_xmin status = IN_PROGRESS */ IF t_xmin status is 'IN_PROGRESS' THEN IF t_xmin = current_txid THEN Rule 2: IF t_xmax = INVALID THEN RETURN 'Visible' Rule 3: ELSE /* this tuple has been deleted or updated by the current transaction itself. */ RETURN 'Invisible' END IF Rule 4: ELSE /* t_xmin ≠ current_txid */ RETURN 'Invisible' END IF END IF /* t_xmin status = COMMITTED */ IF t_xmin status is 'COMMITTED' THEN Rule 5: IF t_xmin is active in the obtained transaction snapshot THEN RETURN 'Invisible' Rule 6: ELSE IF t_xmax = INVALID OR status of t_xmax is 'ABORTED' THEN RETURN 'Visible' ELSE IF t_xmax status is 'IN_PROGRESS' THEN Rule 7: IF t_xmax = current_txid THEN RETURN 'Invisible' Rule 8: ELSE /* t_xmax ≠ current_txid */ RETURN 'Visible' END IF ELSE IF t_xmax status is 'COMMITTED' THEN Rule 9: IF t_xmax is active in the obtained transaction snapshot THEN RETURN 'Visible' Rule 10: ELSE RETURN 'Invisible' END IF END IF END IF
Snapshot GetTransactionSnapshot(void) { /* * Return historic snapshot if doing logical decoding. We'll never need a * non-historic transaction snapshot in this (sub-)transaction, so there's * no need to be careful to set one up for later calls to * GetTransactionSnapshot(). */ if (HistoricSnapshotActive()) { Assert(!FirstSnapshotSet); return HistoricSnapshot; }
/* First call in transaction? */ if (!FirstSnapshotSet) { /* * Don't allow catalog snapshot to be older than xact snapshot. Must * do this first to allow the empty-heap Assert to succeed. */ InvalidateCatalogSnapshot();
if (IsInParallelMode()) elog(ERROR, "cannot take query snapshot during a parallel operation");
/* * In transaction-snapshot mode, the first snapshot must live until * end of xact regardless of what the caller does with it, so we must * make a copy of it rather than returning CurrentSnapshotData * directly. Furthermore, if we're running in serializable mode, * predicate.c needs to wrap the snapshot fetch in its own processing. */ if (IsolationUsesXactSnapshot()) { /* First, create the snapshot in CurrentSnapshotData */ if (IsolationIsSerializable()) CurrentSnapshot = GetSerializableTransactionSnapshot(&CurrentSnapshotData); else CurrentSnapshot = GetSnapshotData(&CurrentSnapshotData); /* Make a saved copy */ CurrentSnapshot = CopySnapshot(CurrentSnapshot); FirstXactSnapshot = CurrentSnapshot; /* Mark it as "registered" in FirstXactSnapshot */ FirstXactSnapshot->regd_count++; pairingheap_add(&RegisteredSnapshots, &FirstXactSnapshot->ph_node); } else CurrentSnapshot = GetSnapshotData(&CurrentSnapshotData);