postgres.git / summary / log / commit / refs

commit    af4f029675ea2550f12d0b25efb4a673f5c08b08
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Sun Jul 01 21:12:59 2012 +0000
First released in: 9.3.0, 9.1.5, 9.2.0

    Fix race condition in enum value comparisons.
    
    When (re) loading the typcache comparison cache for an enum type's values,
    use an up-to-date MVCC snapshot, not the transaction's existing snapshot.
    This avoids problems if we encounter an enum OID that was created since our
    transaction started.  Per report from Andres Freund and diagnosis by Robert
    Haas.
    
    To ensure this is safe even if enum comparison manages to get invoked
    before we've set a transaction snapshot, tweak GetLatestSnapshot to
    redirect to GetTransactionSnapshot instead of throwing error when
    FirstSnapshotSet is false.  The existing uses of GetLatestSnapshot (in
    ri_triggers.c) don't care since they couldn't be invoked except in a
    transaction that's already done some work --- but it seems just conceivable
    that this might not be true of enums, especially if we ever choose to use
    enums in system catalogs.
    
    Note that the comparable coding in enum_endpoint and enum_range_internal
    remains GetTransactionSnapshot; this is perhaps debatable, but if we
    changed it those functions would have to be marked volatile, which doesn't
    seem attractive.
    
    Back-patch to 9.1 where ALTER TYPE ADD VALUE was added.


src/backend/utils/cache/typcache.c | 2 +- src/backend/utils/time/snapmgr.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c index b16ed6a2089..afbe121f7af 100644 --- a/src/backend/utils/cache/typcache.c +++ b/src/backend/utils/cache/typcache.c @@ -1021,7 +1021,7 @@ load_enum_cache_data(TypeCacheEntry *tcache) enum_rel = heap_open(EnumRelationId, AccessShareLock); enum_scan = systable_beginscan(enum_rel, EnumTypIdLabelIndexId, - true, GetTransactionSnapshot(), + true, GetLatestSnapshot(), 1, &skey); while (HeapTupleIsValid(enum_tuple = systable_getnext(enum_scan))) diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index ef66466baf1..5917b014fdc 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -167,9 +167,9 @@ GetTransactionSnapshot(void) Snapshot GetLatestSnapshot(void) { - /* Should not be first call in transaction */ + /* If first call in transaction, go ahead and set the xact snapshot */ if (!FirstSnapshotSet) - elog(ERROR, "no snapshot has been set"); + return GetTransactionSnapshot(); SecondarySnapshot = GetSnapshotData(&SecondarySnapshotData); [parent: 81aa9610373a]