]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix race condition in enum value comparisons.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 1 Jul 2012 21:12:59 +0000 (17:12 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 1 Jul 2012 21:12:59 +0000 (17:12 -0400)
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
src/backend/utils/time/snapmgr.c

index b16ed6a208965becd2c28c550fc02bb8236cffb1..afbe121f7af096fef2ef75e125195473a7c856ba 100644 (file)
@@ -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)))
index ef66466baf17e6825d9d04c8bb5918aa4e59eaf6..5917b014fdcd792ea5ea37d187a3beee95c001f0 100644 (file)
@@ -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);